Skip to content

Commit 3088ca0

Browse files
committed
Take substitutions into account.
1 parent e16f413 commit 3088ca0

File tree

3 files changed

+33
-14
lines changed

3 files changed

+33
-14
lines changed

crates/hir_ty/src/diagnostics/match_check.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ pub(crate) struct Pat {
3939
}
4040

4141
impl Pat {
42-
pub(crate) fn wildcard_from_ty(ty: &Ty) -> Self {
43-
Pat { ty: ty.clone(), kind: Box::new(PatKind::Wild) }
42+
pub(crate) fn wildcard_from_ty(ty: Ty) -> Self {
43+
Pat { ty, kind: Box::new(PatKind::Wild) }
4444
}
4545
}
4646

@@ -1145,6 +1145,22 @@ fn main() {
11451145
);
11461146
}
11471147

1148+
#[test]
1149+
fn pattern_type_is_of_substitution() {
1150+
cov_mark::check!(match_check_wildcard_expanded_to_substitutions);
1151+
check_diagnostics(
1152+
r#"
1153+
struct Foo<T>(T);
1154+
struct Bar;
1155+
fn main() {
1156+
match Foo(Bar) {
1157+
_ | Foo(Bar) => {}
1158+
}
1159+
}
1160+
"#,
1161+
);
1162+
}
1163+
11481164
mod false_negatives {
11491165
//! The implementation of match checking here is a work in progress. As we roll this out, we
11501166
//! prefer false negatives to false positives (ideally there would be no false positives). This

crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -632,10 +632,7 @@ impl Fields {
632632
}
633633

634634
/// Convenience; internal use.
635-
fn wildcards_from_tys<'a>(
636-
cx: &MatchCheckCtx<'_>,
637-
tys: impl IntoIterator<Item = &'a Ty>,
638-
) -> Self {
635+
fn wildcards_from_tys(cx: &MatchCheckCtx<'_>, tys: impl IntoIterator<Item = Ty>) -> Self {
639636
let wilds = tys.into_iter().map(Pat::wildcard_from_ty);
640637
let pats = wilds.map(|pat| cx.alloc_pat(pat)).collect();
641638
Fields::Vec(pats)
@@ -645,13 +642,13 @@ impl Fields {
645642
pub(crate) fn wildcards(pcx: PatCtxt<'_>, constructor: &Constructor) -> Self {
646643
let ty = pcx.ty;
647644
let cx = pcx.cx;
648-
let wildcard_from_ty = |ty| cx.alloc_pat(Pat::wildcard_from_ty(ty));
645+
let wildcard_from_ty = |ty: &Ty| cx.alloc_pat(Pat::wildcard_from_ty(ty.clone()));
649646

650647
let ret = match constructor {
651648
Single | Variant(_) => match ty.kind(&Interner) {
652649
TyKind::Tuple(_, substs) => {
653650
let tys = substs.iter(&Interner).map(|ty| ty.assert_ty_ref(&Interner));
654-
Fields::wildcards_from_tys(cx, tys)
651+
Fields::wildcards_from_tys(cx, tys.cloned())
655652
}
656653
TyKind::Ref(.., rty) => Fields::from_single_pattern(wildcard_from_ty(rty)),
657654
&TyKind::Adt(AdtId(adt), ref substs) => {
@@ -666,14 +663,20 @@ impl Fields {
666663
// Whether we must not match the fields of this variant exhaustively.
667664
let is_non_exhaustive =
668665
is_field_list_non_exhaustive(variant_id, cx) && !adt_is_local;
669-
let field_ty_arena = cx.db.field_types(variant_id);
670-
let field_tys =
671-
|| field_ty_arena.iter().map(|(_, binders)| binders.skip_binders());
666+
667+
cov_mark::hit!(match_check_wildcard_expanded_to_substitutions);
668+
let field_ty_data = cx.db.field_types(variant_id);
669+
let field_tys = || {
670+
field_ty_data
671+
.iter()
672+
.map(|(_, binders)| binders.clone().substitute(&Interner, substs))
673+
};
674+
672675
// In the following cases, we don't need to filter out any fields. This is
673676
// the vast majority of real cases, since uninhabited fields are uncommon.
674677
let has_no_hidden_fields = (matches!(adt, hir_def::AdtId::EnumId(_))
675678
&& !is_non_exhaustive)
676-
|| !field_tys().any(|ty| cx.is_uninhabited(ty));
679+
|| !field_tys().any(|ty| cx.is_uninhabited(&ty));
677680

678681
if has_no_hidden_fields {
679682
Fields::wildcards_from_tys(cx, field_tys())
@@ -759,7 +762,7 @@ impl Fields {
759762
FloatRange(..) => UNHANDLED,
760763
Constructor::IntRange(_) => UNHANDLED,
761764
NonExhaustive => PatKind::Wild,
762-
Wildcard => return Pat::wildcard_from_ty(pcx.ty),
765+
Wildcard => return Pat::wildcard_from_ty(pcx.ty.clone()),
763766
Opaque => pcx.cx.bug("we should not try to apply an opaque constructor"),
764767
Missing => pcx.cx.bug(
765768
"trying to apply the `Missing` constructor;\

crates/hir_ty/src/diagnostics/match_check/usefulness.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,7 @@ pub(crate) fn compute_match_usefulness(
11521152
.collect();
11531153

11541154
let wild_pattern =
1155-
cx.pattern_arena.borrow_mut().alloc(Pat::wildcard_from_ty(&cx.infer[cx.match_expr]));
1155+
cx.pattern_arena.borrow_mut().alloc(Pat::wildcard_from_ty(cx.infer[cx.match_expr].clone()));
11561156
let v = PatStack::from_pattern(wild_pattern);
11571157
let usefulness = is_useful(cx, &matrix, &v, ConstructWitness, false, true);
11581158
let non_exhaustiveness_witnesses = match usefulness {

0 commit comments

Comments
 (0)