@@ -15,7 +15,7 @@ use ide_db::{
15
15
} ;
16
16
use itertools:: { izip, Itertools } ;
17
17
use syntax:: {
18
- ast:: { self , edit:: IndentLevel , edit_in_place:: Indent , HasArgList , PathExpr } ,
18
+ ast:: { self , edit:: IndentLevel , edit_in_place:: Indent , HasArgList , Pat , PathExpr } ,
19
19
ted, AstNode , NodeOrToken , SyntaxKind ,
20
20
} ;
21
21
@@ -278,7 +278,7 @@ fn get_fn_params(
278
278
279
279
let mut params = Vec :: new ( ) ;
280
280
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
282
282
params. push ( (
283
283
make:: ident_pat (
284
284
self_param. amp_token ( ) . is_some ( ) ,
@@ -409,16 +409,56 @@ fn inline(
409
409
let mut let_stmts = Vec :: new ( ) ;
410
410
411
411
// 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) {
413
413
// izip confuses RA due to our lack of hygiene info currently losing us type info causing incorrect errors
414
414
let usages: & [ ast:: PathExpr ] = & usages;
415
415
let expr: & ast:: Expr = expr;
416
416
417
417
let mut insert_let_stmt = || {
418
418
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
+ }
422
462
} ;
423
463
424
464
// check if there is a local var in the function that conflicts with parameter
0 commit comments