Skip to content

Add support for lower bounds in type parameters#2490

Merged
soutaro merged 1 commit intoruby:masterfrom
Shopify:support-lower-bound
May 27, 2025
Merged

Add support for lower bounds in type parameters#2490
soutaro merged 1 commit intoruby:masterfrom
Shopify:support-lower-bound

Conversation

@allcre
Copy link
Copy Markdown
Contributor

@allcre allcre commented May 15, 2025

This change implements lower bound constraints for generic type parameters in RBS, allowing declarations like [T > SomeType].

The implementation includes:

  • Parser and lexer modifications to handle ">" token in type params
  • Relevant changes to the Ruby API, like Locator and Validator
  • Schema updates to typeParam.json
  • Documentation updates

Comment on lines 1449 to +1454
rbs_parser_advance(parser);
}

if (parser->next_token.type == pRBRACKET) {
} else if (parser->next_token.type == pRBRACKET) {
break;
} else {
rbs_parser_set_error(parser, parser->next_token, true, "expected ',' or ']' after type parameter, got %s", rbs_token_type_str(parser->next_token.type));
return false;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change ensures the parser correctly validates syntax after type parameter bounds. Previously, expressions like [T < String Integer] would be silently accepted despite being invalid.

upper_bound_range.end = parser->current_token.range.end;
rbs_range_t lower_bound_range = NULL_RANGE;

for (int bound_parse_attempt = 0; bound_parse_attempt < 2; bound_parse_attempt++) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This loop is to parse both upper bound (<) and lower bound (>) constraints for type parameters. The loop runs at most twice to allow both bound types in either order: [T < UpperBound > LowerBound] or [T > LowerBound < UpperBound]. It detects and prevents duplicate bounds of the same type and exits early if no bounds are present.

@allcre allcre marked this pull request as draft May 15, 2025 16:00
@allcre allcre force-pushed the support-lower-bound branch from 487f79c to c63e115 Compare May 15, 2025 16:32
@allcre allcre marked this pull request as ready for review May 15, 2025 16:38
Copy link
Copy Markdown
Contributor

@ParadoxV5 ParadoxV5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Side Note: In RBS, the generic type specify covariance and contravariance with in/out keywords:

class Covariant[out O] …
class Contravariant[in I] …
def example(src, dst) #: [T] (Covariant[T], Contravariant[T]) -> void
  dst.set src.get
end

Java generics are invariant; instead, each application specifies co- and contravariance through wildcard lower and upper bounds case-by-case:

class Covariant<O> …
class Contravariant<I> …

<T> void example(Covariant<? extends T> src, Contravariant<? super T> dst) {
  dst.set(src.get());
}

In RBS, that is equivalent to:

class Covariant[O] …
class Contravariant[I] …

def example: [T, O < T = T, I > T = T] (Covariant[O], Contravariant[I]) -> void

This change implements lower bound constraints for generic type
parameters in RBS, allowing declarations like `[T > SomeType]`.

The implementation includes:
- Parser and lexer modifications to handle ">" token in type params
- Relevant changes to the Ruby API, like Locator and Validator
- Schema updates to typeParam.json
- Documentation updates
@allcre allcre force-pushed the support-lower-bound branch from c63e115 to ac8348a Compare May 20, 2025 16:03
@soutaro soutaro added this to the RBS 4.0 milestone May 27, 2025
Copy link
Copy Markdown
Member

@soutaro soutaro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! 🎉

@soutaro soutaro added this pull request to the merge queue May 27, 2025
Merged via the queue into ruby:master with commit 2a73da6 May 27, 2025
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants