@@ -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
@@ -484,12 +524,10 @@ fn inline(
484
524
body = make:: block_expr ( let_stmts, Some ( body. into ( ) ) ) . clone_for_update ( ) ;
485
525
}
486
526
} else if let Some ( stmt_list) = body. stmt_list ( ) {
487
- ted:: insert_all (
488
- ted:: Position :: after (
489
- stmt_list. l_curly_token ( ) . expect ( "L_CURLY for StatementList is missing." ) ,
490
- ) ,
491
- let_stmts. into_iter ( ) . map ( |stmt| stmt. syntax ( ) . clone ( ) . into ( ) ) . collect ( ) ,
492
- ) ;
527
+ let position = stmt_list. l_curly_token ( ) . expect ( "L_CURLY for StatementList is missing." ) ;
528
+ let_stmts. into_iter ( ) . rev ( ) . for_each ( |let_stmt| {
529
+ ted:: insert ( ted:: Position :: after ( position. clone ( ) ) , let_stmt. syntax ( ) . clone ( ) ) ;
530
+ } ) ;
493
531
}
494
532
495
533
let original_indentation = match node {
@@ -721,7 +759,7 @@ impl Foo {
721
759
722
760
fn main() {
723
761
let x = {
724
- let ref this = Foo(3);
762
+ let this = & Foo(3);
725
763
Foo(this.0 + 2)
726
764
};
727
765
}
@@ -757,7 +795,7 @@ impl Foo {
757
795
758
796
fn main() {
759
797
let x = {
760
- let ref this = Foo(3);
798
+ let this = & Foo(3);
761
799
Foo(this.0 + 2)
762
800
};
763
801
}
@@ -795,7 +833,7 @@ impl Foo {
795
833
fn main() {
796
834
let mut foo = Foo(3);
797
835
{
798
- let ref mut this = foo;
836
+ let this = &mut foo;
799
837
this.0 = 0;
800
838
};
801
839
}
@@ -882,7 +920,7 @@ impl Foo {
882
920
}
883
921
fn bar(&self) {
884
922
{
885
- let ref this = self;
923
+ let this = & self;
886
924
this;
887
925
this;
888
926
};
@@ -1557,7 +1595,7 @@ impl Enum {
1557
1595
1558
1596
fn a() -> bool {
1559
1597
{
1560
- let ref this = Enum::A;
1598
+ let this = & Enum::A;
1561
1599
this == &Enum::A || this == &Enum::B
1562
1600
}
1563
1601
}
@@ -1619,6 +1657,82 @@ fn main() {
1619
1657
a as A
1620
1658
};
1621
1659
}
1660
+ "# ,
1661
+ )
1662
+ }
1663
+
1664
+ #[ test]
1665
+ fn method_by_reborrow ( ) {
1666
+ check_assist (
1667
+ inline_call,
1668
+ r#"
1669
+ pub struct Foo(usize);
1670
+
1671
+ impl Foo {
1672
+ fn add1(&mut self) {
1673
+ self.0 += 1;
1674
+ }
1675
+ }
1676
+
1677
+ pub fn main() {
1678
+ let f = &mut Foo(0);
1679
+ f.add1$0();
1680
+ }
1681
+ "# ,
1682
+ r#"
1683
+ pub struct Foo(usize);
1684
+
1685
+ impl Foo {
1686
+ fn add1(&mut self) {
1687
+ self.0 += 1;
1688
+ }
1689
+ }
1690
+
1691
+ pub fn main() {
1692
+ let f = &mut Foo(0);
1693
+ {
1694
+ let this = &mut *f;
1695
+ this.0 += 1;
1696
+ };
1697
+ }
1698
+ "# ,
1699
+ )
1700
+ }
1701
+
1702
+ #[ test]
1703
+ fn method_by_mut ( ) {
1704
+ check_assist (
1705
+ inline_call,
1706
+ r#"
1707
+ pub struct Foo(usize);
1708
+
1709
+ impl Foo {
1710
+ fn add1(mut self) {
1711
+ self.0 += 1;
1712
+ }
1713
+ }
1714
+
1715
+ pub fn main() {
1716
+ let mut f = Foo(0);
1717
+ f.add1$0();
1718
+ }
1719
+ "# ,
1720
+ r#"
1721
+ pub struct Foo(usize);
1722
+
1723
+ impl Foo {
1724
+ fn add1(mut self) {
1725
+ self.0 += 1;
1726
+ }
1727
+ }
1728
+
1729
+ pub fn main() {
1730
+ let mut f = Foo(0);
1731
+ {
1732
+ let mut this = f;
1733
+ this.0 += 1;
1734
+ };
1735
+ }
1622
1736
"# ,
1623
1737
)
1624
1738
}
0 commit comments