Skip to content

Commit 5853399

Browse files
committed
Move special &str handling to Constructor and Fields
1 parent 035c521 commit 5853399

File tree

2 files changed

+21
-21
lines changed

2 files changed

+21
-21
lines changed

compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -660,9 +660,10 @@ impl<'tcx> Constructor<'tcx> {
660660
} else {
661661
match pat.ty.kind() {
662662
ty::Float(_) => FloatRange(value, value, RangeEnd::Included),
663-
// In `expand_pattern`, we convert string literals to `&CONST` patterns with
664-
// `CONST` a pattern of type `str`. In truth this contains a constant of type
665-
// `&str`.
663+
// We make `&str` constants behave like `Deref` patterns, to be compatible
664+
// with other `Deref` patterns. See also `Fields::extract_pattern_arguments`.
665+
ty::Ref(_, t, _) if t.is_str() => Single,
666+
// In truth this carries a constant of type `&str`.
666667
ty::Str => Str(value),
667668
// All constants that can be structurally matched have already been expanded
668669
// into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
@@ -1393,6 +1394,19 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
13931394
self.fields[i] = pat
13941395
}
13951396
}
1397+
PatKind::Constant { .. } => match pat.ty.kind() {
1398+
ty::Ref(_, t, _) if t.is_str() => {
1399+
assert_eq!(self.len(), 1);
1400+
// We want a `&str` constant to behave like a `Deref` pattern, to be compatible
1401+
// with other `Deref` patterns. This could have been done in `const_to_pat`,
1402+
// but that causes issues with the rest of the matching code.
1403+
// The outer constructor is `&`, and the inner one carries the str value.
1404+
let mut new_pat = pat.clone();
1405+
new_pat.ty = t; // `t` is `str`, not `&str`
1406+
self.fields[0] = &*cx.pattern_arena.alloc(new_pat);
1407+
}
1408+
_ => {}
1409+
},
13961410
_ => {}
13971411
};
13981412
self

compiler/rustc_mir_build/src/thir/pattern/usefulness.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -365,23 +365,9 @@ struct LiteralExpander;
365365
impl<'tcx> PatternFolder<'tcx> for LiteralExpander {
366366
fn fold_pattern(&mut self, pat: &Pat<'tcx>) -> Pat<'tcx> {
367367
debug!("fold_pattern {:?} {:?} {:?}", pat, pat.ty.kind(), pat.kind);
368-
match (pat.ty.kind(), pat.kind.as_ref()) {
369-
(_, PatKind::Binding { subpattern: Some(s), .. }) => s.fold_with(self),
370-
(_, PatKind::AscribeUserType { subpattern: s, .. }) => s.fold_with(self),
371-
(ty::Ref(_, t, _), PatKind::Constant { .. }) if t.is_str() => {
372-
// Treat string literal patterns as deref patterns to a `str` constant, i.e.
373-
// `&CONST`. This expands them like other const patterns. This could have been done
374-
// in `const_to_pat`, but that causes issues with the rest of the matching code.
375-
let mut new_pat = pat.super_fold_with(self);
376-
// Make a fake const pattern of type `str` (instead of `&str`). That the carried
377-
// constant value still knows it is of type `&str`.
378-
new_pat.ty = t;
379-
Pat {
380-
kind: Box::new(PatKind::Deref { subpattern: new_pat }),
381-
span: pat.span,
382-
ty: pat.ty,
383-
}
384-
}
368+
match pat.kind.as_ref() {
369+
PatKind::Binding { subpattern: Some(s), .. } => s.fold_with(self),
370+
PatKind::AscribeUserType { subpattern: s, .. } => s.fold_with(self),
385371
_ => pat.super_fold_with(self),
386372
}
387373
}
@@ -1183,7 +1169,7 @@ fn is_useful<'p, 'tcx>(
11831169
let ctor_wild_subpatterns = Fields::wildcards(pcx.cx, pcx.ty, &ctor);
11841170
let spec_matrix =
11851171
start_matrix.specialize_constructor(pcx, &ctor, &ctor_wild_subpatterns);
1186-
let v = v.pop_head_constructor(pcx.cx, &ctor_wild_subpatterns);
1172+
let v = v.pop_head_constructor(cx, &ctor_wild_subpatterns);
11871173
let usefulness =
11881174
is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false);
11891175
let usefulness =

0 commit comments

Comments
 (0)