Skip to content

Commit 6f5c782

Browse files
committed
Auto merge of #71557 - matthewjasper:mir-asymmetric-or-pattern, r=oli-obk
Fix ICE for broken or-pattern in async fn closes #71297
2 parents 0a3619c + 4dd47d3 commit 6f5c782

File tree

6 files changed

+102
-19
lines changed

6 files changed

+102
-19
lines changed

src/librustc_mir_build/build/block.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
145145
}));
146146

147147
debug!("ast_block_stmts: pattern={:?}", pattern);
148-
this.visit_bindings(
148+
this.visit_primary_bindings(
149149
&pattern,
150150
UserTypeProjections::none(),
151151
&mut |this, _, _, _, node, span, _, _| {

src/librustc_mir_build/build/matches/mod.rs

+43-16
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
511511
opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
512512
) -> Option<SourceScope> {
513513
debug!("declare_bindings: pattern={:?}", pattern);
514-
self.visit_bindings(
514+
self.visit_primary_bindings(
515515
&pattern,
516516
UserTypeProjections::none(),
517517
&mut |this, mutability, name, mode, var, span, ty, user_ty| {
@@ -563,7 +563,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
563563
self.schedule_drop(span, region_scope, local_id, DropKind::Value);
564564
}
565565

566-
pub(super) fn visit_bindings(
566+
/// Visit all of the primary bindings in a patterns, that is, visit the
567+
/// leftmost occurrence of each variable bound in a pattern. A variable
568+
/// will occur more than once in an or-pattern.
569+
pub(super) fn visit_primary_bindings(
567570
&mut self,
568571
pattern: &Pat<'tcx>,
569572
pattern_user_ty: UserTypeProjections,
@@ -578,12 +581,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
578581
UserTypeProjections,
579582
),
580583
) {
581-
debug!("visit_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty);
584+
debug!(
585+
"visit_primary_bindings: pattern={:?} pattern_user_ty={:?}",
586+
pattern, pattern_user_ty
587+
);
582588
match *pattern.kind {
583-
PatKind::Binding { mutability, name, mode, var, ty, ref subpattern, .. } => {
584-
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty.clone());
589+
PatKind::Binding {
590+
mutability,
591+
name,
592+
mode,
593+
var,
594+
ty,
595+
ref subpattern,
596+
is_primary,
597+
..
598+
} => {
599+
if is_primary {
600+
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty.clone());
601+
}
585602
if let Some(subpattern) = subpattern.as_ref() {
586-
self.visit_bindings(subpattern, pattern_user_ty, f);
603+
self.visit_primary_bindings(subpattern, pattern_user_ty, f);
587604
}
588605
}
589606

@@ -592,20 +609,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
592609
let from = u32::try_from(prefix.len()).unwrap();
593610
let to = u32::try_from(suffix.len()).unwrap();
594611
for subpattern in prefix {
595-
self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f);
612+
self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
596613
}
597614
for subpattern in slice {
598-
self.visit_bindings(subpattern, pattern_user_ty.clone().subslice(from, to), f);
615+
self.visit_primary_bindings(
616+
subpattern,
617+
pattern_user_ty.clone().subslice(from, to),
618+
f,
619+
);
599620
}
600621
for subpattern in suffix {
601-
self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f);
622+
self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f);
602623
}
603624
}
604625

605626
PatKind::Constant { .. } | PatKind::Range { .. } | PatKind::Wild => {}
606627

607628
PatKind::Deref { ref subpattern } => {
608-
self.visit_bindings(subpattern, pattern_user_ty.deref(), f);
629+
self.visit_primary_bindings(subpattern, pattern_user_ty.deref(), f);
609630
}
610631

611632
PatKind::AscribeUserType {
@@ -630,26 +651,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
630651
projs: Vec::new(),
631652
};
632653
let subpattern_user_ty = pattern_user_ty.push_projection(&projection, user_ty_span);
633-
self.visit_bindings(subpattern, subpattern_user_ty, f)
654+
self.visit_primary_bindings(subpattern, subpattern_user_ty, f)
634655
}
635656

636657
PatKind::Leaf { ref subpatterns } => {
637658
for subpattern in subpatterns {
638659
let subpattern_user_ty = pattern_user_ty.clone().leaf(subpattern.field);
639-
debug!("visit_bindings: subpattern_user_ty={:?}", subpattern_user_ty);
640-
self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f);
660+
debug!("visit_primary_bindings: subpattern_user_ty={:?}", subpattern_user_ty);
661+
self.visit_primary_bindings(&subpattern.pattern, subpattern_user_ty, f);
641662
}
642663
}
643664

644665
PatKind::Variant { adt_def, substs: _, variant_index, ref subpatterns } => {
645666
for subpattern in subpatterns {
646667
let subpattern_user_ty =
647668
pattern_user_ty.clone().variant(adt_def, variant_index, subpattern.field);
648-
self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f);
669+
self.visit_primary_bindings(&subpattern.pattern, subpattern_user_ty, f);
649670
}
650671
}
651672
PatKind::Or { ref pats } => {
652-
self.visit_bindings(&pats[0], pattern_user_ty, f);
673+
// In cases where we recover from errors the primary bindings
674+
// may not all be in the leftmost subpattern. For example in
675+
// `let (x | y) = ...`, the primary binding of `y` occurs in
676+
// the right subpattern
677+
for subpattern in pats {
678+
self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f);
679+
}
653680
}
654681
}
655682
}
@@ -1955,7 +1982,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
19551982
is_block_tail: None,
19561983
local_info: Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
19571984
binding_mode,
1958-
// hypothetically, `visit_bindings` could try to unzip
1985+
// hypothetically, `visit_primary_bindings` could try to unzip
19591986
// an outermost hir::Ty as we descend, matching up
19601987
// idents in pat; but complex w/ unclear UI payoff.
19611988
// Instead, just abandon providing diagnostic info.

src/librustc_mir_build/build/matches/simplify.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
129129
Ok(())
130130
}
131131

132-
PatKind::Binding { name, mutability, mode, var, ty, ref subpattern } => {
132+
PatKind::Binding { name, mutability, mode, var, ty, ref subpattern, is_primary: _ } => {
133133
candidate.bindings.push(Binding {
134134
name,
135135
mutability,

src/librustc_mir_build/hair/pattern/mod.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ crate enum PatKind<'tcx> {
133133
var: hir::HirId,
134134
ty: Ty<'tcx>,
135135
subpattern: Option<Pat<'tcx>>,
136+
/// Is this the leftmost occurance of the binding, i.e., is `var` the
137+
/// `HirId` of this pattern?
138+
is_primary: bool,
136139
},
137140

138141
/// `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> {
601604
var: id,
602605
ty: var_ty,
603606
subpattern: self.lower_opt_pattern(sub),
607+
is_primary: id == pat.hir_id,
604608
}
605609
}
606610

@@ -977,14 +981,15 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> {
977981
user_ty_span,
978982
},
979983
},
980-
PatKind::Binding { mutability, name, mode, var, ty, ref subpattern } => {
984+
PatKind::Binding { mutability, name, mode, var, ty, ref subpattern, is_primary } => {
981985
PatKind::Binding {
982986
mutability: mutability.fold_with(folder),
983987
name: name.fold_with(folder),
984988
mode: mode.fold_with(folder),
985989
var: var.fold_with(folder),
986990
ty: ty.fold_with(folder),
987991
subpattern: subpattern.fold_with(folder),
992+
is_primary,
988993
}
989994
}
990995
PatKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Regression test for #71297
2+
// edition:2018
3+
4+
#![feature(or_patterns)]
5+
6+
async fn a((x | s): String) {}
7+
//~^ ERROR variable `x` is not bound in all patterns
8+
//~| ERROR variable `s` is not bound in all patterns
9+
10+
async fn b() {
11+
let x | s = String::new();
12+
//~^ ERROR variable `x` is not bound in all patterns
13+
//~| ERROR variable `s` is not bound in all patterns
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error[E0408]: variable `x` is not bound in all patterns
2+
--> $DIR/mismatched-bindings-async-fn.rs:6:17
3+
|
4+
LL | async fn a((x | s): String) {}
5+
| - ^ pattern doesn't bind `x`
6+
| |
7+
| variable not in all patterns
8+
9+
error[E0408]: variable `s` is not bound in all patterns
10+
--> $DIR/mismatched-bindings-async-fn.rs:6:13
11+
|
12+
LL | async fn a((x | s): String) {}
13+
| ^ - variable not in all patterns
14+
| |
15+
| pattern doesn't bind `s`
16+
17+
error[E0408]: variable `x` is not bound in all patterns
18+
--> $DIR/mismatched-bindings-async-fn.rs:11:13
19+
|
20+
LL | let x | s = String::new();
21+
| - ^ pattern doesn't bind `x`
22+
| |
23+
| variable not in all patterns
24+
25+
error[E0408]: variable `s` is not bound in all patterns
26+
--> $DIR/mismatched-bindings-async-fn.rs:11:9
27+
|
28+
LL | let x | s = String::new();
29+
| ^ - variable not in all patterns
30+
| |
31+
| pattern doesn't bind `s`
32+
33+
error: aborting due to 4 previous errors
34+
35+
For more information about this error, try `rustc --explain E0408`.

0 commit comments

Comments
 (0)