rust-lang / rust-lang/rust-analyzer

Structural search & replace of nested `try!()` causes corruption

Open
#11,591 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

rust-analyzer version: 2022-01-31
rustc version: 1.58.1
relevant settings: N/A


Given the following code:

// abcdefghijklmnopqrstuvwxyz
fn main() {
    try!(try!("what"));
}

running

rust-analyzer ssr 'try!($expr) ==>> $expr?'

produces the following absurd result:

// abcdefghijklmnopqrstuvwxyz
fn main() {
    ijklmn??;
}

I have observed the following properties:

  • Varying the inner invocation's input changes how many characters from the initial 'i' is included.
  • Inserting linebreaks before the comment slides the window to the right by a corresponding number of characters.
  • Inserting linebreaks after the comment does nothing; nor does removing letters from the end of the comment.
  • Removing the ? from the replacement rule (or adding more) does not change the corruption.
  • Adding things to the beginning of the replacement rule (for instance, wrapping it in parentheses) similarly has no effect.
  • Wrapping the input with additional try!()s consumes another input.len() characters for each one you add, although no further ? are added beyond the initial two.
    • This continues past the end of the comment, and will happily generate invalid code (e.g. half of an identifier).

This implies the replacement data is being taken from a location relative to the start of the file, rather than relative to the match itself. I have no idea why this is, and am not sufficiently familiar with rust-analyzer's internals to investigate it further, but knowing these things will probably help with tracking down the problem.

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.

Research direction

Reproduce the issue with the provided nested try!() example and the rust-analyzer ssr command. Start by tracing the structural search-and-replace entry point and how replacement spans are calculated for nested matches. Done means nested replacements use the matched source text and no unrelated comment or file characters are inserted.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.