Skip to content

Nested coercion in array results in type mismatch, inconsistent with if and match. #145048

@adwinwhite

Description

@adwinwhite

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.

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

No one assigned

    Labels

    C-bugCategory: This is a bug.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions