class RBS::AST::TypeParam
Attributes
Types::t?
loc?
Types::t?
Types::t?
variance
Public Class Methods
(Array[TypeParam], Array[Types::t]) → Substitution?
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 166 def self.application(params, args) if params.empty? return nil end optional_params, required_params = params.partition {|param| param.default_type } param_subst = Substitution.new() app_subst = Substitution.new() required_params.zip(args.take(required_params.size)).each do |param, arg| arg ||= Types::Bases::Any.new(location: nil) param_subst.add(from: param.name, to: arg) app_subst.add(from: param.name, to: arg) end optional_params.each do |param| param_subst.add(from: param.name, to: Types::Bases::Any.new(location: nil)) end optional_params.zip(args.drop(required_params.size)).each do |param, arg| if arg app_subst.add(from: param.name, to: arg) else param.default_type or raise app_subst.add(from: param.name, to: param.default_type.sub(param_subst)) end end app_subst end
Returns an application with respect to type paramsβ default
(name: Symbol, variance: variance, upper_bound: Types::t?, lower_bound: Types::t?, location: loc?, ?default_type: Types::t?, ?unchecked: bool) → void
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 8 def initialize(name:, variance:, upper_bound:, lower_bound:, location:, default_type: nil, unchecked: false) @name = name @variance = variance @upper_bound_type = upper_bound @lower_bound_type = lower_bound @location = location @default_type = default_type @unchecked = unchecked end
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 198 def self.normalize_args(params, args) app = application(params, args) or return args min_count = params.count { _1.default_type.nil? } unless min_count <= args.size && args.size <= params.size return args end params.zip(args).filter_map do |param, arg| if arg arg else if param.default_type param.default_type.sub(app) else Types::Bases::Any.new(location: nil) end end end end
Returns an array of type args, that fills omitted types with the defaults
interface _Foo[T, S = untyped] end
Normalizing type args with _Foo works as following:
_Foo[String] # => _Foo[String, untyped] _Foo[String, Integer] # => _Foo[String, Integer] _Foo # => _Foo (Omitting missing args) _Foo[String, Integer, untyped] # => _Foo[String, Integer, untyped] (Keeping extra args)
Note that it allows invalid arities, returning the args immediately.
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 114 def self.rename(params, new_names:) raise unless params.size == new_names.size subst = Substitution.build(new_names, Types::Variable.build(new_names)) params.map.with_index do |param, index| new_name = new_names[index] TypeParam.new( name: new_name, variance: param.variance, upper_bound: param.upper_bound_type&.map_type {|type| type.sub(subst) }, lower_bound: param.lower_bound_type&.map_type {|type| type.sub(subst) }, location: param.location, default_type: param.default_type&.map_type {|type| type.sub(subst) } ).unchecked!(param.unchecked?) end end
Rename type parameter name.
The renaming cannot be done separately because a set of TypeParam decls may be mutual recursive.
Example:
-
Renaming
A -> X, B -> Y -
Input
[A, B < _Pushable[A]] -
Result
[X, Y < _Pushable[X]]
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 92 def self.resolve_variables(params) return if params.empty? vars = Set.new(params.map(&:name)) params.map! do |param| param.map_type {|bound| _ = subst_var(vars, bound) } end end
Helper function to resolve class instance types to type variables.
We need this step because RBS language has an identical syntax for both unqualified class instance types and type variables. String may be an instance of ::String class or type variable depending on the list of bound type variables.
So, we need second pass to parse the following generics parameter declaration.
class Foo[X < _Each[Y], Y]
# ^ We want this `Y` to be a type variable.
end
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 102 def self.subst_var(vars, type) case type when Types::ClassInstance namespace = type.name.namespace if namespace.relative? && namespace.empty? && vars.member?(type.name.name) return Types::Variable.new(name: type.name.name, location: type.location) end end type.map_type {|t| subst_var(vars, t) } end
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 219 def self.validate(type_params) optionals = type_params.filter {|param| param.default_type } optional_param_names = optionals.map(&:name).sort optionals.filter! do |param| default_type = param.default_type or raise optional_param_names.any? { default_type.free_variables.include?(_1) } end unless optionals.empty? optionals end end
Validates TypeParams if it refers another optional type params
-
Returns array of
TypeParamobjects that refers other optional type params -
Returns
nilif all type params are valid
Public Instance Methods
(untyped) → bool
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 41 def ==(other) other.is_a?(TypeParam) && other.name == name && other.variance == variance && other.upper_bound_type == upper_bound_type && other.lower_bound_type == lower_bound_type && other.default_type == default_type && other.unchecked? == unchecked? end
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 53 def hash self.class.hash ^ name.hash ^ variance.hash ^ upper_bound_type.hash ^ lower_bound_type.hash ^ unchecked?.hash ^ default_type.hash end
() → bound?
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 25 def lower_bound case lower_bound_type when Types::ClassInstance, Types::ClassSingleton, Types::Interface lower_bound_type end end
() { (Types::t) → Types::t } → TypeParam
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 69 def map_type(&block) if b = upper_bound_type _upper_bound_type = yield(b) end if b = lower_bound_type _lower_bound_type = yield(b) end if dt = default_type _default_type = yield(dt) end TypeParam.new( name: name, variance: variance, upper_bound: _upper_bound_type, lower_bound: _lower_bound_type, location: location, default_type: _default_type ).unchecked!(unchecked?) end
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 57 def to_json(state = JSON::State.new) { name: name, variance: variance, unchecked: unchecked?, location: location, upper_bound: upper_bound_type, lower_bound: lower_bound_type, default_type: default_type }.to_json(state) end
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 133 def to_s s = +"" if unchecked? s << "unchecked " end case variance when :invariant # nop when :covariant s << "out " when :contravariant s << "in " end s << name.to_s if type = upper_bound_type s << " < #{type}" end if type = lower_bound_type s << " > #{type}" end if dt = default_type s << " = #{dt}" end s end
(?boolish) → self
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 32 def unchecked!(value = true) @unchecked = value ? true : false self end
() → bool
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 37 def unchecked? @unchecked end
() → bound?
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/ast/type_param.rb, line 18 def upper_bound case upper_bound_type when Types::ClassInstance, Types::ClassSingleton, Types::Interface upper_bound_type end end