rust-lang/rust-analyzer · error · SsrError
Expected ident, found {:?} while parsing kind constraint
Error message
Expected ident, found {:?} while parsing kind constraint What it means
Inside a kind(...) constraint, SSR expects exactly one identifier naming the node kind, then a closing ')'. If the token found where the identifier should be is not a SyntaxKind::IDENT, this error reports the unexpected token kind via {:?}. It comes from parse_constraint, which is reachable both directly from parse_placeholder and recursively via the 'not(...)' constraint.
Source
Thrown at crates/ide-ssr/src/parsing.rs:318
}
let name = name.ok_or_else(|| SsrError::new("Placeholder ($) with no name"))?;
Ok(Placeholder::new(name, constraints))
}
fn parse_constraint(tokens: &mut std::vec::IntoIter<Token>) -> Result<Constraint, SsrError> {
let constraint_type = tokens
.next()
.ok_or_else(|| SsrError::new("Found end of placeholder while looking for a constraint"))?
.text
.to_string();
match constraint_type.as_str() {
"kind" => {
expect_token(tokens, "(")?;
let t = tokens.next().ok_or_else(|| {
SsrError::new("Unexpected end of constraint while looking for kind")
})?;
if t.kind != SyntaxKind::IDENT {
bail!("Expected ident, found {:?} while parsing kind constraint", t.kind);
}
expect_token(tokens, ")")?;
Ok(Constraint::Kind(NodeKind::from(&t.text)?))
}
"not" => {
expect_token(tokens, "(")?;
let sub = parse_constraint(tokens)?;
expect_token(tokens, ")")?;
Ok(Constraint::Not(Box::new(sub)))
}
x => bail!("Unsupported constraint type '{}'", x),
}
}
fn expect_token(tokens: &mut std::vec::IntoIter<Token>, expected: &str) -> Result<(), SsrError> {
if let Some(t) = tokens.next() {
if t.text == expected {
return Ok(());View on GitHub (pinned to e8f7e90aa3)
Solutions
- Pass the kind name as a bare unquoted identifier: kind(literal)
- Ensure exactly one identifier appears between kind( and )
- Check the reported token kind in the message to see what the parser actually found
Example fix
// before let pattern = "$x:kind(\"literal\")"; // after let pattern = "$x:kind(literal)";
Defensive patterns
Strategy: validation
Validate before calling
fn valid_kind_constraint(p: &str) -> bool {
if let Some(idx) = p.find("kind(") {
let rest = &p[idx + 5..];
let mut chars = rest.chars();
match chars.next() {
Some(c) if c.is_alphabetic() || c == '_' => {
// next non-ident char should be ')'
let ident_end = rest.find(|c: char| !(c.is_alphanumeric() || c == '_'));
matches!(ident_end.map(|e| rest[e..].starts_with(')')), Some(true))
}
_ => false, // missing or non-ident argument (e.g. quoted)
}
} else {
true
}
}
Try / catch
match parse_pattern(pattern) {
Ok(p) => use_pattern(p),
Err(e) if e.message.contains("while parsing kind constraint") => {
eprintln!("kind() takes one unquoted identifier: kind(literal)");
}
Err(e) => return Err(e),
} Prevention
- Never quote the kind name
- Always supply exactly one identifier inside kind(...)
- Balance the parentheses of kind(...)
- Remember not(...) parses its argument recursively with the same rules
When it happens
Trigger: Writing constraints like kind(42), kind("literal"), kind() where the next token is a literal/paren/EOF rather than an ident, or kind(kind) with a keyword-ish token that does not lex as IDENT.
Common situations: Quoting the kind name out of habit (kind("literal")); forgetting the argument entirely (kind()); typos that leave punctuation inside the parentheses.
Related errors
- Unsupported constraint type '{}'
- Expected {} found {}
- Expected {} found end of stream
- Unknown node kind '{}'
- Failed to parse pattern: {}
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/22c3574fe8a9fd10.
Report an issue: GitHub.