Skip to content

Commit 306defa

Browse files
committed
Auto merge of rust-lang#16114 - roife:fix-inline-with-self-type, r=Veykril
fix: self type replacement in inline-function Fix rust-lang#16113, fix rust-lang#16091 The problem described in this issue actually involves three bugs. Firstly, when using `ted` to modify the syntax tree, the offset of nodes on the tree changes, which causes the syntax range information from `hir` to become invalid. Therefore, we need to edit the AST after the last usage for `usages_for_locals`. The second issue is that when inserting nodes, it's necessary to use `clone_subtree` for duplication because the `ted::replace` operation essentially moves a node. The third issue is that we should use `ancestors_with_macros` instead of `ancestors` to handle impl definition in macros. I have fixed the three bugs mentioned above and added unit tests.
2 parents 792c946 + 38b5dcb commit 306defa

File tree

1 file changed

+123
-11
lines changed

1 file changed

+123
-11
lines changed

crates/ide-assists/src/handlers/inline_call.rs

Lines changed: 123 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -315,17 +315,6 @@ fn inline(
315315
} else {
316316
fn_body.clone_for_update()
317317
};
318-
if let Some(imp) = body.syntax().ancestors().find_map(ast::Impl::cast) {
319-
if !node.syntax().ancestors().any(|anc| &anc == imp.syntax()) {
320-
if let Some(t) = imp.self_ty() {
321-
body.syntax()
322-
.descendants_with_tokens()
323-
.filter_map(NodeOrToken::into_token)
324-
.filter(|tok| tok.kind() == SyntaxKind::SELF_TYPE_KW)
325-
.for_each(|tok| ted::replace(tok, t.syntax()));
326-
}
327-
}
328-
}
329318
let usages_for_locals = |local| {
330319
Definition::Local(local)
331320
.usages(sema)
@@ -381,6 +370,27 @@ fn inline(
381370
}
382371
}
383372

373+
// We should place the following code after last usage of `usages_for_locals`
374+
// because `ted::replace` will change the offset in syntax tree, which makes
375+
// `FileReference` incorrect
376+
if let Some(imp) =
377+
sema.ancestors_with_macros(fn_body.syntax().clone()).find_map(ast::Impl::cast)
378+
{
379+
if !node.syntax().ancestors().any(|anc| &anc == imp.syntax()) {
380+
if let Some(t) = imp.self_ty() {
381+
while let Some(self_tok) = body
382+
.syntax()
383+
.descendants_with_tokens()
384+
.filter_map(NodeOrToken::into_token)
385+
.find(|tok| tok.kind() == SyntaxKind::SELF_TYPE_KW)
386+
{
387+
let replace_with = t.clone_subtree().syntax().clone_for_update();
388+
ted::replace(self_tok, replace_with);
389+
}
390+
}
391+
}
392+
}
393+
384394
let mut func_let_vars: BTreeSet<String> = BTreeSet::new();
385395

386396
// grab all of the local variable declarations in the function
@@ -1510,4 +1520,106 @@ fn main() {
15101520
"#,
15111521
);
15121522
}
1523+
1524+
#[test]
1525+
fn inline_call_with_multiple_self_types_eq() {
1526+
check_assist(
1527+
inline_call,
1528+
r#"
1529+
#[derive(PartialEq, Eq)]
1530+
enum Enum {
1531+
A,
1532+
B,
1533+
}
1534+
1535+
impl Enum {
1536+
fn a_or_b_eq(&self) -> bool {
1537+
self == &Self::A || self == &Self::B
1538+
}
1539+
}
1540+
1541+
fn a() -> bool {
1542+
Enum::A.$0a_or_b_eq()
1543+
}
1544+
"#,
1545+
r#"
1546+
#[derive(PartialEq, Eq)]
1547+
enum Enum {
1548+
A,
1549+
B,
1550+
}
1551+
1552+
impl Enum {
1553+
fn a_or_b_eq(&self) -> bool {
1554+
self == &Self::A || self == &Self::B
1555+
}
1556+
}
1557+
1558+
fn a() -> bool {
1559+
{
1560+
let ref this = Enum::A;
1561+
this == &Enum::A || this == &Enum::B
1562+
}
1563+
}
1564+
"#,
1565+
)
1566+
}
1567+
1568+
#[test]
1569+
fn inline_call_with_self_type_in_macros() {
1570+
check_assist(
1571+
inline_call,
1572+
r#"
1573+
trait Trait<T1> {
1574+
fn f(a: T1) -> Self;
1575+
}
1576+
1577+
macro_rules! impl_from {
1578+
($t: ty) => {
1579+
impl Trait<$t> for $t {
1580+
fn f(a: $t) -> Self {
1581+
a as Self
1582+
}
1583+
}
1584+
};
1585+
}
1586+
1587+
struct A {}
1588+
1589+
impl_from!(A);
1590+
1591+
fn main() {
1592+
let a: A = A{};
1593+
let b = <A as Trait<A>>::$0f(a);
1594+
}
1595+
"#,
1596+
r#"
1597+
trait Trait<T1> {
1598+
fn f(a: T1) -> Self;
1599+
}
1600+
1601+
macro_rules! impl_from {
1602+
($t: ty) => {
1603+
impl Trait<$t> for $t {
1604+
fn f(a: $t) -> Self {
1605+
a as Self
1606+
}
1607+
}
1608+
};
1609+
}
1610+
1611+
struct A {}
1612+
1613+
impl_from!(A);
1614+
1615+
fn main() {
1616+
let a: A = A{};
1617+
let b = {
1618+
let a = a;
1619+
a as A
1620+
};
1621+
}
1622+
"#,
1623+
)
1624+
}
15131625
}

0 commit comments

Comments
 (0)