Skip to content

hir_ty::match_check cleanup: remove special handling for box patterns #20175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions crates/hir-ty/src/diagnostics/match_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ use crate::{
db::HirDatabase,
display::{HirDisplay, HirDisplayError, HirFormatter},
infer::BindingMode,
lang_items::is_box,
};

use self::pat_util::EnumerateAndAdjustIterator;
Expand Down Expand Up @@ -77,7 +76,7 @@ pub(crate) enum PatKind {
subpatterns: Vec<FieldPat>,
},

/// `box P`, `&P`, `&mut P`, etc.
/// `&P`, `&mut P`, etc.
Deref {
subpattern: Pat,
},
Expand Down Expand Up @@ -406,7 +405,6 @@ impl HirDisplay for Pat {
}
PatKind::Deref { subpattern } => {
match self.ty.kind(Interner) {
TyKind::Adt(adt, _) if is_box(f.db, adt.0) => write!(f, "box ")?,
&TyKind::Ref(mutbl, ..) => {
write!(f, "&{}", if mutbl == Mutability::Mut { "mut " } else { "" })?
}
Expand Down
76 changes: 19 additions & 57 deletions crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{
inhabitedness::{is_enum_variant_uninhabited_from, is_ty_uninhabited_from},
};

use super::{FieldPat, Pat, PatKind, is_box};
use super::{FieldPat, Pat, PatKind};

use Constructor::*;

Expand Down Expand Up @@ -170,8 +170,6 @@ impl<'db> MatchCheckCtx<'db> {
}
PatKind::Deref { subpattern } => {
ctor = match pat.ty.kind(Interner) {
// This is a box pattern.
TyKind::Adt(adt, _) if is_box(self.db, adt.0) => Struct,
TyKind::Ref(..) => Ref,
_ => {
never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty);
Expand All @@ -194,23 +192,6 @@ impl<'db> MatchCheckCtx<'db> {
ctor = Struct;
arity = substs.len(Interner);
}
TyKind::Adt(adt, _) if is_box(self.db, adt.0) => {
// The only legal patterns of type `Box` (outside `std`) are `_` and box
// patterns. If we're here we can assume this is a box pattern.
// FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_,
// _)` or a box pattern. As a hack to avoid an ICE with the former, we
// ignore other fields than the first one. This will trigger an error later
// anyway.
// See https://github.com/rust-lang/rust/issues/82772 ,
// explanation: https://github.com/rust-lang/rust/pull/82789#issuecomment-796921977
// The problem is that we can't know from the type whether we'll match
// normally or through box-patterns. We'll have to figure out a proper
// solution when we introduce generalized deref patterns. Also need to
// prevent mixing of those two options.
fields.retain(|ipat| ipat.idx == 0);
ctor = Struct;
arity = 1;
}
&TyKind::Adt(AdtId(adt), _) => {
ctor = match pat.kind.as_ref() {
PatKind::Leaf { .. } if matches!(adt, hir_def::AdtId::UnionId(_)) => {
Expand Down Expand Up @@ -277,12 +258,6 @@ impl<'db> MatchCheckCtx<'db> {
})
.collect(),
},
TyKind::Adt(adt, _) if is_box(self.db, adt.0) => {
// Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside
// of `std`). So this branch is only reachable when the feature is enabled and
// the pattern is a box pattern.
PatKind::Deref { subpattern: subpatterns.next().unwrap() }
}
TyKind::Adt(adt, substs) => {
let variant = Self::variant_id_for_adt(self.db, pat.ctor(), adt.0).unwrap();
let subpatterns = self
Expand Down Expand Up @@ -343,14 +318,8 @@ impl PatCx for MatchCheckCtx<'_> {
Struct | Variant(_) | UnionField => match *ty.kind(Interner) {
TyKind::Tuple(arity, ..) => arity,
TyKind::Adt(AdtId(adt), ..) => {
if is_box(self.db, adt) {
// The only legal patterns of type `Box` (outside `std`) are `_` and box
// patterns. If we're here we can assume this is a box pattern.
1
} else {
let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
variant.fields(self.db).fields().len()
}
let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
variant.fields(self.db).fields().len()
}
_ => {
never!("Unexpected type for `Single` constructor: {:?}", ty);
Expand Down Expand Up @@ -383,29 +352,22 @@ impl PatCx for MatchCheckCtx<'_> {
tys.cloned().map(|ty| (ty, PrivateUninhabitedField(false))).collect()
}
TyKind::Ref(.., rty) => single(rty.clone()),
&TyKind::Adt(AdtId(adt), ref substs) => {
if is_box(self.db, adt) {
// The only legal patterns of type `Box` (outside `std`) are `_` and box
// patterns. If we're here we can assume this is a box pattern.
let subst_ty = substs.at(Interner, 0).assert_ty_ref(Interner).clone();
single(subst_ty)
} else {
let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();

let visibilities = LazyCell::new(|| self.db.field_visibilities(variant));

self.list_variant_fields(ty, variant)
.map(move |(fid, ty)| {
let is_visible = || {
matches!(adt, hir_def::AdtId::EnumId(..))
|| visibilities[fid].is_visible_from(self.db, self.module)
};
let is_uninhabited = self.is_uninhabited(&ty);
let private_uninhabited = is_uninhabited && !is_visible();
(ty, PrivateUninhabitedField(private_uninhabited))
})
.collect()
}
&TyKind::Adt(AdtId(adt), ..) => {
let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();

let visibilities = LazyCell::new(|| self.db.field_visibilities(variant));

self.list_variant_fields(ty, variant)
.map(move |(fid, ty)| {
let is_visible = || {
matches!(adt, hir_def::AdtId::EnumId(..))
|| visibilities[fid].is_visible_from(self.db, self.module)
};
let is_uninhabited = self.is_uninhabited(&ty);
let private_uninhabited = is_uninhabited && !is_visible();
(ty, PrivateUninhabitedField(private_uninhabited))
})
.collect()
}
ty_kind => {
never!("Unexpected type for `{:?}` constructor: {:?}", ctor, ty_kind);
Expand Down