Auto merge of #71557 - matthewjasper:mir-asymmetric-or-pattern, r=oli-obk
Fix ICE for broken or-pattern in async fn closes #71297
This commit is contained in:
commit
6f5c7827b7
@ -145,7 +145,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}));
|
||||
|
||||
debug!("ast_block_stmts: pattern={:?}", pattern);
|
||||
this.visit_bindings(
|
||||
this.visit_primary_bindings(
|
||||
&pattern,
|
||||
UserTypeProjections::none(),
|
||||
&mut |this, _, _, _, node, span, _, _| {
|
||||
|
@ -511,7 +511,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
|
||||
) -> Option<SourceScope> {
|
||||
debug!("declare_bindings: pattern={:?}", pattern);
|
||||
self.visit_bindings(
|
||||
self.visit_primary_bindings(
|
||||
&pattern,
|
||||
UserTypeProjections::none(),
|
||||
&mut |this, mutability, name, mode, var, span, ty, user_ty| {
|
||||
@ -563,7 +563,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
self.schedule_drop(span, region_scope, local_id, DropKind::Value);
|
||||
}
|
||||
|
||||
pub(super) fn visit_bindings(
|
||||
/// Visit all of the primary bindings in a patterns, that is, visit the
|
||||
/// leftmost occurrence of each variable bound in a pattern. A variable
|
||||
/// will occur more than once in an or-pattern.
|
||||
pub(super) fn visit_primary_bindings(
|
||||
&mut self,
|
||||
pattern: &Pat<'tcx>,
|
||||
pattern_user_ty: UserTypeProjections,
|
||||
@ -578,12 +581,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
UserTypeProjections,
|
||||
),
|
||||
) {
|
||||
debug!("visit_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty);
|
||||
debug!(
|
||||
"visit_primary_bindings: pattern={:?} pattern_user_ty={:?}",
|
||||
pattern, pattern_user_ty
|
||||
);
|
||||
match *pattern.kind {
|
||||
PatKind::Binding { mutability, name, mode, var, ty, ref subpattern, .. } => {
|
||||
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty.clone());
|
||||
PatKind::Binding {
|
||||
mutability,
|
||||
name,
|
||||
mode,
|
||||
var,
|
||||
ty,
|
||||
ref subpattern,
|
||||
is_primary,
|
||||
..
|
||||
} => {
|
||||
if is_primary {
|
||||
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty.clone());
|
||||
}
|
||||
if let Some(subpattern) = subpattern.as_ref() {
|
||||
self.visit_bindings(subpattern, pattern_user_ty, f);
|
||||
self.visit_primary_bindings(subpattern, pattern_user_ty, f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -592,20 +609,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let from = u32::try_from(prefix.len()).unwrap();
|
||||
let to = u32::try_from(suffix.len()).unwrap();
|
||||
for subpattern in prefix {
|
||||
self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f);
|
||||
self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
|
||||
}
|
||||
for subpattern in slice {
|
||||
self.visit_bindings(subpattern, pattern_user_ty.clone().subslice(from, to), f);
|
||||
self.visit_primary_bindings(
|
||||
subpattern,
|
||||
pattern_user_ty.clone().subslice(from, to),
|
||||
f,
|
||||
);
|
||||
}
|
||||
for subpattern in suffix {
|
||||
self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f);
|
||||
self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Constant { .. } | PatKind::Range { .. } | PatKind::Wild => {}
|
||||
|
||||
PatKind::Deref { ref subpattern } => {
|
||||
self.visit_bindings(subpattern, pattern_user_ty.deref(), f);
|
||||
self.visit_primary_bindings(subpattern, pattern_user_ty.deref(), f);
|
||||
}
|
||||
|
||||
PatKind::AscribeUserType {
|
||||
@ -630,14 +651,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
projs: Vec::new(),
|
||||
};
|
||||
let subpattern_user_ty = pattern_user_ty.push_projection(&projection, user_ty_span);
|
||||
self.visit_bindings(subpattern, subpattern_user_ty, f)
|
||||
self.visit_primary_bindings(subpattern, subpattern_user_ty, f)
|
||||
}
|
||||
|
||||
PatKind::Leaf { ref subpatterns } => {
|
||||
for subpattern in subpatterns {
|
||||
let subpattern_user_ty = pattern_user_ty.clone().leaf(subpattern.field);
|
||||
debug!("visit_bindings: subpattern_user_ty={:?}", subpattern_user_ty);
|
||||
self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f);
|
||||
debug!("visit_primary_bindings: subpattern_user_ty={:?}", subpattern_user_ty);
|
||||
self.visit_primary_bindings(&subpattern.pattern, subpattern_user_ty, f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -645,11 +666,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
for subpattern in subpatterns {
|
||||
let subpattern_user_ty =
|
||||
pattern_user_ty.clone().variant(adt_def, variant_index, subpattern.field);
|
||||
self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f);
|
||||
self.visit_primary_bindings(&subpattern.pattern, subpattern_user_ty, f);
|
||||
}
|
||||
}
|
||||
PatKind::Or { ref pats } => {
|
||||
self.visit_bindings(&pats[0], pattern_user_ty, f);
|
||||
// In cases where we recover from errors the primary bindings
|
||||
// may not all be in the leftmost subpattern. For example in
|
||||
// `let (x | y) = ...`, the primary binding of `y` occurs in
|
||||
// the right subpattern
|
||||
for subpattern in pats {
|
||||
self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1955,7 +1982,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
is_block_tail: None,
|
||||
local_info: Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
|
||||
binding_mode,
|
||||
// hypothetically, `visit_bindings` could try to unzip
|
||||
// hypothetically, `visit_primary_bindings` could try to unzip
|
||||
// an outermost hir::Ty as we descend, matching up
|
||||
// idents in pat; but complex w/ unclear UI payoff.
|
||||
// Instead, just abandon providing diagnostic info.
|
||||
|
@ -129,7 +129,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
PatKind::Binding { name, mutability, mode, var, ty, ref subpattern } => {
|
||||
PatKind::Binding { name, mutability, mode, var, ty, ref subpattern, is_primary: _ } => {
|
||||
candidate.bindings.push(Binding {
|
||||
name,
|
||||
mutability,
|
||||
|
@ -133,6 +133,9 @@ crate enum PatKind<'tcx> {
|
||||
var: hir::HirId,
|
||||
ty: Ty<'tcx>,
|
||||
subpattern: Option<Pat<'tcx>>,
|
||||
/// Is this the leftmost occurance of the binding, i.e., is `var` the
|
||||
/// `HirId` of this pattern?
|
||||
is_primary: bool,
|
||||
},
|
||||
|
||||
/// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with
|
||||
@ -601,6 +604,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
var: id,
|
||||
ty: var_ty,
|
||||
subpattern: self.lower_opt_pattern(sub),
|
||||
is_primary: id == pat.hir_id,
|
||||
}
|
||||
}
|
||||
|
||||
@ -977,7 +981,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> {
|
||||
user_ty_span,
|
||||
},
|
||||
},
|
||||
PatKind::Binding { mutability, name, mode, var, ty, ref subpattern } => {
|
||||
PatKind::Binding { mutability, name, mode, var, ty, ref subpattern, is_primary } => {
|
||||
PatKind::Binding {
|
||||
mutability: mutability.fold_with(folder),
|
||||
name: name.fold_with(folder),
|
||||
@ -985,6 +989,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> {
|
||||
var: var.fold_with(folder),
|
||||
ty: ty.fold_with(folder),
|
||||
subpattern: subpattern.fold_with(folder),
|
||||
is_primary,
|
||||
}
|
||||
}
|
||||
PatKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
|
||||
|
16
src/test/ui/or-patterns/mismatched-bindings-async-fn.rs
Normal file
16
src/test/ui/or-patterns/mismatched-bindings-async-fn.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// Regression test for #71297
|
||||
// edition:2018
|
||||
|
||||
#![feature(or_patterns)]
|
||||
|
||||
async fn a((x | s): String) {}
|
||||
//~^ ERROR variable `x` is not bound in all patterns
|
||||
//~| ERROR variable `s` is not bound in all patterns
|
||||
|
||||
async fn b() {
|
||||
let x | s = String::new();
|
||||
//~^ ERROR variable `x` is not bound in all patterns
|
||||
//~| ERROR variable `s` is not bound in all patterns
|
||||
}
|
||||
|
||||
fn main() {}
|
35
src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr
Normal file
35
src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr
Normal file
@ -0,0 +1,35 @@
|
||||
error[E0408]: variable `x` is not bound in all patterns
|
||||
--> $DIR/mismatched-bindings-async-fn.rs:6:17
|
||||
|
|
||||
LL | async fn a((x | s): String) {}
|
||||
| - ^ pattern doesn't bind `x`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
||||
error[E0408]: variable `s` is not bound in all patterns
|
||||
--> $DIR/mismatched-bindings-async-fn.rs:6:13
|
||||
|
|
||||
LL | async fn a((x | s): String) {}
|
||||
| ^ - variable not in all patterns
|
||||
| |
|
||||
| pattern doesn't bind `s`
|
||||
|
||||
error[E0408]: variable `x` is not bound in all patterns
|
||||
--> $DIR/mismatched-bindings-async-fn.rs:11:13
|
||||
|
|
||||
LL | let x | s = String::new();
|
||||
| - ^ pattern doesn't bind `x`
|
||||
| |
|
||||
| variable not in all patterns
|
||||
|
||||
error[E0408]: variable `s` is not bound in all patterns
|
||||
--> $DIR/mismatched-bindings-async-fn.rs:11:9
|
||||
|
|
||||
LL | let x | s = String::new();
|
||||
| ^ - variable not in all patterns
|
||||
| |
|
||||
| pattern doesn't bind `s`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0408`.
|
Loading…
x
Reference in New Issue
Block a user