Infer if type through indirection.
It surprised me that the first example works, while the second doesn't.
https://play.rust-lang.org/?gist=a1bee92067f87a67240b4ccd2bc9a6a4&version=stable
trait Foo {}
struct A;
impl Foo for A {}
struct B;
impl Foo for B {}
pub fn test() {
let a = A;
let b = B;
// Works.
let x: &Foo = if true { &a } else { &b };
// Doesn't work.
let y = if true { &a } else { &b };
let z: &Foo = y;
}
error[E0308]: if and else have incompatible types
--> src/main.rs:17:13
|
17 | let y = if true { &a } else { &b };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `A`, found struct `B`
|
= note: expected type `&A`
found type `&B`
It seems like adding this let shouldn't change anything but it seems the required type of the if statement isn't propagated unless it is directly used. The same behaviour can be found when using func(if ...) vs let x = if ...; func(x)
(sorry if this is known, I couldn't find anything)
Should the last line be
let z: &Foo = y;(It still doesn't work with that change, but right now the
zline isn't doing anything.)scottmcm at 2017-11-21 22:38:37
Yes, good catch. Of course what I posted doesn't work because
yis never used. However with that change in would expect it to work (but it doesn't).I've updated the original comment to be correct.
Kevin Cox at 2017-11-21 22:42:33
Triage: still reproduces on 2021 edition, tested on
rustc 1.59.0 (9d1b2106e 2022-02-23)Code needs be adjusted a bit using the
dynkeyword:trait Foo {} struct A; impl Foo for A {} struct B; impl Foo for B {} pub fn main() { let a = A; let b = B; // Works. let x: &dyn Foo = if true { &a } else { &b }; // Doesn't work. let y = if true { &a } else { &b }; let z: &dyn Foo = y; }Maayan Hanin at 2022-03-21 12:08:49