rust-lang/rust-analyzer · error

Not a valid Rust expression, type, item, path or pattern

Error message

Not a valid Rust expression, type, item, path or pattern

What it means

`ParsedRule::new` delegates to `build`, which parses the user's search/replacement pattern into `ParsedRule`s. If nothing could be parsed into a rule — the token stream produced no rules — the library rejects the pattern string because it is not a Rust expression, type, item, path, or pattern, i.e. it is syntactically meaningless to SSR.

Source

Thrown at crates/ide-ssr/src/parsing.rs:118

    ) {
        match (pattern, template) {
            (Ok(pattern), Some(Ok(template))) => self.rules.push(ParsedRule {
                placeholders_by_stand_in: self.placeholders_by_stand_in.clone(),
                pattern,
                template: Some(template),
            }),
            (Ok(pattern), None) => self.rules.push(ParsedRule {
                placeholders_by_stand_in: self.placeholders_by_stand_in.clone(),
                pattern,
                template: None,
            }),
            _ => {}
        }
    }

    fn build(mut self) -> Result<Vec<ParsedRule>, SsrError> {
        if self.rules.is_empty() {
            bail!("Not a valid Rust expression, type, item, path or pattern");
        }
        // If any rules contain paths, then we reject any rules that don't contain paths. Allowing a
        // mix leads to strange semantics, since the path-based rules only match things where the
        // path refers to semantically the same thing, whereas the non-path-based rules could match
        // anything. Specifically, if we have a rule like `foo ==>> bar` we only want to match the
        // `foo` that is in the current scope, not any `foo`. However "foo" can be parsed as a
        // pattern (IDENT_PAT -> NAME -> IDENT). Allowing such a rule through would result in
        // renaming everything called `foo` to `bar`. It'd also be slow, since without a path, we'd
        // have to use the slow-scan search mechanism.
        if self.rules.iter().any(|rule| contains_path(&rule.pattern)) {
            let old_len = self.rules.len();
            self.rules.retain(|rule| contains_path(&rule.pattern));
            if self.rules.len() < old_len {
                cov_mark::hit!(pattern_is_a_single_segment_path);
            }
        }
        Ok(self.rules)
    }

View on GitHub (pinned to e8f7e90aa3)

Solutions

  1. Verify the pattern string is non-empty and contains real Rust syntax (e.g. `foo()`, `Some($x)`, `foo($a) ==>> bar($a)`).
  2. Print/log the exact string reaching SSR — shell quoting or config interpolation may have mangled it.
  3. Feed a minimal known-good pattern to confirm the API wiring, then build up your real pattern incrementally.
  4. Check for unbalanced parentheses/brackets that cause the whole parse to be discarded.

Example fix

// before
let rule = SsrPattern::new("$"); // garbage -> no rules parsed
// after
let rule = SsrPattern::new("foo($arg) ==>> bar($arg)").unwrap();
Defensive patterns

Strategy: validation

Validate before calling

fn looks_like_pattern(s: &str) -> bool {
    let t = s.trim();
    !t.is_empty() && t.chars().any(|c| !c.is_whitespace()) && t.contains(|c: char| c.is_alphanumeric() || c == '_')
}
// then: anyhow::ensure!(looks_like_pattern(&pat), "invalid SSR pattern: {:?}", pat);

Type guard

fn is_valid_rule_input(s: &str) -> bool {
    matches!(s.trim(), t if !t.is_empty() && rust_lexer_yields_tokens(t))
}

Try / catch

match SsrPattern::new(&pat) {
    Ok(p) => p,
    Err(e) if e.to_string().contains("Not a valid Rust") => {
        eprintln!("Pattern {:?} is not valid Rust syntax; check quoting/escaping", pat);
        return Ok(());
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling `SsrPattern::new`/`from_str` with a pattern string that parses to zero rules — e.g. an empty string, only whitespace/comments, or text that the parser cannot interpret as any of expression/type/item/path/pattern (garbage tokens, unbalanced delimiters consumed as trivia).

Common situations: Typo or truncation when passing an SSR rule from a CLI flag or editor config; shell quoting stripping the pattern (e.g. `$var` expanded away); passing a full `foo ==>> bar` rule string where only a pattern is expected, or vice versa, causing parse failure.

Related errors


AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03). Data as JSON: /api/errors/984b7106a5920c32. Report an issue: GitHub.