Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,19 @@ end

You are correct. We want to move to their repos. We haven't started the migration yet.

However, bundled gems listed in `ALUMNI_STDLIBS` in `lib/rbs/collection/config/lockfile_generator.rb` (such as `abbrev`, `benchmark`, `bigdecimal`, `csv`, and `logger`) maintain their RBS definitions in their upstream repositories (e.g., `ruby/csv`). Submit type improvements for those libraries to their respective repositories instead of `ruby/rbs`.

### How can we handle incompatibilities of core APIs and standard libraries between Rubies

We ignore the incompatibilities for now.
We focus on the latest version of core APIs and standard libraries.

* **Do not use union types to bridge Ruby versions**: Avoid patterns like `URI::RFC2396_Parser | URI::RFC3986_Parser`. Match the signature to the latest supported Ruby release.

### Should we use `void` or `untyped` for method return values?

Use `void` when callers should ignore or discard the return value. Use `untyped` only when the method returns an arbitrary object intended for use. (See [syntax guide](syntax.md#void-boolish-or-top)).

### How do we avoid duplicate documentation when importing RDoc?

When an extension library extends a core class (such as `time` extending `Time` or `random-formatter` extending `Random::Formatter`), `rbs annotate` can duplicate core class documentation. Add `%a{annotate:rdoc:skip}` to the module or class declaration to skip the duplicate docs.
35 changes: 29 additions & 6 deletions docs/stdlib.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ It's clear having type aliases makes sense.

#### 📣 Constant type assertions

We also have `assert_const_type` method, to test the type of constant is correct with respect to RBS type definition.
Use `assert_const_type` to test that a constant matches its RBS definition.

```ruby
class FloatConstantTest < Test::Unit::TestCase
Expand All @@ -138,12 +138,35 @@ end

It confirms:

1. The type of constant `Float::INFINITY` is `Float`
2. The type of constant `Float::INFINITY` is correct with respect to RBS definition
1. The constant `Float::INFINITY` is a `Float` at runtime.
2. The type matches its RBS definition.

We don't have any strong recommendation about where the constants test should be written in.
The `FloatConstantTest` example defines a test case only for the constant tests.
You may write the tests inside `FloatInstanceTest` or `FloatSingletonTest`.
When testing class and exception constants, assert that their type is `"Class"`:

* **Good:** `assert_const_type "Class", "StringScanner::Error"`
* **Bad:** `assert_const_type "singleton(::StringScanner::Error)", "StringScanner::Error"`

You can place constant tests inside existing `*SingletonTest` or `*InstanceTest` classes, or define a `*ConstantTest` class.

#### 📣 Write Type Tests, Not Behavior Tests

Stdlib tests verify that RBS signatures match runtime method types. Do not test Ruby implementation behavior.

* **Use `assert_send_type` and `assert_const_type`**: Verify arguments, return values, and constants through type assertions.
* **Skip behavior assertions**: Drop `assert_equal`, `assert_instance_of`, and `assert` for return values, superclasses, and constant contents:
* **Bad:** `assert_equal StandardError, StringScanner::Error.superclass`
* **Bad:** `assert_equal "A", Random::Formatter::ALPHANUMERIC.first`
* **Good:** `assert_const_type "Array[String]", "Random::Formatter::ALPHANUMERIC"`
Reserve `assert_equal` and `assert` for test setup.
* **Ignore untestable behavior**: If a method behavior has no corresponding type check (such as `Singleton.instance` object identity), test only the method signature and return type.

#### 📣 Extending Existing Tests

When updating existing library tests:

1. **Check existing tests first**: Open `test/stdlib/<Library>_test.rb`.
2. **Add to existing test classes**: Put new tests in `*InstanceTest`, `*SingletonTest`, or `*ConstantTest`. Do not create duplicate test classes.
3. **Preserve existing coverage**: Keep existing test cases intact.

### Running tests

Expand Down
Loading