@@ -15,7 +15,7 @@ use ide_db::{
1515} ; 
1616use  itertools:: { izip,  Itertools } ; 
1717use  syntax:: { 
18-  ast:: { self ,  edit:: IndentLevel ,  edit_in_place:: Indent ,  HasArgList ,  PathExpr } , 
18+  ast:: { self ,  edit:: IndentLevel ,  edit_in_place:: Indent ,  HasArgList ,  Pat ,   PathExpr } , 
1919 ted,  AstNode ,  NodeOrToken ,  SyntaxKind , 
2020} ; 
2121
@@ -278,7 +278,7 @@ fn get_fn_params(
278278
279279 let  mut  params = Vec :: new ( ) ; 
280280 if  let  Some ( self_param)  = param_list. self_param ( )  { 
281-  // FIXME this should depend on the receiver as well as the self_param  
281+  // Keep `ref` and `mut` and transform them into `&` and `mut` later  
282282 params. push ( ( 
283283 make:: ident_pat ( 
284284 self_param. amp_token ( ) . is_some ( ) , 
@@ -409,16 +409,56 @@ fn inline(
409409 let  mut  let_stmts = Vec :: new ( ) ; 
410410
411411 // Inline parameter expressions or generate `let` statements depending on whether inlining works or not. 
412-  for  ( ( pat,  param_ty,  _ ) ,  usages,  expr)  in  izip ! ( params,  param_use_nodes,  arguments)  { 
412+  for  ( ( pat,  param_ty,  param ) ,  usages,  expr)  in  izip ! ( params,  param_use_nodes,  arguments)  { 
413413 // izip confuses RA due to our lack of hygiene info currently losing us type info causing incorrect errors 
414414 let  usages:  & [ ast:: PathExpr ]  = & usages; 
415415 let  expr:  & ast:: Expr  = expr; 
416416
417417 let  mut  insert_let_stmt = || { 
418418 let  ty = sema. type_of_expr ( expr) . filter ( TypeInfo :: has_adjustment) . and ( param_ty. clone ( ) ) ; 
419-  let_stmts. push ( 
420-  make:: let_stmt ( pat. clone ( ) ,  ty,  Some ( expr. clone ( ) ) ) . clone_for_update ( ) . into ( ) , 
421-  ) ; 
419+ 
420+  let  is_self = param
421+  . name ( sema. db ) 
422+  . and_then ( |name| name. as_text ( ) ) 
423+  . is_some_and ( |name| name == "self" ) ; 
424+ 
425+  if  is_self { 
426+  let  mut  this_pat = make:: ident_pat ( false ,  false ,  make:: name ( "this" ) ) ; 
427+  let  mut  expr = expr. clone ( ) ; 
428+  match  pat { 
429+  Pat :: IdentPat ( pat)  => match  ( pat. ref_token ( ) ,  pat. mut_token ( ) )  { 
430+  // self => let this = obj 
431+  ( None ,  None )  => { } 
432+  // mut self => let mut this = obj 
433+  ( None ,  Some ( _) )  => { 
434+  this_pat = make:: ident_pat ( false ,  true ,  make:: name ( "this" ) ) ; 
435+  } 
436+  // &self => let this = &obj 
437+  ( Some ( _) ,  None )  => { 
438+  expr = make:: expr_ref ( expr,  false ) ; 
439+  } 
440+  // let foo = &mut X; &mut self => let this = &mut obj 
441+  // let mut foo = X; &mut self => let this = &mut *obj (reborrow) 
442+  ( Some ( _) ,  Some ( _) )  => { 
443+  let  should_reborrow = sema
444+  . type_of_expr ( & expr) 
445+  . map ( |ty| ty. original . is_mutable_reference ( ) ) ; 
446+  expr = if  let  Some ( true )  = should_reborrow { 
447+  make:: expr_reborrow ( expr) 
448+  }  else  { 
449+  make:: expr_ref ( expr,  true ) 
450+  } ; 
451+  } 
452+  } , 
453+  _ => { } 
454+  } ; 
455+  let_stmts
456+  . push ( make:: let_stmt ( this_pat. into ( ) ,  ty,  Some ( expr) ) . clone_for_update ( ) . into ( ) ) 
457+  }  else  { 
458+  let_stmts. push ( 
459+  make:: let_stmt ( pat. clone ( ) ,  ty,  Some ( expr. clone ( ) ) ) . clone_for_update ( ) . into ( ) , 
460+  ) ; 
461+  } 
422462 } ; 
423463
424464 // check if there is a local var in the function that conflicts with parameter 
0 commit comments