-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Open
Labels
C-bugCategory: This is a bug.Category: This is a bug.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.This issue may need triage. Remove it if it has been sufficiently triaged.
Description
I tried this code:
fn foo() {}
fn bar() {}
fn main() {
let _ = [foo, if false { bar } else { foo }];
}
I expected to see this happen: It compiles, like in if
or match
.
fn foo() {}
fn bar() {}
fn main() {
let _ = if false {
foo
} else {
if false {
bar
} else {
foo
}
};
let _ = match 1 {
2 => foo,
_ => if false {
bar
} else {
foo
},
};
}
Instead, this happened: type mismatch when trying to coerce bar
into foo
.
The cause: check_expr_array
uses a type variable as the expectation during element typecking but the type variable is unified with the first element's type during coercion.
rust/compiler/rustc_hir_typeck/src/expr.rs
Lines 1818 to 1828 in 9b1a30e
let coerce_to = expected | |
.to_option(self) | |
.and_then(|uty| self.try_structurally_resolve_type(expr.span, uty).builtin_index()) | |
.unwrap_or_else(|| self.next_ty_var(expr.span)); | |
let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args); | |
assert_eq!(self.diverges.get(), Diverges::Maybe); | |
for e in args { | |
let e_ty = self.check_expr_with_hint(e, coerce_to); | |
let cause = self.misc(e.span); | |
coerce.coerce(self, &cause, e, e_ty); | |
} |
It should use
try_structurally_resolve_and_adjust_for_branches
on the element expectation as if
and match
do, which turns the expectation into NoExpectation
if the expected_ty is a true type variable.However, this simple fix can break some other code.
Recursive tuple coercion can fix this case. But it's complicated.
Meta
rustc --version --verbose
:
1.91.0-nightly
(2025-08-06 7d82b83ed57d188ab3f2)
Metadata
Metadata
Assignees
Labels
C-bugCategory: This is a bug.Category: This is a bug.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.This issue may need triage. Remove it if it has been sufficiently triaged.