@@ -593,8 +593,8 @@ impl<'a> InferenceContext<'a> {
593
593
}
594
594
Expr :: BinaryOp { lhs, rhs, op } => match op {
595
595
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 ) ;
598
598
self . result . standard_types . unit . clone ( )
599
599
}
600
600
Some ( BinaryOp :: LogicOp ( _) ) => {
@@ -817,6 +817,95 @@ impl<'a> InferenceContext<'a> {
817
817
}
818
818
}
819
819
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
+
820
909
fn infer_overloadable_binop (
821
910
& mut self ,
822
911
lhs : ExprId ,
0 commit comments