oracle/graal · error · RuleParseError
Captured node "%s" has differing types
Error message
Captured node "%s" has differing types
What it means
Thrown by RuleParser.parseType when the same captured name (lowercase identifier after '=') is bound to two different node types within one rule. Captured names are how a @MatchRule communicates matched nodes to the generated method parameters, so one name must consistently denote one type; reusing it for a different node type is rejected.
Source
Thrown at compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/core/match/processor/MatchProcessor.java:209
next();
name = next();
}
originatingElements.addAll(type.originatingElements);
} else if (Character.isLowerCase(peek("name").charAt(0))) {
name = next();
type = valueType;
} else {
throw new RuleParseError("Unexpected token \"%s\" when looking for name or node type", peek(null));
}
requiredPackages.add(type.nodePackage);
if (name != null) {
if (!capturedNames.contains(name)) {
capturedNames.add(name);
capturedTypes.add(type);
} else {
int index = capturedNames.indexOf(name);
if (capturedTypes.get(index) != type) {
throw new RuleParseError("Captured node \"%s\" has differing types", name);
}
}
}
return new MatchDescriptor(type, name, forExpression);
}
List<String> generateVariants() {
return matchDescriptor.generateVariants();
}
/**
* Recursively accumulate any required Position declarations.
*/
void generatePositionDeclarations(Set<String> declarations) {
matchDescriptor.generatePositionDeclarations(declarations);
}
/**View on GitHub (pinned to a66e9ccd1d)
Solutions
- Rename one of the captures so each name maps to exactly one node type (x = a, x = b).
- If both captures genuinely refer to the same node position, bind the name once and reuse it only for the identical type.
- Adopt unique, descriptive capture names per rule to avoid collisions.
Example fix
// before
@MatchRule("Add(x = v, Mul(x = w))")
// after
@MatchRule("Add(x = v, Mul(y = w))") Defensive patterns
Strategy: try-catch
Try / catch
Compile-time only; the diagnostic names the conflicting capture. No runtime handling possible.
Prevention
- Give each captured name in a rule a unique, descriptive identifier.
- Never reuse a short capture name for a different node type within one rule.
- When copy-pasting sub-patterns, rename captures as you paste.
When it happens
Trigger: A rule like "Add(x = value, Mul(x = other))" where 'x' binds first to an Add input type and then to a Mul type differing by reference equality (capturedTypes.get(index) != type). Note the check is exact TypeDescriptor identity, not name compatibility.
Common situations: Copy-pasting a sub-pattern and forgetting to rename its capture; rules grown organically where 'x'/'y' get reused; introducing a new sub-match that accidentally reuses an existing short name with a different node type.
Related errors
- Unexpected tokens :${rule.substring(m.end(), m.regionEnd())}
- didn't consume all tokens
- Out of tokens
- Out of tokens looking for %s
- not enough inputs for ${descriptor.name}
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/f2fa68c4d5dc4ed5.
Report an issue: GitHub.