diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a75f6f4caac91..70ba4acf48954 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1760,7 +1760,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let coerce_to = expected .to_option(self) .and_then(|uty| match *self.try_structurally_resolve_type(expr.span, uty).kind() { - ty::Array(ty, _) | ty::Slice(ty) => Some(ty), + // Avoid using a type variable as the coerce_to type, as it may resolve + // during the first coercion instead of being based on the common type. + ty::Array(ty, _) | ty::Slice(ty) if !ty.is_ty_var() => Some(ty), _ => None, }) .unwrap_or_else(|| self.next_ty_var(expr.span)); diff --git a/tests/ui/coercion/coerce-many-with-ty-var.rs b/tests/ui/coercion/coerce-many-with-ty-var.rs new file mode 100644 index 0000000000000..e759918c9e398 --- /dev/null +++ b/tests/ui/coercion/coerce-many-with-ty-var.rs @@ -0,0 +1,25 @@ +//@ run-pass +// Check that least upper bound coercions don't resolve type variable merely based on the first +// coercion. Check issue #136420. + +fn foo() {} +fn bar() {} + +fn infer(_: T) {} + +fn infer_array_element(_: [T; 2]) {} + +fn main() { + infer(if false { + foo + } else { + bar + }); + + infer(match false { + true => foo, + false => bar, + }); + + infer_array_element([foo, bar]); +}