rust-lang / rust-lang/rust-analyzer

`destructure_struct_binding` produces intersecting edits when a macro expands the usage twice

Open
#22,556 1 comment 0 reactions 1 assignee View on GitHub

@Albab-Hasan is already working on this.

Since Jun 10, 2026.

A-assists C-bug
Dominant language
Rust
Stars
16.9k
Forks
2.2k
Avg merge
1d 12h
Merged PRs (30d)
72

Description

rust-analyzer version: 0.3.2929-standalone (panic message below is from a source build of master with force-always-assert; on the release build the assist silently does nothing and only logs the error)

rustc version: rustc 1.97.0-nightly (ca9a134e0 2026-04-26)

editor or extension: VSCode, rust-analyzer extension 0.3.2929

relevant settings: none

repository link (if public, optional): n/a

code snippet to reproduce:

macro_rules! m { ($e:expr) => { ($e, $e) }; }

struct S { a: i32 }

fn main() {
    let s2 = S { a: 1 };
    m!(s2.a);
}

reproduce:
cursor on s2 in let s2 = S { a: 1 };
Destructure struct binding

expected:
let S { a } = S { a: 1 }; and m!(a);, or the assist bails on the macro usage. either way no crash.

actual:
on the release build the assist is offered, applies nothing, and logs the error. on a build with debug assertions the request handler panics:

request handler panicked: some replace change ranges intersect!
left change:  ReplaceAll(Token(IDENT@296..298 "s2")..=Token(IDENT@299..300 "a"), [Node(PATH_EXPR@0..1)]) (s2.aa)
equals
right change: ReplaceAll(Token(IDENT@296..298 "s2")..=Token(IDENT@299..300 "a"), [Node(PATH_EXPR@0..1)]) (s2.aa)
panicked at crates/syntax/src/syntax_editor/edit_algo.rs:478:5:
some replace change ranges intersect!

cause:
the macro expands $e twice, so FindUsages returns two FileReferences for the single s2 token in the source. update_usages maps each one back to the same source range and registers two identical ReplaceAll changes, tripping stdx::always!(false, "some replace change ranges intersect!") in edit_algo.rs — the whole edit is discarded. My fix in #21838 fixed this assist for a single usage inside a macro, but not for a macro that duplicates its argument.

note:
same root cause as the destructure_tuple_binding issue, also affects convert_named_struct_to_tuple_struct and convert_tuple_struct_to_named_struct.

env:

  • rustc: 1.97.0-nightly
  • rust-analyzer: 0.3.2929
  • OS: Ubuntu
  • Editor: VS Code

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.