@@ -2247,7 +2247,8 @@ fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
22472247 base_expr : & ' tcx hir:: Expr ,
22482248 base_ty : Ty < ' tcx > ,
22492249 idx_ty : Ty < ' tcx > ,
2250- lvalue_pref : LvaluePreference )
2250+ lvalue_pref : LvaluePreference ,
2251+ is_assignment : bool )
22512252 -> Option < ( /*index type*/ Ty < ' tcx > , /*element type*/ Ty < ' tcx > ) >
22522253{
22532254 // FIXME(#18741) -- this is almost but not quite the same as the
@@ -2262,7 +2263,7 @@ fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
22622263 lvalue_pref,
22632264 |adj_ty, idx| {
22642265 try_index_step ( fcx, MethodCall :: expr ( expr. id ) , expr, base_expr,
2265- adj_ty, idx, false , lvalue_pref, idx_ty)
2266+ adj_ty, idx, false , lvalue_pref, idx_ty, is_assignment )
22662267 } ) ;
22672268
22682269 if final_mt. is_some ( ) {
@@ -2274,7 +2275,7 @@ fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
22742275 if let ty:: TyArray ( element_ty, _) = ty. sty {
22752276 let adjusted_ty = fcx. tcx ( ) . mk_slice ( element_ty) ;
22762277 try_index_step ( fcx, MethodCall :: expr ( expr. id ) , expr, base_expr,
2277- adjusted_ty, autoderefs, true , lvalue_pref, idx_ty)
2278+ adjusted_ty, autoderefs, true , lvalue_pref, idx_ty, is_assignment )
22782279 } else {
22792280 None
22802281 }
@@ -2292,21 +2293,45 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
22922293 autoderefs : usize ,
22932294 unsize : bool ,
22942295 lvalue_pref : LvaluePreference ,
2295- index_ty : Ty < ' tcx > )
2296+ index_ty : Ty < ' tcx > ,
2297+ is_assignment : bool )
22962298 -> Option < ( /*index type*/ Ty < ' tcx > , /*element type*/ Ty < ' tcx > ) >
22972299{
22982300 let tcx = fcx. tcx ( ) ;
22992301 debug ! ( "try_index_step(expr={:?}, base_expr.id={:?}, adjusted_ty={:?}, \
2300- autoderefs={}, unsize={}, index_ty={:?})",
2302+ autoderefs={}, unsize={}, index_ty={:?}, is_assignment={} )",
23012303 expr,
23022304 base_expr,
23032305 adjusted_ty,
23042306 autoderefs,
23052307 unsize,
2306- index_ty) ;
2308+ index_ty,
2309+ is_assignment) ;
23072310
23082311 let input_ty = fcx. infcx ( ) . next_ty_var ( ) ;
23092312
2313+ // Try `IndexAssign` if this is an assignment operation
2314+ if is_assignment {
2315+ return tcx. lang_items . index_assign_trait ( ) . and_then ( |trait_did| {
2316+ let rhs_ty = fcx. infcx ( ) . next_ty_var ( ) ;
2317+
2318+ method:: lookup_in_trait_adjusted ( fcx,
2319+ expr. span ,
2320+ Some ( & * base_expr) ,
2321+ token:: intern ( "index_assign" ) ,
2322+ trait_did,
2323+ autoderefs,
2324+ unsize,
2325+ adjusted_ty,
2326+ Some ( vec ! [ input_ty, rhs_ty] ) )
2327+ . map ( |method| {
2328+ fcx. inh . tables . borrow_mut ( ) . method_map . insert ( method_call, method) ;
2329+
2330+ ( input_ty, rhs_ty)
2331+ } )
2332+ } )
2333+ }
2334+
23102335 // First, try built-in indexing.
23112336 match ( adjusted_ty. builtin_index ( ) , & index_ty. sty ) {
23122337 ( Some ( ty) , & ty:: TyUint ( ast:: TyUs ) ) | ( Some ( ty) , & ty:: TyInfer ( ty:: IntVar ( _) ) ) => {
@@ -3445,25 +3470,56 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
34453470 fcx. write_ty ( id, fcx. infcx ( ) . next_diverging_ty_var ( ) ) ;
34463471 }
34473472 hir:: ExprAssign ( ref lhs, ref rhs) => {
3448- check_expr_with_lvalue_pref ( fcx, & * * lhs, PreferMutLvalue ) ;
3473+ if let hir:: ExprIndex ( ref base, ref idx) = lhs. node {
3474+ let lvalue_pref = PreferMutLvalue ;
3475+
3476+ check_expr_with_lvalue_pref ( fcx, & * * base, lvalue_pref) ;
3477+ check_expr ( fcx, & * * idx) ;
3478+
3479+ let base_t = structurally_resolved_type ( fcx, lhs. span , fcx. expr_ty ( & * * base) ) ;
3480+ let idx_t = fcx. expr_ty ( & * * idx) ;
3481+
3482+ lookup_indexing ( fcx, expr, base, base_t, idx_t, lvalue_pref, true )
3483+ . map ( |( index_ty, rhs_ty) | {
3484+ demand:: eqtype ( fcx, idx. span , index_ty, idx_t) ;
3485+ check_expr_coercable_to_type ( fcx, & * * rhs, rhs_ty) ;
3486+ fcx. write_nil ( lhs. id ) ;
3487+ fcx. write_nil ( id) ;
3488+
3489+ if !tcx. sess . features . borrow ( ) . indexed_assignments {
3490+ tcx. sess . span_err (
3491+ expr. span ,
3492+ "overloaded indexed assignments are not stable" ) ;
3493+ fileline_help ! (
3494+ tcx. sess,
3495+ expr. span,
3496+ "add `#![feature(indexed_assignments)]` to the crate features to \
3497+ enable") ;
3498+ }
3499+ } )
3500+ } else {
3501+ None
3502+ } . unwrap_or_else ( || {
3503+ check_expr_with_lvalue_pref ( fcx, & * * lhs, PreferMutLvalue ) ;
34493504
3450- let tcx = fcx. tcx ( ) ;
3451- if !tcx. expr_is_lval ( & * * lhs) {
3452- span_err ! ( tcx. sess, expr. span, E0070 ,
3453- "invalid left-hand side expression" ) ;
3454- }
3505+ let tcx = fcx. tcx ( ) ;
3506+ if !tcx. expr_is_lval ( & * * lhs) {
3507+ span_err ! ( tcx. sess, expr. span, E0070 ,
3508+ "invalid left-hand side expression" ) ;
3509+ }
34553510
3456- let lhs_ty = fcx. expr_ty ( & * * lhs) ;
3457- check_expr_coercable_to_type ( fcx, & * * rhs, lhs_ty) ;
3458- let rhs_ty = fcx. expr_ty ( & * * rhs) ;
3511+ let lhs_ty = fcx. expr_ty ( & * * lhs) ;
3512+ check_expr_coercable_to_type ( fcx, & * * rhs, lhs_ty) ;
3513+ let rhs_ty = fcx. expr_ty ( & * * rhs) ;
34593514
3460- fcx. require_expr_have_sized_type ( & * * lhs, traits:: AssignmentLhsSized ) ;
3515+ fcx. require_expr_have_sized_type ( & * * lhs, traits:: AssignmentLhsSized ) ;
34613516
3462- if lhs_ty. references_error ( ) || rhs_ty. references_error ( ) {
3463- fcx. write_error ( id) ;
3464- } else {
3465- fcx. write_nil ( id) ;
3466- }
3517+ if lhs_ty. references_error ( ) || rhs_ty. references_error ( ) {
3518+ fcx. write_error ( id) ;
3519+ } else {
3520+ fcx. write_nil ( id) ;
3521+ }
3522+ } )
34673523 }
34683524 hir:: ExprIf ( ref cond, ref then_blk, ref opt_else_expr) => {
34693525 check_then_else ( fcx, & * * cond, & * * then_blk, opt_else_expr. as_ref ( ) . map ( |e| & * * e) ,
@@ -3666,7 +3722,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
36663722 fcx. write_ty ( id, idx_t) ;
36673723 } else {
36683724 let base_t = structurally_resolved_type ( fcx, expr. span , base_t) ;
3669- match lookup_indexing ( fcx, expr, base, base_t, idx_t, lvalue_pref) {
3725+ match lookup_indexing ( fcx, expr, base, base_t, idx_t, lvalue_pref, false ) {
36703726 Some ( ( index_ty, element_ty) ) => {
36713727 let idx_expr_ty = fcx. expr_ty ( idx) ;
36723728 demand:: eqtype ( fcx, expr. span , index_ty, idx_expr_ty) ;
0 commit comments