@@ -3412,19 +3412,37 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3412
3412
"field `{}` of struct `{}` is private" ,
3413
3413
field, struct_path) ;
3414
3414
// Also check if an accessible method exists, which is often what is meant.
3415
- if self . method_exists ( field, expr_t, expr. id , false ) {
3416
- err. note ( & format ! ( "a method `{}` also exists, perhaps you wish to call it" , field) ) ;
3415
+ if self . method_exists ( field, expr_t, expr. id , false ) && !self . expr_in_place ( expr. id ) {
3416
+ self . suggest_method_call (
3417
+ & mut err,
3418
+ & format ! ( "a method `{}` also exists, call it with parentheses" , field) ,
3419
+ field,
3420
+ expr_t,
3421
+ expr. id ,
3422
+ ) ;
3417
3423
}
3418
3424
err. emit ( ) ;
3419
3425
field_ty
3420
3426
} else if field. name == keywords:: Invalid . name ( ) {
3421
3427
self . tcx ( ) . types . err
3422
3428
} else if self . method_exists ( field, expr_t, expr. id , true ) {
3423
- type_error_struct ! ( self . tcx( ) . sess, field. span, expr_t, E0615 ,
3429
+ let mut err = type_error_struct ! ( self . tcx( ) . sess, field. span, expr_t, E0615 ,
3424
3430
"attempted to take value of method `{}` on type `{}`" ,
3425
- field, expr_t)
3426
- . help ( "maybe a `()` to call it is missing?" )
3427
- . emit ( ) ;
3431
+ field, expr_t) ;
3432
+
3433
+ if !self . expr_in_place ( expr. id ) {
3434
+ self . suggest_method_call (
3435
+ & mut err,
3436
+ "use parentheses to call the method" ,
3437
+ field,
3438
+ expr_t,
3439
+ expr. id
3440
+ ) ;
3441
+ } else {
3442
+ err. help ( "methods are immutable and cannot be assigned to" ) ;
3443
+ }
3444
+
3445
+ err. emit ( ) ;
3428
3446
self . tcx ( ) . types . err
3429
3447
} else {
3430
3448
if !expr_t. is_primitive_ty ( ) {
@@ -5435,6 +5453,28 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5435
5453
original_values,
5436
5454
query_result)
5437
5455
}
5456
+
5457
+ /// Returns whether an expression is contained inside the LHS of an assignment expression.
5458
+ fn expr_in_place ( & self , mut expr_id : ast:: NodeId ) -> bool {
5459
+ let mut contained_in_place = false ;
5460
+
5461
+ while let hir:: Node :: Expr ( parent_expr) =
5462
+ self . tcx . hir ( ) . get ( self . tcx . hir ( ) . get_parent_node ( expr_id) )
5463
+ {
5464
+ match & parent_expr. node {
5465
+ hir:: ExprKind :: Assign ( lhs, ..) | hir:: ExprKind :: AssignOp ( _, lhs, ..) => {
5466
+ if lhs. id == expr_id {
5467
+ contained_in_place = true ;
5468
+ break ;
5469
+ }
5470
+ }
5471
+ _ => ( ) ,
5472
+ }
5473
+ expr_id = parent_expr. id ;
5474
+ }
5475
+
5476
+ contained_in_place
5477
+ }
5438
5478
}
5439
5479
5440
5480
pub fn check_bounds_are_used < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
0 commit comments