Mark type_name as optional on the alias annotations - #3039
Merged
Conversation
`: class-alias` and `: module-alias` may be written without a name, to be
inferred from the Ruby code. The parser then leaves both `type_name` and
`type_name_location` unset:
rbs_type_name_t *type_name = NULL;
rbs_location_range type_name_loc = RBS_LOCATION_NULL_RANGE;
if (parser->next_token.type == tUIDENT || parser->next_token.type == pCOLON2) {
...
type_name_loc = RBS_RANGE_LEX2AST(type_name_range);
} else {
// No type name provided - will be inferred
}
config.yml marked only `type_name_location` as optional, so the generated
declarations promised `rbs_type_name_t *RBS_NONNULL type_name` for a field
the parser sets to NULL.
Nothing changes at run time. `rbs_struct_to_ruby_value` maps NULL to `nil`,
`AliasAnnotation#type_name` is already typed `TypeName?`, and
`map_type_name` and `type_fingerprint` already guard for nil;
`serialize_node` handles NULL too. clang does not flag the current code
either, because the local the parser passes carries no nullability
annotation of its own, so `-Wnullable-to-nonnull-conversion` stays quiet.
What the annotation does affect is generated bindings that trust it. The
Rust `ruby-rbs` crate derives its accessors from config.yml, emitting an
`Option`-returning one for optional node fields and a plain one otherwise.
So `ClassAliasAnnotationNode::type_name` currently hands out a wrapper
around a NULL pointer and reading through it dereferences null; it becomes
`Option<TypeNameNode<'_>>` once that crate's vendored config.yml is
re-pinned to a release containing this.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
soutaro
enabled auto-merge
July 28, 2026 04:21
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #3038.
: class-aliasand: module-aliasmay be written without a name, to be inferred from the Ruby code, and the parser leavestype_nameNULL in that case.config.ymlmarked onlytype_name_locationas optional, so the generated declarations promisedrbs_type_name_t *RBS_NONNULL type_namefor a field that can be NULL.Nothing changes at run time:
rbs_struct_to_ruby_valuemaps NULL tonil,AliasAnnotation#type_nameis already typedTypeName?, andmap_type_name,type_fingerprintandserialize_nodeall guard for nil. What the annotation does affect is generated bindings that trust it — the Rustruby-rbscrate emits anOption-returning accessor for optional node fields and a plain one otherwise, soClassAliasAnnotationNode::type_namecurrently hands out a wrapper around a NULL pointer.🤖 Generated with Claude Code