Skip to content

Commit 9cd3f1c

Browse files
committed
Auto merge of #72506 - Nadrieril:fix-72476, r=matthewjasper
Exhaustiveness checking: work around type normalization issues This should resolve #72476 and probably #72467. This is a bit hacky but that's actually what the code was doing before #71930. I'm essentially reverting e5a2cd5. So despite being hacky, it's been tried and tested (so much so that code relies on it now x)). Only the third commit does anything interesting.
2 parents 255c033 + 3e8ba3a commit 9cd3f1c

File tree

2 files changed

+52
-19
lines changed

2 files changed

+52
-19
lines changed

Diff for: src/librustc_mir_build/hair/pattern/_match.rs

+30-19
Original file line numberDiff line numberDiff line change
@@ -1025,11 +1025,11 @@ enum Fields<'p, 'tcx> {
10251025
/// have not measured if it really made a difference.
10261026
Slice(&'p [Pat<'tcx>]),
10271027
Vec(SmallVec<[&'p Pat<'tcx>; 2]>),
1028-
/// Patterns where some of the fields need to be hidden. `len` caches the number of non-hidden
1029-
/// fields.
1028+
/// Patterns where some of the fields need to be hidden. `kept_count` caches the number of
1029+
/// non-hidden fields.
10301030
Filtered {
10311031
fields: SmallVec<[FilteredField<'p, 'tcx>; 2]>,
1032-
len: usize,
1032+
kept_count: usize,
10331033
},
10341034
}
10351035

@@ -1066,10 +1066,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
10661066
constructor: &Constructor<'tcx>,
10671067
ty: Ty<'tcx>,
10681068
) -> Self {
1069-
debug!("Fields::wildcards({:#?}, {:?})", constructor, ty);
10701069
let wildcard_from_ty = |ty| &*cx.pattern_arena.alloc(Pat::wildcard_from_ty(ty));
10711070

1072-
match constructor {
1071+
let ret = match constructor {
10731072
Single | Variant(_) => match ty.kind {
10741073
ty::Tuple(ref fs) => {
10751074
Fields::wildcards_from_tys(cx, fs.into_iter().map(|ty| ty.expect_ty()))
@@ -1093,7 +1092,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
10931092
if has_no_hidden_fields {
10941093
Fields::wildcards_from_tys(cx, field_tys)
10951094
} else {
1096-
let mut len = 0;
1095+
let mut kept_count = 0;
10971096
let fields = variant
10981097
.fields
10991098
.iter()
@@ -1110,12 +1109,12 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11101109
if is_uninhabited && (!is_visible || is_non_exhaustive) {
11111110
FilteredField::Hidden(ty)
11121111
} else {
1113-
len += 1;
1112+
kept_count += 1;
11141113
FilteredField::Kept(wildcard_from_ty(ty))
11151114
}
11161115
})
11171116
.collect();
1118-
Fields::Filtered { fields, len }
1117+
Fields::Filtered { fields, kept_count }
11191118
}
11201119
}
11211120
}
@@ -1129,14 +1128,19 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11291128
_ => bug!("bad slice pattern {:?} {:?}", constructor, ty),
11301129
},
11311130
ConstantValue(..) | FloatRange(..) | IntRange(..) | NonExhaustive => Fields::empty(),
1132-
}
1131+
};
1132+
debug!("Fields::wildcards({:?}, {:?}) = {:#?}", constructor, ty, ret);
1133+
ret
11331134
}
11341135

1136+
/// Returns the number of patterns from the viewpoint of match-checking, i.e. excluding hidden
1137+
/// fields. This is what we want in most cases in this file, the only exception being
1138+
/// conversion to/from `Pat`.
11351139
fn len(&self) -> usize {
11361140
match self {
11371141
Fields::Slice(pats) => pats.len(),
11381142
Fields::Vec(pats) => pats.len(),
1139-
Fields::Filtered { len, .. } => *len,
1143+
Fields::Filtered { kept_count, .. } => *kept_count,
11401144
}
11411145
}
11421146

@@ -1206,7 +1210,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
12061210
let pats: &[_] = cx.pattern_arena.alloc_from_iter(pats);
12071211

12081212
match self {
1209-
Fields::Filtered { fields, len } => {
1213+
Fields::Filtered { fields, kept_count } => {
12101214
let mut pats = pats.iter();
12111215
let mut fields = fields.clone();
12121216
for f in &mut fields {
@@ -1215,7 +1219,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
12151219
*p = pats.next().unwrap();
12161220
}
12171221
}
1218-
Fields::Filtered { fields, len: *len }
1222+
Fields::Filtered { fields, kept_count: *kept_count }
12191223
}
12201224
_ => Fields::Slice(pats),
12211225
}
@@ -1866,11 +1870,13 @@ crate fn is_useful<'p, 'tcx>(
18661870
return if any_is_useful { Useful(unreachable_pats) } else { NotUseful };
18671871
}
18681872

1869-
let pcx = PatCtxt { ty: v.head().ty, span: v.head().span };
1873+
// FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).
1874+
let ty = matrix.heads().next().map(|r| r.ty).unwrap_or(v.head().ty);
1875+
let pcx = PatCtxt { ty, span: v.head().span };
18701876

18711877
debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v.head());
18721878

1873-
if let Some(constructor) = pat_constructor(cx.tcx, cx.param_env, v.head()) {
1879+
let ret = if let Some(constructor) = pat_constructor(cx.tcx, cx.param_env, v.head()) {
18741880
debug!("is_useful - expanding constructor: {:#?}", constructor);
18751881
split_grouped_constructors(
18761882
cx.tcx,
@@ -1901,11 +1907,11 @@ crate fn is_useful<'p, 'tcx>(
19011907

19021908
let used_ctors: Vec<Constructor<'_>> =
19031909
matrix.heads().filter_map(|p| pat_constructor(cx.tcx, cx.param_env, p)).collect();
1904-
debug!("used_ctors = {:#?}", used_ctors);
1910+
debug!("is_useful_used_ctors = {:#?}", used_ctors);
19051911
// `all_ctors` are all the constructors for the given type, which
19061912
// should all be represented (or caught with the wild pattern `_`).
19071913
let all_ctors = all_constructors(cx, pcx);
1908-
debug!("all_ctors = {:#?}", all_ctors);
1914+
debug!("is_useful_all_ctors = {:#?}", all_ctors);
19091915

19101916
// `missing_ctors` is the set of constructors from the same type as the
19111917
// first column of `matrix` that are matched only by wildcard patterns
@@ -1920,7 +1926,7 @@ crate fn is_useful<'p, 'tcx>(
19201926
// can be big.
19211927
let missing_ctors = MissingConstructors::new(all_ctors, used_ctors);
19221928

1923-
debug!("missing_ctors.empty()={:#?}", missing_ctors.is_empty(),);
1929+
debug!("is_useful_missing_ctors.empty()={:#?}", missing_ctors.is_empty(),);
19241930

19251931
if missing_ctors.is_empty() {
19261932
let (all_ctors, _) = missing_ctors.into_inner();
@@ -1988,7 +1994,9 @@ crate fn is_useful<'p, 'tcx>(
19881994
usefulness.apply_missing_ctors(cx, pcx.ty, &missing_ctors)
19891995
}
19901996
}
1991-
}
1997+
};
1998+
debug!("is_useful::returns({:#?}, {:#?}) = {:?}", matrix, v, ret);
1999+
ret
19922000
}
19932001

19942002
/// A shorthand for the `U(S(c, P), S(c, q))` operation from the paper. I.e., `is_useful` applied
@@ -2647,7 +2655,10 @@ fn specialize_one_pattern<'p, 'tcx>(
26472655

26482656
PatKind::Or { .. } => bug!("Or-pattern should have been expanded earlier on."),
26492657
};
2650-
debug!("specialize({:#?}, {:#?}) = {:#?}", pat, ctor_wild_subpatterns, result);
2658+
debug!(
2659+
"specialize({:#?}, {:#?}, {:#?}) = {:#?}",
2660+
pat, constructor, ctor_wild_subpatterns, result
2661+
);
26512662

26522663
result
26532664
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// check-pass
2+
3+
// From https://github.com/rust-lang/rust/issues/72476
4+
5+
trait A {
6+
type Projection;
7+
}
8+
9+
impl A for () {
10+
type Projection = bool;
11+
}
12+
13+
struct Next<T: A>(T::Projection);
14+
15+
fn f(item: Next<()>) {
16+
match item {
17+
Next(true) => {}
18+
Next(false) => {}
19+
}
20+
}
21+
22+
fn main() {}

0 commit comments

Comments
 (0)