--- title: Module Alias Declaration tags: RBS --- # Module Alias Declaration This proposal is to add a *module alias declaration* to RBS language. The feature has been requested [in 2020](https://github.com/ruby/rbs/issues/345), and [I also found a Ruby code that needs this feature](https://github.com/ruby/gem_rbs_collection/pull/281). ```rbs= # Make ::HashWithIndifferentAccess an alias of ActiveSupport::HashWithIndiffirentAccess class HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess # Define ActiveRecord::Type::* types that are aliases of ActiveModel types module ActiveRecord module Type class BigInteger = ActiveModel::Type::BigInteger class Binary = ActiveModel::Type::Binary class Boolean = ActiveModel::Type::Boolean class Decimal = ActiveModel::Type::Decimal class Float = ActiveModel::Type::Float class Integer = ActiveModel::Type::Integer class String = ActiveModel::Type::String class Value = ActiveModel::Type::Value end end ``` ## Syntax The syntax is defined as the following: ``` module_alias_declaration ::= `class` _type_name_ `=` _type_name_ | `module` _type_name_ `=` _type_name_ ``` Note that a module alias is a relation between a module name and another module name. ```rbs module Foo = Kernel # Valid class StringArray = Array[String] # RHS cannot be a type application class MyHash[K, V] = Hash[K, V] # LHS cannot be a generic type ``` The type name at the right hand side can be a relative name that is interpreted same as other relative type names. ## Validation We have several limitations of the usage of module aliases. 1. The module alias can be used as a type name in many places, but it cannot be used in left-hand-side-ish position of other declarations. ```rbs class HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess # Error: opening an alias module is prohibited class HashWithIndifferentAccess end # Error: adding types under an alias module is prohibited HashWithIndifferentAccess::t = String ``` 2. The alias declarations must have correct keyword `class`/`module` that matches to the right hand side. ```rbs class Foo = ::Kernel # Error: Kernel is a module module Bar = ::BasicObject # Error: BasicObject is a class ``` 3. A module alias cannot be cyclic. ```rbs= class Foo = Bar class Bar = Foo # Error: cyclic definition ``` ## API The APIs provided by RBS library automatically normalizes the module aliases. * `DefinitionBuilder` returns `Definitions` of the normalized classes automatically * The `#type_name` and `#self_type` of the definition may differ from the given type name to `#build_singleton` or `#build_instance` * The normalization works for outer namespaces and ancestors * Type names are not normalized * `Resolver::TypeNameResolver` works for alias names. It returns absolute names of the class aliases. * `Environment` provides *normalize* methods ## Limitations The alias cannot be used to describe the *left-hand-side* of the declarations. ```rbs class Foo = String class Foo # Cannot open the aliased class end type Foo::bar = Integer # Cannot add a type alias ```