@@ -822,82 +822,72 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
822822 expr : & hir:: Expr < ' _ > ,
823823 error : Option < TypeError < ' tcx > > ,
824824 ) -> bool {
825- let Some ( TypeError :: Sorts ( ExpectedFound { expected, found } ) ) = error else { return false } ;
826- let ty:: Ref ( _, inner, hir:: Mutability :: Not ) = expected. kind ( ) else { return false } ;
827- if !self . can_eq ( self . param_env , * inner, found) {
828- // The difference between the expected and found values isn't one level of borrowing.
829- return false ;
830- }
831- // We have an `ident = expr;` assignment.
832- let hir:: Node :: Expr ( hir:: Expr { kind : hir:: ExprKind :: Assign ( lhs, rhs, _) , .. } ) =
833- self . tcx . parent_hir_node ( expr. hir_id )
834- else {
835- return false ;
836- } ;
837- if rhs. hir_id != expr. hir_id || expected. is_closure ( ) {
838- return false ;
839- }
840- // We are assigning to some binding.
841- let hir:: ExprKind :: Path ( hir:: QPath :: Resolved (
842- None ,
843- hir:: Path { res : hir:: def:: Res :: Local ( hir_id) , .. } ,
844- ) ) = lhs. kind
845- else {
846- return false ;
847- } ;
848- let hir:: Node :: Pat ( pat) = self . tcx . hir_node ( * hir_id) else { return false } ;
849- // The pattern we have is an fn argument.
850- let hir:: Node :: Param ( hir:: Param { ty_span, .. } ) = self . tcx . parent_hir_node ( pat. hir_id )
851- else {
852- return false ;
853- } ;
854- let item = self . tcx . hir ( ) . get_parent_item ( pat. hir_id ) ;
855- let item = self . tcx . hir_owner_node ( item) ;
856- let Some ( fn_decl) = item. fn_decl ( ) else { return false } ;
825+ if let Some ( TypeError :: Sorts ( ExpectedFound { expected, found } ) ) = error
826+ && let ty:: Ref ( _, inner, hir:: Mutability :: Not ) = expected. kind ( )
857827
858- // We have a mutable binding in the argument.
859- let hir:: PatKind :: Binding ( hir:: BindingMode :: MUT , _hir_id, ident, _) = pat. kind else {
860- return false ;
861- } ;
828+ // The difference between the expected and found values is one level of borrowing.
829+ && self . can_eq ( self . param_env , * inner, found)
862830
863- // Look for the type corresponding to the argument pattern we have in the argument list.
864- let Some ( ty_sugg) = fn_decl
865- . inputs
866- . iter ( )
867- . filter_map ( |ty| {
868- if ty. span == * ty_span
869- && let hir:: TyKind :: Ref ( lt, mut_ty) = ty. kind
870- {
871- // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
872- Some ( (
873- mut_ty. ty . span . shrink_to_lo ( ) ,
874- format ! (
875- "{}mut " ,
876- if lt. ident. span. lo( ) == lt. ident. span. hi( ) { "" } else { " " }
877- ) ,
878- ) )
879- } else {
880- None
881- }
882- } )
883- . next ( )
884- else {
885- return false ;
886- } ;
887- let sugg = vec ! [
888- ty_sugg,
889- ( pat. span. until( ident. span) , String :: new( ) ) ,
890- ( lhs. span. shrink_to_lo( ) , "*" . to_string( ) ) ,
891- ] ;
892- // We suggest changing the argument from `mut ident: &Ty` to `ident: &'_ mut Ty` and the
893- // assignment from `ident = val;` to `*ident = val;`.
894- err. multipart_suggestion_verbose (
895- "you might have meant to mutate the pointed at value being passed in, instead of \
896- changing the reference in the local binding",
897- sugg,
898- Applicability :: MaybeIncorrect ,
899- ) ;
900- return true ;
831+ // We have an `ident = expr;` assignment.
832+ && let hir:: Node :: Expr ( hir:: Expr { kind : hir:: ExprKind :: Assign ( lhs, rhs, _) , .. } ) =
833+ self . tcx . parent_hir_node ( expr. hir_id )
834+ && rhs. hir_id == expr. hir_id
835+
836+ // We are assigning to some binding.
837+ && let hir:: ExprKind :: Path ( hir:: QPath :: Resolved (
838+ None ,
839+ hir:: Path { res : hir:: def:: Res :: Local ( hir_id) , .. } ,
840+ ) ) = lhs. kind
841+ && let hir:: Node :: Pat ( pat) = self . tcx . hir_node ( * hir_id)
842+
843+ // The pattern we have is an fn argument.
844+ && let hir:: Node :: Param ( hir:: Param { ty_span, .. } ) =
845+ self . tcx . parent_hir_node ( pat. hir_id )
846+ && let item = self . tcx . hir ( ) . get_parent_item ( pat. hir_id )
847+ && let item = self . tcx . hir_owner_node ( item)
848+ && let Some ( fn_decl) = item. fn_decl ( )
849+
850+ // We have a mutable binding in the argument.
851+ && let hir:: PatKind :: Binding ( hir:: BindingMode :: MUT , _hir_id, ident, _) = pat. kind
852+
853+ // Look for the type corresponding to the argument pattern we have in the argument list.
854+ && let Some ( ty_sugg) = fn_decl
855+ . inputs
856+ . iter ( )
857+ . filter_map ( |ty| {
858+ if ty. span == * ty_span
859+ && let hir:: TyKind :: Ref ( lt, x) = ty. kind
860+ {
861+ // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
862+ Some ( (
863+ x. ty . span . shrink_to_lo ( ) ,
864+ format ! (
865+ "{}mut " ,
866+ if lt. ident. span. lo( ) == lt. ident. span. hi( ) { "" } else { " " }
867+ ) ,
868+ ) )
869+ } else {
870+ None
871+ }
872+ } )
873+ . next ( )
874+ {
875+ let sugg = vec ! [
876+ ty_sugg,
877+ ( pat. span. until( ident. span) , String :: new( ) ) ,
878+ ( lhs. span. shrink_to_lo( ) , "*" . to_string( ) ) ,
879+ ] ;
880+ // We suggest changing the argument from `mut ident: &Ty` to `ident: &'_ mut Ty` and the
881+ // assignment from `ident = val;` to `*ident = val;`.
882+ err. multipart_suggestion_verbose (
883+ "you might have meant to mutate the pointed at value being passed in, instead of \
884+ changing the reference in the local binding",
885+ sugg,
886+ Applicability :: MaybeIncorrect ,
887+ ) ;
888+ return true ;
889+ }
890+ false
901891 }
902892
903893 fn annotate_alternative_method_deref (
0 commit comments