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
NoTypeFoundError.check!(type.name,
env: env,
location: type.location)
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
end
type.args.each.with_index do |ty, i|
var = type_params.params[i]
case var&.variance
when :invariant
type(ty, result: result, context: :invariant)
when :covariant
type(ty, result: result, context: context)
when :contravariant
con = case context
when :invariant
:invariant
when :covariant
:contravariant
when :contravariant
:covariant
else
raise
end
type(ty, result: result, context: con)
end
end
when Types::Tuple, Types::Record, Types::Union, Types::Intersection
type.each_type do |ty|
type(ty, result: result, context: context)
end
end
end