mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-17 22:46:50 +00:00
Move special &str
handling to Constructor
and Fields
This commit is contained in:
parent
035c5213ae
commit
5853399aee
@ -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
|
||||
|
@ -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 =
|
||||
|
Loading…
Reference in New Issue
Block a user