Try   HackMD

Module Alias Declaration

This proposal is to add a module alias declaration to RBS language. The feature has been requested in 2020, and I also found a Ruby code that needs this feature.

# 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.

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.
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
  1. The alias declarations must have correct keyword class/module that matches to the right hand side.
class Foo = ::Kernel        # Error: Kernel is a module

module Bar = ::BasicObject  # Error: BasicObject is a class
  1. A module alias cannot be cyclic.
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.

class Foo = String

class Foo                # Cannot open the aliased class
end

type Foo::bar = Integer  # Cannot add a type alias