diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 4a300fe09215c..a477df6ae2d56 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -626,9 +626,9 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); let discrim_diverges = self.diverges.get(); self.diverges.set(Diverges::Maybe); - // Typecheck the patterns first, so that we get types for all the - // bindings. - let all_arm_pats_diverge = arms.iter().map(|arm| { + // rust-lang/rust#55810: Typecheck patterns first (via eager + // collection into `Vec`), so we get types for all bindings. + let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| { let mut all_pats_diverge = Diverges::WarnedAlways; for p in &arm.pats { self.diverges.set(Diverges::Maybe); @@ -644,7 +644,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); Diverges::Maybe => Diverges::Maybe, Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways, } - }); + }).collect(); // Now typecheck the blocks. // diff --git a/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs b/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs new file mode 100644 index 0000000000000..9eed80ad886e0 --- /dev/null +++ b/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs @@ -0,0 +1,23 @@ +// compile-pass + +// rust-lang/rust#55810: types for a binding in a match arm can be +// inferred from arms that come later in the match. + +struct S; + +impl S { + fn method(&self) -> bool { + unimplemented!() + } +} + +fn get() -> T { + unimplemented!() +} + +fn main() { + match get() { + x if x.method() => {} + &S => {} + } +}