ruby-rbs

repository·master·Indexed 24 days ago

https://github.com/ruby/rbs

Rust bindings for RBS, a type signature language for Ruby programs used to describe the structure of classes, modules, methods, instance variables, constants, and inheritance. The library provides tools for parsing RBS files via RBS::Parser, managing declarations through RBS::Environment, and constructing type definitions using DefinitionBuilder. It includes features for generating boilerplate signatures via `rbs prototype`, managing third-party gem signatures with `rbs collection`, and a WebAssembly parser for cross-platform use.

Tokens
22.8K
Snippets
79
Records
145
Agent score
80%

What's inside ruby-rbs

  1. Overview of RBS Rust Crates

    master

    RBS provides two distinct Rust crates for interacting with RBS signatures:

    • ruby-rbs-sys: Provides low-level FFI bindings to the RBS C parser.
    • ruby-rbs: Provides a high-level, safe Rust API for parsing RBS signatures.

    Both crates are available on crates.io and are maintained in the rust/ directory of the repository.

  2. Define multiple signatures for a single method

    master

    If a method behaves differently depending on the input types, you can provide multiple signatures separated by a pipe | symbol. This is common when a method returns different types based on its arguments.

    class Array[E]
      def *: (String) -> String
           | (Integer) -> Array[E]
    end
  3. Handle method overloading in RBS

    master

    RBS does not allow duplicate method definitions. If you need to overload a method (provide multiple definitions for the same method name), you must use the ... syntax in the subsequent definitions to tell RBS that the method is being overloaded.

    # First definition
    class C
      def foo: () -> untyped
    end
    
    # Second definition, use `...` syntax to tell RBS that we're overloading the method
    class C
      def foo: () -> untyped
             | ...
    end
  4. Use Optional, Record, and Tuple types

    master

    For complex data structures and nullability:

    • Optional type (?): Denotes a type that can be the specified type or nil.
    • Record type ({}): Represents a Hash object with a fixed set of keys and heterogeneous values.
    • Tuple type ([]): Represents an Array object with a fixed size and heterogeneous values.
  5. Configure RBS signature testing via environment variables

    master

    Signature testing is configured using the RBS_TEST_TARGET environment variable and several optional configuration variables.

    Target Selection

    • RBS_TEST_TARGET: Specifies the classes to test. Use comma-separated exact names (e.g., Foo::Bar,Foo::Baz) or wildcards (e.g., Foo::*).
    • RBS_TEST_SKIP: (Optional) Skips specific classes that match the RBS_TEST_TARGET pattern.

    Test Options and Debugging

    • RBS_TEST_OPT: (Optional) Passes options to the RBS handler. By default, it uses -I sig. You can use this to load additional libraries or signature paths (e.g., RBS_TEST_OPT='-r logger -I sig -Iprivate').
    • RBS_TEST_LOGLEVEL: (Optional) Configures the log level. Defaults to info.
    • RBS_TEST_RAISE: (Optional) If set, the test will raise an exception when a type error is detected, providing a backtrace to help debug the cause of the error.
  6. Use Type Variables in declarations

    master
    Type variables (e.g., T, U, Elem) are used for generics. They are scoped within class, module, interface, alias declarations, or generic method types. They cannot be distinguished from class instance types by syntax alone.
  7. Respect contextual limitations for void, self, and class/instance types

    master

    RBS enforces contextual limitations on certain types. While the parser may accept them, rbs validate will report warnings. In future versions (3.4+), these will be rejected.

    void limitations

    • Allowed: As a return type or a generic parameter.
    • Prohibited: As a function parameter, or inside an optional type (void?) or a union type (void | String).

    self limitations

    • Allowed: Only in self-context (e.g., instance attributes or method return types).
    • Prohibited: In mixin arguments, constant types, class variables, or type aliases.

    class and instance limitations

    • Allowed: Only in classish-context (e.g., instance attributes, class variables, or mixin arguments).
    • Prohibited: In constant types or type aliases.
  8. Use Union and Nilable types

    master

    RBS provides ways to represent values that can be one of several types:

    • Union types: Use the pipe | to allow multiple types. Example: String | Integer means the value can be either a String or an Integer.
    • Nilable types: Use the ? suffix on a type to indicate it can also be nil. This is a shorthand for a union with nil. Example: E? is equivalent to (E | nil).
    # Union type
    def <<: (String | Integer) -> String
    end
    
    # Nilable type
    def first: () -> E?
    end
  9. Understand third-party RBS version resolution

    master

    RBS uses optimistic version resolution rather than strict semantic versioning. The goal is to provide type definitions even if they are not a perfect match for the requested version, as having some type definitions is preferred over none.

    Resolution Rules:

    1. RBS attempts to find the latest available version m such that m <= n (where n is the requested version).
    2. If no such version exists (i.e., the requested version is older than any available version), RBS resolves to the oldest available version.

    Example Resolution Table: If versions 0.4.0 and 1.0.0 are available:

    Requested versionResolved version
    0.3.00.4.0 (Rule 2)
    0.4.00.4.0
    0.5.00.4.0
    1.0.01.0.0
    2.0.01.0.0
  10. How Unicode codepoint symbols behave with different encodings

    master

    RBS string literal types can use Unicode codepoint escape sequences (\uXXXX). The parser's behavior depends on the file encoding:

    In UTF-8 encoded files

    The parser translates the escape sequence into the actual Unicode character.

    type t = "\u0123"  # Translated to the actual Unicode character ģ
    type s = "\u3042"  # Translated to the actual Unicode character あ

    In non-UTF-8 encoded files

    The escape sequence is interpreted literally as the string \uXXXX.

    type t = "\u0123"  # Remains as the literal string "\u0123"
  11. Hiding RBS files from gem users

    master

    If you want to include RBS files in your gem package that should not be exported to gem users, place them in a directory starting with an underscore (_).

    For example:

    • /sig/foo.rbs (Loaded)
    • /sig/bar/baz.rbs (Loaded)
    • /sig/_private/internal.rbs (Skipped when loading as a library)

    Behavior Note:

    • When loading as a library (e.g., rbs -r your-gem), files in _ directories are skipped.
    • When loading as source code (e.g., rbs -I sig), hidden files will be loaded.
  12. Understand RBS::Environment and declaration mapping

    master

    An RBS::Environment is populated by an RBS::EnvironmentLoader. It maps absolute names to their corresponding declarations.

    For example, if you have nested declarations:

    module Hello
      class World
      end
    end
    
    class Hello::World
    end

    The environment organizes these into:

    • A mapping for ::Hello to its module declaration.
    • A mapping for ::Hello::World to its two distinct class declarations.