@@ -593,8 +593,8 @@ impl<'a> InferenceContext<'a> {
593593 }
594594 Expr :: BinaryOp { lhs, rhs, op } => match op {
595595 Some ( BinaryOp :: Assignment { op : None } ) => {
596- let lhs_ty = self . infer_expr ( * lhs , & Expectation :: none ( ) ) ;
597- self . infer_expr_coerce ( * rhs , & Expectation :: has_type ( lhs_ty ) ) ;
596+ let rhs_ty = self . infer_expr ( * rhs , & Expectation :: none ( ) ) ;
597+ self . infer_assignee_expr ( * lhs , & rhs_ty ) ;
598598 self . result . standard_types . unit . clone ( )
599599 }
600600 Some ( BinaryOp :: LogicOp ( _) ) => {
@@ -817,6 +817,95 @@ impl<'a> InferenceContext<'a> {
817817 }
818818 }
819819
820+ pub ( super ) fn infer_assignee_expr ( & mut self , lhs : ExprId , rhs_ty : & Ty ) -> Ty {
821+ let is_rest_expr = |expr| {
822+ matches ! (
823+ & self . body[ expr] ,
824+ Expr :: Range { lhs: None , rhs: None , range_type: RangeOp :: Exclusive } ,
825+ )
826+ } ;
827+
828+ let rhs_ty = self . resolve_ty_shallow ( rhs_ty) ;
829+
830+ let ty = match & self . body [ lhs] {
831+ Expr :: Tuple { exprs } => {
832+ // We don't consider multiple ellipses. This is analogous to
833+ // `hir_def::body::lower::ExprCollector::collect_tuple_pat()`.
834+ let ellipsis = exprs. iter ( ) . position ( |e| is_rest_expr ( * e) ) ;
835+ let exprs: Vec < _ > = exprs. iter ( ) . filter ( |e| !is_rest_expr ( * * e) ) . copied ( ) . collect ( ) ;
836+
837+ self . infer_tuple_pat_like ( & rhs_ty, ( ) , ellipsis, & exprs)
838+ }
839+ Expr :: Call { callee, args } => {
840+ // Tuple structs
841+ let path = match & self . body [ * callee] {
842+ Expr :: Path ( path) => Some ( path) ,
843+ _ => None ,
844+ } ;
845+
846+ // We don't consider multiple ellipses. This is analogous to
847+ // `hir_def::body::lower::ExprCollector::collect_tuple_pat()`.
848+ let ellipsis = args. iter ( ) . position ( |e| is_rest_expr ( * e) ) ;
849+ let args: Vec < _ > = args. iter ( ) . filter ( |e| !is_rest_expr ( * * e) ) . copied ( ) . collect ( ) ;
850+
851+ self . infer_tuple_struct_pat_like ( path, & rhs_ty, ( ) , lhs, ellipsis, & args)
852+ }
853+ Expr :: Array ( Array :: ElementList ( elements) ) => {
854+ let elem_ty = match rhs_ty. kind ( Interner ) {
855+ TyKind :: Array ( st, _) => st. clone ( ) ,
856+ _ => self . err_ty ( ) ,
857+ } ;
858+
859+ // There's no need to handle `..` as it cannot be bound.
860+ let sub_exprs = elements. iter ( ) . filter ( |e| !is_rest_expr ( * * e) ) ;
861+
862+ for e in sub_exprs {
863+ self . infer_assignee_expr ( * e, & elem_ty) ;
864+ }
865+
866+ match rhs_ty. kind ( Interner ) {
867+ TyKind :: Array ( _, _) => rhs_ty. clone ( ) ,
868+ // Even when `rhs_ty` is not an array type, this assignee
869+ // expression is infered to be an array (of unknown element
870+ // type and length). This should not be just an error type,
871+ // because we are to compute the unifiability of this type and
872+ // `rhs_ty` in the end of this function to issue type mismatches.
873+ _ => TyKind :: Array ( self . err_ty ( ) , crate :: consteval:: usize_const ( None ) )
874+ . intern ( Interner ) ,
875+ }
876+ }
877+ Expr :: RecordLit { path, fields, .. } => {
878+ let subs = fields. iter ( ) . map ( |f| ( f. name . clone ( ) , f. expr ) ) ;
879+
880+ self . infer_record_pat_like ( path. as_deref ( ) , & rhs_ty, ( ) , lhs. into ( ) , subs)
881+ }
882+ Expr :: Underscore => rhs_ty. clone ( ) ,
883+ _ => {
884+ // `lhs` is a place expression, a unit struct, or an enum variant.
885+ let lhs_ty = self . infer_expr ( lhs, & Expectation :: none ( ) ) ;
886+
887+ // This is the only branch where this function may coerce any type.
888+ // We are returning early to avoid the unifiability check below.
889+ let lhs_ty = self . insert_type_vars_shallow ( lhs_ty) ;
890+ let ty = match self . coerce ( None , & rhs_ty, & lhs_ty) {
891+ Ok ( ty) => ty,
892+ Err ( _) => self . err_ty ( ) ,
893+ } ;
894+ self . write_expr_ty ( lhs, ty. clone ( ) ) ;
895+ return ty;
896+ }
897+ } ;
898+
899+ let ty = self . insert_type_vars_shallow ( ty) ;
900+ if !self . unify ( & ty, & rhs_ty) {
901+ self . result
902+ . type_mismatches
903+ . insert ( lhs. into ( ) , TypeMismatch { expected : rhs_ty. clone ( ) , actual : ty. clone ( ) } ) ;
904+ }
905+ self . write_expr_ty ( lhs, ty. clone ( ) ) ;
906+ ty
907+ }
908+
820909 fn infer_overloadable_binop (
821910 & mut self ,
822911 lhs : ExprId ,
0 commit comments