mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 07:22:42 +00:00
fix: infer lhs first on ordinary assignment expressions
This commit is contained in:
parent
d101439c77
commit
afdbd6cce2
@ -593,8 +593,28 @@ impl<'a> InferenceContext<'a> {
|
|||||||
}
|
}
|
||||||
Expr::BinaryOp { lhs, rhs, op } => match op {
|
Expr::BinaryOp { lhs, rhs, op } => match op {
|
||||||
Some(BinaryOp::Assignment { op: None }) => {
|
Some(BinaryOp::Assignment { op: None }) => {
|
||||||
let rhs_ty = self.infer_expr(*rhs, &Expectation::none());
|
let lhs = *lhs;
|
||||||
self.infer_assignee_expr(*lhs, &rhs_ty);
|
let is_ordinary = match &self.body[lhs] {
|
||||||
|
Expr::Array(_)
|
||||||
|
| Expr::RecordLit { .. }
|
||||||
|
| Expr::Tuple { .. }
|
||||||
|
| Expr::Underscore => false,
|
||||||
|
Expr::Call { callee, .. } => !matches!(&self.body[*callee], Expr::Path(_)),
|
||||||
|
_ => true,
|
||||||
|
};
|
||||||
|
|
||||||
|
// In ordinary (non-destructuring) assignments, the type of
|
||||||
|
// `lhs` must be inferred first so that the ADT fields
|
||||||
|
// instantiations in RHS can be coerced to it. Note that this
|
||||||
|
// cannot happen in destructuring assignments because of how
|
||||||
|
// they are desugared.
|
||||||
|
if is_ordinary {
|
||||||
|
let lhs_ty = self.infer_expr(lhs, &Expectation::none());
|
||||||
|
self.infer_expr_coerce(*rhs, &Expectation::has_type(lhs_ty));
|
||||||
|
} else {
|
||||||
|
let rhs_ty = self.infer_expr(*rhs, &Expectation::none());
|
||||||
|
self.infer_assignee_expr(lhs, &rhs_ty);
|
||||||
|
}
|
||||||
self.result.standard_types.unit.clone()
|
self.result.standard_types.unit.clone()
|
||||||
}
|
}
|
||||||
Some(BinaryOp::LogicOp(_)) => {
|
Some(BinaryOp::LogicOp(_)) => {
|
||||||
|
@ -709,3 +709,47 @@ fn test() {
|
|||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assign_coerce_struct_fields() {
|
||||||
|
check_no_mismatches(
|
||||||
|
r#"
|
||||||
|
//- minicore: coerce_unsized
|
||||||
|
struct S;
|
||||||
|
trait Tr {}
|
||||||
|
impl Tr for S {}
|
||||||
|
struct V<T> { t: T }
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: V<&dyn Tr>;
|
||||||
|
a = V { t: &S };
|
||||||
|
|
||||||
|
let mut a: V<&dyn Tr> = V { t: &S };
|
||||||
|
a = V { t: &S };
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn destructuring_assign_coerce_struct_fields() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- minicore: coerce_unsized
|
||||||
|
struct S;
|
||||||
|
trait Tr {}
|
||||||
|
impl Tr for S {}
|
||||||
|
struct V<T> { t: T }
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: V<&dyn Tr>;
|
||||||
|
(a,) = V { t: &S };
|
||||||
|
//^^^^expected V<&S>, got (V<&dyn Tr>,)
|
||||||
|
|
||||||
|
let mut a: V<&dyn Tr> = V { t: &S };
|
||||||
|
(a,) = V { t: &S };
|
||||||
|
//^^^^expected V<&S>, got (V<&dyn Tr>,)
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user