From b7cfb6a9ac1b59f62cfce2be6d09e45557af84d5 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 23 May 2020 13:11:28 +0100 Subject: [PATCH 1/4] Improve debugging --- src/librustc_mir_build/hair/pattern/_match.rs | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 626e531c807b7..928d1f6a68abc 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -1066,10 +1066,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { constructor: &Constructor<'tcx>, ty: Ty<'tcx>, ) -> Self { - debug!("Fields::wildcards({:#?}, {:?})", constructor, ty); let wildcard_from_ty = |ty| &*cx.pattern_arena.alloc(Pat::wildcard_from_ty(ty)); - match constructor { + let ret = match constructor { Single | Variant(_) => match ty.kind { ty::Tuple(ref fs) => { Fields::wildcards_from_tys(cx, fs.into_iter().map(|ty| ty.expect_ty())) @@ -1129,7 +1128,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { _ => bug!("bad slice pattern {:?} {:?}", constructor, ty), }, ConstantValue(..) | FloatRange(..) | IntRange(..) | NonExhaustive => Fields::empty(), - } + }; + debug!("Fields::wildcards({:?}, {:?}) = {:#?}", constructor, ty, ret); + ret } fn len(&self) -> usize { @@ -1870,7 +1871,7 @@ crate fn is_useful<'p, 'tcx>( debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v.head()); - if let Some(constructor) = pat_constructor(cx.tcx, cx.param_env, v.head()) { + let ret = if let Some(constructor) = pat_constructor(cx.tcx, cx.param_env, v.head()) { debug!("is_useful - expanding constructor: {:#?}", constructor); split_grouped_constructors( cx.tcx, @@ -1901,11 +1902,11 @@ crate fn is_useful<'p, 'tcx>( let used_ctors: Vec> = matrix.heads().filter_map(|p| pat_constructor(cx.tcx, cx.param_env, p)).collect(); - debug!("used_ctors = {:#?}", used_ctors); + debug!("is_useful_used_ctors = {:#?}", used_ctors); // `all_ctors` are all the constructors for the given type, which // should all be represented (or caught with the wild pattern `_`). let all_ctors = all_constructors(cx, pcx); - debug!("all_ctors = {:#?}", all_ctors); + debug!("is_useful_all_ctors = {:#?}", all_ctors); // `missing_ctors` is the set of constructors from the same type as the // first column of `matrix` that are matched only by wildcard patterns @@ -1920,7 +1921,7 @@ crate fn is_useful<'p, 'tcx>( // can be big. let missing_ctors = MissingConstructors::new(all_ctors, used_ctors); - debug!("missing_ctors.empty()={:#?}", missing_ctors.is_empty(),); + debug!("is_useful_missing_ctors.empty()={:#?}", missing_ctors.is_empty(),); if missing_ctors.is_empty() { let (all_ctors, _) = missing_ctors.into_inner(); @@ -1988,7 +1989,9 @@ crate fn is_useful<'p, 'tcx>( usefulness.apply_missing_ctors(cx, pcx.ty, &missing_ctors) } } - } + }; + debug!("is_useful::returns({:#?}, {:#?}) = {:?}", matrix, v, ret); + ret } /// A shorthand for the `U(S(c, P), S(c, q))` operation from the paper. I.e., `is_useful` applied @@ -2647,7 +2650,10 @@ fn specialize_one_pattern<'p, 'tcx>( PatKind::Or { .. } => bug!("Or-pattern should have been expanded earlier on."), }; - debug!("specialize({:#?}, {:#?}) = {:#?}", pat, ctor_wild_subpatterns, result); + debug!( + "specialize({:#?}, {:#?}, {:#?}) = {:#?}", + pat, constructor, ctor_wild_subpatterns, result + ); result } From 3bf94b2c9d300132e391a27dfa6d44256ebee316 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 23 May 2020 18:49:38 +0100 Subject: [PATCH 2/4] Naming --- src/librustc_mir_build/hair/pattern/_match.rs | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 928d1f6a68abc..32c54fbbfd9a6 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -1025,11 +1025,11 @@ enum Fields<'p, 'tcx> { /// have not measured if it really made a difference. Slice(&'p [Pat<'tcx>]), Vec(SmallVec<[&'p Pat<'tcx>; 2]>), - /// Patterns where some of the fields need to be hidden. `len` caches the number of non-hidden - /// fields. + /// Patterns where some of the fields need to be hidden. `kept_count` caches the number of + /// non-hidden fields. Filtered { fields: SmallVec<[FilteredField<'p, 'tcx>; 2]>, - len: usize, + kept_count: usize, }, } @@ -1092,7 +1092,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { if has_no_hidden_fields { Fields::wildcards_from_tys(cx, field_tys) } else { - let mut len = 0; + let mut kept_count = 0; let fields = variant .fields .iter() @@ -1109,12 +1109,12 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { if is_uninhabited && (!is_visible || is_non_exhaustive) { FilteredField::Hidden(ty) } else { - len += 1; + kept_count += 1; FilteredField::Kept(wildcard_from_ty(ty)) } }) .collect(); - Fields::Filtered { fields, len } + Fields::Filtered { fields, kept_count } } } } @@ -1133,11 +1133,14 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { ret } + /// Returns the number of patterns from the viewpoint of match-checking, i.e. excluding hidden + /// fields. This is what we want in most cases in this file, the only exception being + /// conversion to/from `Pat`. fn len(&self) -> usize { match self { Fields::Slice(pats) => pats.len(), Fields::Vec(pats) => pats.len(), - Fields::Filtered { len, .. } => *len, + Fields::Filtered { kept_count, .. } => *kept_count, } } @@ -1207,7 +1210,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { let pats: &[_] = cx.pattern_arena.alloc_from_iter(pats); match self { - Fields::Filtered { fields, len } => { + Fields::Filtered { fields, kept_count } => { let mut pats = pats.iter(); let mut fields = fields.clone(); for f in &mut fields { @@ -1216,7 +1219,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { *p = pats.next().unwrap(); } } - Fields::Filtered { fields, len: *len } + Fields::Filtered { fields, kept_count: *kept_count } } _ => Fields::Slice(pats), } From 7addc115eb18fb4a1e5347b55a138d0428fb6344 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 23 May 2020 18:59:27 +0100 Subject: [PATCH 3/4] Work around type normalization issues --- src/librustc_mir_build/hair/pattern/_match.rs | 4 +++- .../usefulness/issue-72476-associated-type.rs | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/pattern/usefulness/issue-72476-associated-type.rs diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 32c54fbbfd9a6..575ddcef99715 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -1870,7 +1870,9 @@ crate fn is_useful<'p, 'tcx>( return if any_is_useful { Useful(unreachable_pats) } else { NotUseful }; } - let pcx = PatCtxt { ty: v.head().ty, span: v.head().span }; + // FIXME(Nadrieril): Hack to work around type normalization issues (see #72476). + let ty = matrix.heads().next().map(|r| r.ty).unwrap_or(v.head().ty); + let pcx = PatCtxt { ty, span: v.head().span }; debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v.head()); diff --git a/src/test/ui/pattern/usefulness/issue-72476-associated-type.rs b/src/test/ui/pattern/usefulness/issue-72476-associated-type.rs new file mode 100644 index 0000000000000..21ad6c7d989e0 --- /dev/null +++ b/src/test/ui/pattern/usefulness/issue-72476-associated-type.rs @@ -0,0 +1,23 @@ +// check-pass + +// From https://github.com/rust-lang/rust/issues/72476 + +trait A { + type Projection; +} + +impl A for () { + type Projection = bool; + // using () instead of bool here does compile though +} + +struct Next(T::Projection); + +fn f(item: Next<()>) { + match item { + Next(true) => {} + Next(false) => {} + } +} + +fn main() {} From 3e8ba3a3cbf5d25352f95d93867a9fcda7d33e91 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 23 May 2020 19:39:38 +0100 Subject: [PATCH 4/4] Remove out-of-date comment --- src/test/ui/pattern/usefulness/issue-72476-associated-type.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/ui/pattern/usefulness/issue-72476-associated-type.rs b/src/test/ui/pattern/usefulness/issue-72476-associated-type.rs index 21ad6c7d989e0..1e1d21433b79c 100644 --- a/src/test/ui/pattern/usefulness/issue-72476-associated-type.rs +++ b/src/test/ui/pattern/usefulness/issue-72476-associated-type.rs @@ -8,7 +8,6 @@ trait A { impl A for () { type Projection = bool; - // using () instead of bool here does compile though } struct Next(T::Projection);