class RBS::VarianceCalculator
Calculate the use variances of type variables in declaration.
calculator = VarianceCalculator.new(builder: builder) # Calculates variances in a method type result = calculator.in_method_type(method_type: method_type, variables: variables) # Calculates variances in a inheritance/mixin/... result = calculator.in_inherit(name: name, args: args, variables: variables) # Calculates variances in a type alias result = calculator.in_type_alias(name: name, args: args, variables: variables)
See RBS::VarianceCalculator::Result for information recorded in the Result object.
Attributes
Public Class Methods
(builder: DefinitionBuilder) → void
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/variance_calculator.rb, line 78 def initialize(builder:) @builder = builder end
Public Instance Methods
() → Environment
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/variance_calculator.rb, line 82 def env builder.env end
(Types::function, result: Result, context: variance) → void
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/variance_calculator.rb, line 169 def function(type, result:, context:) type.each_param do |param| type(param.type, result: result, context: negate(context)) end type(type.return_type, result: result, context: context) end
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/variance_calculator.rb, line 98 def in_inherit(name:, args:, variables:) type = if name.class? Types::ClassInstance.new(name: name, args: args, location: nil) else Types::Interface.new(name: name, args: args, location: nil) end Result.new(variables: variables).tap do |result| type(type, result: result, context: :covariant) end end
(method_type: MethodType, variables: Array[Symbol]) → Result
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/variance_calculator.rb, line 86 def in_method_type(method_type:, variables:) result = Result.new(variables: variables) function(method_type.type, result: result, context: :covariant) if block = method_type.block function(block.type, result: result, context: :contravariant) end result end
(name: TypeName) → Result
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/variance_calculator.rb, line 110 def in_type_alias(name:) env.normalized_type_name!(name) decl = env.type_alias_decls[name].decl or raise variables = decl.type_params.each.map(&:name) Result.new(variables: variables).tap do |result| type(decl.type, result: result, context: :covariant) end end
The type name must be normalized
(variance) → variance
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/variance_calculator.rb, line 176 def negate(variance) case variance when :invariant :invariant when :covariant :contravariant when :contravariant :covariant else raise end end
(Types::t, result: Result, context: variance) → void
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.0.3/lib/rbs/variance_calculator.rb, line 121 def type(type, result:, context:) case type when Types::Variable if result.include?(type.name) case context when :covariant result.covariant(type.name) when :contravariant result.contravariant(type.name) when :invariant result.invariant(type.name) end end when Types::ClassInstance, Types::Interface, Types::Alias if type_name = env.normalize_type_name?(type.name) type_params = case type when Types::ClassInstance env.class_decls[type_name].type_params when Types::Interface env.interface_decls[type_name].decl.type_params when Types::Alias env.type_alias_decls[type_name].decl.type_params end type.args.each.with_index do |ty, i| if var = type_params[i] case var.variance when :invariant type(ty, result: result, context: :invariant) when :covariant type(ty, result: result, context: context) when :contravariant type(ty, result: result, context: negate(context)) end end end else raise NoTypeFoundError.new(type_name: type.name, location: type.location) end when Types::Proc function(type.type, result: result, context: context) else type.each_type do |ty| type(ty, result: result, context: context) end end end