diff options
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/pattern/_match.rs | 95 |
1 files changed, 56 insertions, 39 deletions
diff --git a/compiler/rustc_mir_build/src/thir/pattern/_match.rs b/compiler/rustc_mir_build/src/thir/pattern/_match.rs index 850ce1847db..948c441f2c9 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/_match.rs @@ -1285,7 +1285,9 @@ impl<'tcx> Constructor<'tcx> { IntRange(range) => return range.to_pat(pcx.cx.tcx), NonExhaustive => PatKind::Wild, Opaque => bug!("we should not try to apply an opaque constructor"), - Wildcard => bug!("we should not try to apply a wildcard constructor"), + Wildcard => bug!( + "trying to apply a wildcard constructor; this should have been done in `apply_constructors`" + ), }; Pat { ty: pcx.ty, span: DUMMY_SP, kind: Box::new(pat) } @@ -1610,27 +1612,13 @@ impl<'tcx> Usefulness<'tcx> { pcx: PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>, ctor_wild_subpatterns: &Fields<'p, 'tcx>, - ) -> Self { - match self { - UsefulWithWitness(witnesses) => UsefulWithWitness( - witnesses - .into_iter() - .map(|witness| witness.apply_constructor(pcx, &ctor, ctor_wild_subpatterns)) - .collect(), - ), - x => x, - } - } - - fn apply_wildcard<'p>( - self, - pcx: PatCtxt<'_, 'p, 'tcx>, - missing_ctors: MissingConstructors<'tcx>, + is_top_level: bool, ) -> Self { match self { UsefulWithWitness(witnesses) => { - let new_patterns = missing_ctors.report_patterns(pcx); - UsefulWithWitness( + let new_witnesses = if ctor.is_wildcard() { + let missing_ctors = MissingConstructors::new(pcx, is_top_level); + let new_patterns = missing_ctors.report_patterns(pcx); witnesses .into_iter() .flat_map(|witness| { @@ -1640,8 +1628,14 @@ impl<'tcx> Usefulness<'tcx> { witness }) }) - .collect(), - ) + .collect() + } else { + witnesses + .into_iter() + .map(|witness| witness.apply_constructor(pcx, &ctor, ctor_wild_subpatterns)) + .collect() + }; + UsefulWithWitness(new_witnesses) } x => x, } @@ -2419,7 +2413,17 @@ crate fn is_useful<'p, 'tcx>( constructor .split(pcx, Some(hir_id)) .into_iter() - .map(|c| is_useful_specialized(pcx, v, c, witness_preference, hir_id, is_under_guard)) + .map(|c| { + is_useful_specialized( + pcx, + v, + &c, + witness_preference, + hir_id, + is_under_guard, + is_top_level, + ) + }) .find(|result| result.is_useful()) .unwrap_or(NotUseful) } else { @@ -2446,20 +2450,31 @@ crate fn is_useful<'p, 'tcx>( .into_iter() .flat_map(|ctor| ctor.split(pcx, None)) .map(|c| { - is_useful_specialized(pcx, v, c, witness_preference, hir_id, is_under_guard) + is_useful_specialized( + pcx, + v, + &c, + witness_preference, + hir_id, + is_under_guard, + is_top_level, + ) }) .find(|result| result.is_useful()) .unwrap_or(NotUseful) } else { - let ctor_wild_subpatterns = Fields::empty(); - let matrix = matrix.specialize_constructor(pcx, &constructor, &ctor_wild_subpatterns); - // Unwrap is ok: v can always be specialized with its own constructor. - let v = - v.specialize_constructor(pcx, &constructor, &ctor_wild_subpatterns, true).unwrap(); - let usefulness = - is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false); - - usefulness.apply_wildcard(pcx, missing_ctors) + // Some constructors are missing, thus we can specialize with the wildcard constructor, + // which will stand for those constructors that are missing, and behaves like any of + // them. + is_useful_specialized( + pcx, + v, + constructor, + witness_preference, + hir_id, + is_under_guard, + is_top_level, + ) } }; debug!("is_useful::returns({:#?}, {:#?}) = {:?}", matrix, v, ret); @@ -2471,20 +2486,22 @@ crate fn is_useful<'p, 'tcx>( fn is_useful_specialized<'p, 'tcx>( pcx: PatCtxt<'_, 'p, 'tcx>, v: &PatStack<'p, 'tcx>, - ctor: Constructor<'tcx>, + ctor: &Constructor<'tcx>, witness_preference: WitnessPreference, hir_id: HirId, is_under_guard: bool, + is_top_level: bool, ) -> Usefulness<'tcx> { debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, pcx.ty); // We cache the result of `Fields::wildcards` because it is used a lot. - let ctor_wild_subpatterns = Fields::wildcards(pcx, &ctor); - let matrix = pcx.matrix.specialize_constructor(pcx, &ctor, &ctor_wild_subpatterns); - v.specialize_constructor(pcx, &ctor, &ctor_wild_subpatterns, true) - .map(|v| is_useful(pcx.cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false)) - .map(|u| u.apply_constructor(pcx, &ctor, &ctor_wild_subpatterns)) - .unwrap_or(NotUseful) + let ctor_wild_subpatterns = Fields::wildcards(pcx, ctor); + let matrix = pcx.matrix.specialize_constructor(pcx, ctor, &ctor_wild_subpatterns); + // Unwrap is ok: v can always be specialized with its own constructor. + let v = v.specialize_constructor(pcx, ctor, &ctor_wild_subpatterns, true).unwrap(); + let usefulness = + is_useful(pcx.cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false); + usefulness.apply_constructor(pcx, ctor, &ctor_wild_subpatterns, is_top_level) } /// Determines the constructor that the given pattern can be specialized to. |
