4412: infer: Make expected rhs type for plain assign the lhs type r=flodiebold a=kiljacken

This fixes an issue where the following code sample would fail to infer
the type contained in the option:
```rust
fn main() {
    let mut end = None; // Was Option<{unknown}>, is now Option<bool>
    loop {
        end = Some(true);
    }
}
```

Co-authored-by: Emil Lauridsen <mine809@gmail.com>
This commit is contained in:
bors[bot] 2020-05-10 14:48:04 +00:00 committed by GitHub
commit 225f353aa2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 1 deletions

View file

@ -30,7 +30,8 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty {
match op {
BinaryOp::LogicOp(..) => Ty::simple(TypeCtor::Bool),
BinaryOp::Assignment { op: None } | BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty {
BinaryOp::Assignment { op: None } => lhs_ty,
BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty {
Ty::Apply(ApplicationTy { ctor, .. }) => match ctor {
TypeCtor::Int(..)
| TypeCtor::Float(..)

View file

@ -1787,3 +1787,32 @@ fn main() {
"###
)
}
#[test]
fn infer_generic_from_later_assignment() {
assert_snapshot!(
infer(r#"
enum Option<T> { Some(T), None }
use Option::*;
fn test() {
let mut end = None;
loop {
end = Some(true);
}
}
"#),
@r###"
60..130 '{ ... } }': ()
70..77 'mut end': Option<bool>
80..84 'None': Option<bool>
90..128 'loop {... }': !
95..128 '{ ... }': ()
105..108 'end': Option<bool>
105..121 'end = ...(true)': ()
111..115 'Some': Some<bool>(bool) -> Option<bool>
111..121 'Some(true)': Option<bool>
116..120 'true': bool
"###
);
}