Skip to content

Mismatched types for a conditional containing closures inside method call #127525

Open
@marmac02

Description

@marmac02

Hello! I have encountered an issue when using a conditional returning closures inside a method call - specifically, the compiler is unable to coerce closure types to Box<dyn Fn(...)->...> for a very specific case. Consider this code.

trait Foo<I : Fn() -> i16>{
    fn foo(&self, param : I) -> ();
}
struct S {}

impl Foo<Box<dyn Fn() -> i16>> for S {
    fn foo(&self, param : Box<dyn Fn() -> i16>) -> () {
        unimplemented!();
    }
}

fn main() {
    let s = S {};
    
    let cond = true;
    s.foo(if cond { //replace cond with cond==true
        Box::new(|| {42})
    }
    else {
        Box::new(|| {42})
    });
}

The above code does not compile, with an error message saying that if and else have incompatible types. When cond is replaced with cond==true, the code will compile.

This issue is very similar to an issue I submitted a while back (#126988). But only now have I found that the compiler behaves differently for different conditionals.

Also, when you enclose the type of param in another type, for example Vec, the code will compile even with just cond if-statement conditional. See adjusted code below that compiles:

trait Foo<I : Fn() -> i16>{
    fn foo(&self, param : Vec<I>) -> ();
}
struct S {}

impl Foo<Box<dyn Fn() -> i16>> for S {
    fn foo(&self, param : Vec<Box<dyn Fn() -> i16>>) -> () {
        unimplemented!();
    }
}

fn main() {
    let s = S {};
    
    let cond = true;
    s.foo(if cond {
        vec![if cond {Box::new(|| {42})} else {Box::new(|| {43})}]
    }
    else {
        vec![Box::new(|| {42})]
    });
}

Meta

rustc 1.75.0 (82e1608df 2023-12-21)
release: 1.75.0
LLVM version: 17.0.6

Metadata

Metadata

Labels

A-closuresArea: Closures (`|…| { … }`)C-bugCategory: This is a bug.T-typesRelevant to the types team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions