Skip to content
Back to skills

Rust Analyzer Ssr

ASecurity

Use rust-analyzer's Structural Search and Replace (SSR) to change lots of Rust code. SSR matches by AST structure and semantic meaning, understanding type resolution and path equivalence.

  • 88 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 3, 2026
ai-agentsrustbashexpressrefactoringapi

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 3, 2026

npx -y skills add the-void-ia/void-box --skill rust-analyzer-ssr --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Rust Analyzer Ssr?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Rust Analyzer Ssr
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/the-void-ia-rust-analyzer-ssr/badge)](https://www.skillsdirectory.com/skills/the-void-ia-rust-analyzer-ssr)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: rust-analyzer-ssr
description: Use rust-analyzer's Structural Search and Replace (SSR) to change lots of Rust code. SSR matches by AST structure and semantic meaning, understanding type resolution and path equivalence.
---

# rust-analyzer Structural Search and Replace (SSR)

Use rust-analyzer's SSR for semantic code transformations in Rust projects. SSR matches code by AST structure and semantic meaning, not text.

## When to Use

- Refactoring patterns across a codebase (rename, restructure, migrate APIs)
- Converting between equivalent forms (UFCS to method calls, struct literals to constructors)
- Finding all usages of a specific code pattern
- Semantic-aware search that understands type resolution

## Basic Syntax

```
<search_pattern> ==>> <replacement_pattern>
```

Placeholders capture matched code:
- `$name` — matches any expression/type/pattern in that position
- `${name:constraint}` — matches with constraints

## Common Patterns

### Swap function arguments
```
foo($a, $b) ==>> foo($b, $a)
```

### Convert struct literal to constructor
```
Foo { a: $a, b: $b } ==>> Foo::new($a, $b)
```

### UFCS to method call
```
Foo::method($receiver, $arg) ==>> $receiver.method($arg)
```

### Method to UFCS
```
$receiver.method($arg) ==>> Foo::method($receiver, $arg)
```

### Wrap in Result
```
Option<$t> ==>> Result<$t, Error>
```

### Unwrap to expect
```
$e.unwrap() ==>> $e.expect("TODO")
```

### Match only literals
```
Some(${a:kind(literal)}) ==>> ...
```

### Match non-literals
```
Some(${a:not(kind(literal))}) ==>> ...
```

## Constraints

| Constraint | Matches |
|------------|---------|
| `kind(literal)` | Literal values: `42`, `"foo"`, `true` |
| `not(...)` | Negates inner constraint |

## How to Invoke

### Via Comment Assist (Interactive)
Write a comment containing an SSR rule, then trigger code actions:
```rust
// foo($a, $b) ==>> bar($b, $a)
```
Actions appear: "Apply SSR in file" or "Apply SSR in workspace"

### Via LSP Command
```json
{
  "command": "rust-analyzer.ssr",
  "arguments": [{
    "query": "foo($a) ==>> bar($a)",
    "parseOnly": false
  }]
}
```

### Via CLI
```bash
rust-analyzer ssr 'foo($a, $b) ==>> bar($b, $a)'
```

## Key Behaviors

**Path Resolution**: Paths match semantically. `foo::Bar` matches `Bar` if imported from `foo`.

**Auto-qualification**: Replacement paths are qualified appropriately for each insertion site.

**Parenthesization**: Automatic parens added when needed (e.g., `$a + $b` becoming `($a + $b).method()`).

**Comment Preservation**: Comments within matched ranges are preserved.

## Macro Handling

SSR can match code inside macro expansions, but with an important restriction: **all matched tokens must originate from the same source**.

### Example: Macro Boundary

```rust
macro_rules! my_macro {
    ($x:expr) => {
        foo($x, 42)  // "42" comes from macro definition
    };
}

my_macro!(bar);  // "bar" comes from call site
```

The expanded code is `foo(bar, 42)`. Here:
- `bar` originates from the **call site** (what the user wrote)
- `foo`, `42` originate from the **macro definition**

If you search for `foo($a, $b)`:
- It would **NOT** match the expanded `foo(bar, 42)` because `$a` would capture `bar` (call site) but `$b` would capture `42` (definition site) — these cross the macro boundary.

### Why This Limitation Exists

SSR can only generate edits for code the user actually wrote. If a match spans both user code and macro-generated code, SSR couldn't produce a valid edit — it would need to modify the macro definition, which is a different (and potentially shared) piece of code.

### What SSR CAN Do With Macros

- Match code entirely within macro arguments: `my_macro!(foo($a))` can match `foo($a)`
- Match the macro call itself: `my_macro!($x)` works
- Match expanded code where all tokens come from call-site arguments

## Other Limitations

- Constraints limited to `kind(literal)` and `not()`
- Single-identifier patterns (`foo ==>> bar`) may be filtered if ambiguous
- Cannot modify `use` declarations with braces

## More Examples

### Convert Option methods
```
$o.map_or(None, Some) ==>> $o
```

### Change field access
```
$s.foo ==>> $s.bar
```

### Reorder struct fields
```
Foo { a: $a, b: $b } ==>> Foo { b: $b, a: $a }
```

### Generic type transformation
```
Vec<$t> ==>> SmallVec<[$t; 4]>
```

## Source Files

- Core implementation: `crates/ide-ssr/src/`
- IDE integration: `crates/ide/src/ssr.rs`
- Tests with examples: `crates/ide-ssr/src/tests.rs`

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.