@@ -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