diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 1d08d8d21daa..d76f58993883 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -2390,7 +2390,10 @@ fn specialize_one_pattern<'p, 'tcx>( ) -> Option> { if let NonExhaustive = constructor { // Only a wildcard pattern can match the special extra constructor - return if pat.is_wildcard() { Some(Fields::empty()) } else { None }; + if !pat.is_wildcard() { + return None; + } + return Some(Fields::empty()); } let result = match *pat.kind { @@ -2400,12 +2403,11 @@ fn specialize_one_pattern<'p, 'tcx>( PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => { let variant = &adt_def.variants[variant_index]; + if constructor != &Variant(variant.def_id) { + return None; + } let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(pat.ty, variant); - Some(Variant(variant.def_id)) - .filter(|variant_constructor| variant_constructor == constructor) - .map(|_| { - patterns_for_variant(cx, subpatterns, ctor_wild_subpatterns, is_non_exhaustive) - }) + Some(patterns_for_variant(cx, subpatterns, ctor_wild_subpatterns, is_non_exhaustive)) } PatKind::Leaf { ref subpatterns } => { @@ -2425,11 +2427,10 @@ fn specialize_one_pattern<'p, 'tcx>( // Shortcut for `n == 0` where no matter what `alloc` and `offset` we produce, // the result would be exactly what we early return here. if n == 0 { - if ctor_wild_subpatterns.len() as u64 == 0 { - return Some(Fields::empty()); - } else { + if ctor_wild_subpatterns.len() as u64 != n { return None; } + return Some(Fields::empty()); } match value.val { ty::ConstKind::Value(ConstValue::ByRef { offset, alloc, .. }) => { @@ -2463,25 +2464,23 @@ fn specialize_one_pattern<'p, 'tcx>( constructor, ), }; - if ctor_wild_subpatterns.len() as u64 == n { - // convert a constant slice/array pattern to a list of patterns. - let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?; - let ptr = Pointer::new(AllocId(0), offset); - let pats = (0..n) - .map(|i| { - let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?; - let scalar = alloc.read_scalar(&cx.tcx, ptr, layout.size).ok()?; - let scalar = scalar.not_undef().ok()?; - let value = ty::Const::from_scalar(cx.tcx, scalar, ty); - let pattern = - Pat { ty, span: pat.span, kind: box PatKind::Constant { value } }; - Some(&*cx.pattern_arena.alloc(pattern)) - }) - .collect::>()?; - Some(Fields::from_vec(pats)) - } else { - None + if ctor_wild_subpatterns.len() as u64 != n { + return None; } + // Convert a constant slice/array pattern to a list of patterns. + let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?; + let ptr = Pointer::new(AllocId(0), offset); + let pats = (0..n) + .map(|i| { + let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?; + let scalar = alloc.read_scalar(&cx.tcx, ptr, layout.size).ok()?; + let scalar = scalar.not_undef().ok()?; + let value = ty::Const::from_scalar(cx.tcx, scalar, ty); + let pattern = Pat { ty, span: pat.span, kind: box PatKind::Constant { value } }; + Some(&*cx.pattern_arena.alloc(pattern)) + }) + .collect::>()?; + Some(Fields::from_vec(pats)) } PatKind::Constant { .. } | PatKind::Range { .. } => { @@ -2489,50 +2488,42 @@ fn specialize_one_pattern<'p, 'tcx>( // - Single value: add a row if the pattern contains the constructor. // - Range: add a row if the constructor intersects the pattern. if let IntRange(ctor) = constructor { - match IntRange::from_pat(cx.tcx, cx.param_env, pat) { - Some(pat) => ctor.intersection(cx.tcx, &pat).map(|_| { - // Constructor splitting should ensure that all intersections we encounter - // are actually inclusions. - assert!(ctor.is_subrange(&pat)); - Fields::empty() - }), - _ => None, - } + let pat = IntRange::from_pat(cx.tcx, cx.param_env, pat)?; + ctor.intersection(cx.tcx, &pat)?; + // Constructor splitting should ensure that all intersections we encounter + // are actually inclusions. + assert!(ctor.is_subrange(&pat)); } else { // Fallback for non-ranges and ranges that involve // floating-point numbers, which are not conveniently handled // by `IntRange`. For these cases, the constructor may not be a // range so intersection actually devolves into being covered // by the pattern. - constructor_covered_by_range(cx.tcx, cx.param_env, constructor, pat) - .map(|()| Fields::empty()) + constructor_covered_by_range(cx.tcx, cx.param_env, constructor, pat)?; } + Some(Fields::empty()) } PatKind::Array { ref prefix, ref slice, ref suffix } | PatKind::Slice { ref prefix, ref slice, ref suffix } => match *constructor { Slice(_) => { + // Number of subpatterns for this pattern let pat_len = prefix.len() + suffix.len(); - if let Some(slice_count) = ctor_wild_subpatterns.len().checked_sub(pat_len) { - if slice_count == 0 || slice.is_some() { - Some(Fields::from_vec( - prefix - .iter() - .chain( - ctor_wild_subpatterns - .iter() - .skip(prefix.len()) - .take(slice_count) - .chain(suffix.iter()), - ) - .collect(), - )) - } else { - None - } - } else { - None + // Number of subpatterns for this constructor + let arity = ctor_wild_subpatterns.len(); + + if slice.is_none() && arity != pat_len { + return None; } + + // Number of subpatterns matched by the `..` subslice pattern (is 0 for a slice + // pattern of fixed length). + let subslice_count = arity.checked_sub(pat_len)?; + let subslice_pats = + ctor_wild_subpatterns.iter().skip(prefix.len()).take(subslice_count); + Some(Fields::from_vec( + prefix.iter().chain(subslice_pats).chain(suffix.iter()).collect(), + )) } ConstantValue(cv) => { match slice_pat_covered_by_const(