diff options
| author | Nadrieril <nadrieril+git@gmail.com> | 2021-09-22 19:29:33 +0100 |
|---|---|---|
| committer | Nadrieril <nadrieril+git@gmail.com> | 2021-09-26 00:05:52 +0100 |
| commit | 5853399aee2495107659c2de48b18900f17d3d2c (patch) | |
| tree | de71a044cd0be46a4d03e6e731f8c582f071c67b | |
| parent | 035c5213aee99adde4895423591e0e076fbb5dd1 (diff) | |
Move special `&str` handling to `Constructor` and `Fields`
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/pattern/usefulness.rs | 22 |
2 files changed, 21 insertions, 21 deletions
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 46bd29e7a3f..96425381b6b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -660,9 +660,10 @@ impl<'tcx> Constructor<'tcx> { } else { match pat.ty.kind() { ty::Float(_) => FloatRange(value, value, RangeEnd::Included), - // In `expand_pattern`, we convert string literals to `&CONST` patterns with - // `CONST` a pattern of type `str`. In truth this contains a constant of type - // `&str`. + // We make `&str` constants behave like `Deref` patterns, to be compatible + // with other `Deref` patterns. See also `Fields::extract_pattern_arguments`. + ty::Ref(_, t, _) if t.is_str() => Single, + // In truth this carries a constant of type `&str`. ty::Str => Str(value), // All constants that can be structurally matched have already been expanded // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are @@ -1393,6 +1394,19 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { self.fields[i] = pat } } + PatKind::Constant { .. } => match pat.ty.kind() { + ty::Ref(_, t, _) if t.is_str() => { + assert_eq!(self.len(), 1); + // We want a `&str` constant to behave like a `Deref` pattern, to be compatible + // with other `Deref` patterns. This could have been done in `const_to_pat`, + // but that causes issues with the rest of the matching code. + // The outer constructor is `&`, and the inner one carries the str value. + let mut new_pat = pat.clone(); + new_pat.ty = t; // `t` is `str`, not `&str` + self.fields[0] = &*cx.pattern_arena.alloc(new_pat); + } + _ => {} + }, _ => {} }; self diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index b518be0141d..76759abca03 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -365,23 +365,9 @@ struct LiteralExpander; impl<'tcx> PatternFolder<'tcx> for LiteralExpander { fn fold_pattern(&mut self, pat: &Pat<'tcx>) -> Pat<'tcx> { debug!("fold_pattern {:?} {:?} {:?}", pat, pat.ty.kind(), pat.kind); - match (pat.ty.kind(), pat.kind.as_ref()) { - (_, PatKind::Binding { subpattern: Some(s), .. }) => s.fold_with(self), - (_, PatKind::AscribeUserType { subpattern: s, .. }) => s.fold_with(self), - (ty::Ref(_, t, _), PatKind::Constant { .. }) if t.is_str() => { - // Treat string literal patterns as deref patterns to a `str` constant, i.e. - // `&CONST`. This expands them like other const patterns. This could have been done - // in `const_to_pat`, but that causes issues with the rest of the matching code. - let mut new_pat = pat.super_fold_with(self); - // Make a fake const pattern of type `str` (instead of `&str`). That the carried - // constant value still knows it is of type `&str`. - new_pat.ty = t; - Pat { - kind: Box::new(PatKind::Deref { subpattern: new_pat }), - span: pat.span, - ty: pat.ty, - } - } + match pat.kind.as_ref() { + PatKind::Binding { subpattern: Some(s), .. } => s.fold_with(self), + PatKind::AscribeUserType { subpattern: s, .. } => s.fold_with(self), _ => pat.super_fold_with(self), } } @@ -1183,7 +1169,7 @@ fn is_useful<'p, 'tcx>( let ctor_wild_subpatterns = Fields::wildcards(pcx.cx, pcx.ty, &ctor); let spec_matrix = start_matrix.specialize_constructor(pcx, &ctor, &ctor_wild_subpatterns); - let v = v.pop_head_constructor(pcx.cx, &ctor_wild_subpatterns); + let v = v.pop_head_constructor(cx, &ctor_wild_subpatterns); let usefulness = is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false); let usefulness = |
