lib/steep/interface/builder.rb in steep-1.8.0.dev.2 vs lib/steep/interface/builder.rb in steep-1.8.0.pre.1
- old
+ new
@@ -275,19 +275,18 @@
shape = Interface::Shape.new(type: AST::Types::Name::Singleton.new(name: type_name), private: true)
definition = factory.definition_builder.build_singleton(type_name)
definition.methods.each do |name, method|
Steep.logger.tagged "method = #{type_name}.#{name}" do
- shape.methods[name] = Interface::Shape::Entry.new(
- private_method: method.private?,
- method_types: method.defs.map do |type_def|
- method_name = method_name_for(type_def, name)
- decl = TypeInference::MethodCall::MethodDecl.new(method_name: method_name, method_def: type_def)
- method_type = factory.method_type(type_def.type, method_decls: Set[decl])
- replace_primitive_method(method_name, type_def, method_type)
- end
- )
+ overloads = method.defs.map do |type_def|
+ method_name = method_name_for(type_def, name)
+ method_type = factory.method_type(type_def.type)
+ method_type = replace_primitive_method(method_name, type_def, method_type)
+ Shape::MethodOverload.new(method_type, [type_def])
+ end
+
+ shape.methods[name] = Interface::Shape::Entry.new(method_name: name, private_method: method.private?, overloads: overloads)
end
end
shape
end
@@ -306,19 +305,18 @@
definition or raise
definition.methods.each do |name, method|
Steep.logger.tagged "method = #{type_name}##{name}" do
- shape.methods[name] = Interface::Shape::Entry.new(
- private_method: method.private?,
- method_types: method.defs.map do |type_def|
- method_name = method_name_for(type_def, name)
- decl = TypeInference::MethodCall::MethodDecl.new(method_name: method_name, method_def: type_def)
- method_type = factory.method_type(type_def.type, method_decls: Set[decl])
- replace_primitive_method(method_name, type_def, method_type)
- end
- )
+ overloads = method.defs.map do |type_def|
+ method_name = method_name_for(type_def, name)
+ method_type = factory.method_type(type_def.type)
+ method_type = replace_primitive_method(method_name, type_def, method_type)
+ Shape::MethodOverload.new(method_type, [type_def])
+ end
+
+ shape.methods[name] = Interface::Shape::Entry.new(method_name: name, private_method: method.private?, overloads: overloads)
end
end
shape
end
@@ -332,55 +330,53 @@
all_common_methods &= shape.methods.each_name
end
shape = Interface::Shape.new(type: shape_type, private: true)
all_common_methods.each do |method_name|
- method_typess = [] #: Array[Array[MethodType]]
+ overloadss = [] #: Array[Array[Shape::MethodOverload]]
private_method = false
shapes.each do |shape|
entry = shape.methods[method_name] || raise
- method_typess << entry.method_types
+ overloadss << entry.overloads
private_method ||= entry.private_method?
end
- shape.methods[method_name] = Interface::Shape::Entry.new(private_method: private_method) do
- method_typess.inject do |types1, types2|
+ shape.methods[method_name] = Interface::Shape::Entry.new(method_name: method_name, private_method: private_method) do
+ overloadss.inject do |overloads1, overloads2|
# @type break: nil
+ types1 = overloads1.map(&:method_type)
+ types2 = overloads2.map(&:method_type)
+
if types1 == types2
- decl_array1 = types1.map(&:method_decls)
- decl_array2 = types2.map(&:method_decls)
+ defs1 = overloads1.flat_map(&:method_defs)
+ defs2 = overloads2.flat_map(&:method_defs)
- if decl_array1 == decl_array2
- next types1
+ if defs1 == defs2
+ next overloads1
end
-
- decls1 = decl_array1.each.with_object(Set[]) {|array, decls| decls.merge(array) } #$ Set[TypeInference::MethodCall::MethodDecl]
- decls2 = decl_array2.each.with_object(Set[]) {|array, decls| decls.merge(array) } #$ Set[TypeInference::MethodCall::MethodDecl]
-
- if decls1 == decls2
- next types1
- end
end
- method_types = {} #: Hash[MethodType, bool]
+ method_overloads = {} #: Hash[Shape::MethodOverload, bool]
- types1.each do |type1|
- types2.each do |type2|
- if type1 == type2
- method_types[type1.with(method_decls: type1.method_decls + type2.method_decls)] = true
+ overloads1.each do |overload1|
+ overloads2.each do |overload2|
+ if overload1.method_type == overload2.method_type
+ overload = Shape::MethodOverload.new(overload1.method_type, overload1.method_defs + overload2.method_defs)
+ method_overloads[overload] = true
else
- if type = MethodType.union(type1, type2, subtyping)
- method_types[type] = true
+ if type = MethodType.union(overload1.method_type, overload2.method_type, subtyping)
+ overload = Shape::MethodOverload.new(type, overload1.method_defs + overload2.method_defs)
+ method_overloads[overload] = true
end
end
end
end
- break nil if method_types.empty?
+ break nil if method_overloads.empty?
- method_types.keys
+ method_overloads.keys
end
end
end
shape
@@ -425,91 +421,96 @@
def subtyping
@subtyping ||= Subtyping::Check.new(builder: self)
end
def tuple_shape(tuple)
- element_type = AST::Types::Union.build(types: tuple.types, location: nil)
+ element_type = AST::Types::Union.build(types: tuple.types)
array_type = AST::Builtin::Array.instance_type(element_type)
array_shape = yield(array_type) or raise
shape = Shape.new(type: tuple, private: true)
shape.methods.merge!(array_shape.methods)
aref_entry = array_shape.methods[:[]].yield_self do |aref|
raise unless aref
Shape::Entry.new(
+ method_name: :[],
private_method: false,
- method_types: tuple.types.map.with_index {|elem_type, index|
- MethodType.new(
- type_params: [],
- type: Function.new(
- params: Function::Params.build(required: [AST::Types::Literal.new(value: index)]),
- return_type: elem_type,
- location: nil
+ overloads: tuple.types.map.with_index {|elem_type, index|
+ Shape::MethodOverload.new(
+ MethodType.new(
+ type_params: [],
+ type: Function.new(
+ params: Function::Params.build(required: [AST::Types::Literal.new(value: index)]),
+ return_type: elem_type,
+ location: nil
+ ),
+ block: nil
),
- block: nil,
- method_decls: Set[]
+ []
)
- } + aref.method_types
+ } + aref.overloads
)
end
aref_update_entry = array_shape.methods[:[]=].yield_self do |update|
raise unless update
Shape::Entry.new(
+ method_name: :[]=,
private_method: false,
- method_types: tuple.types.map.with_index {|elem_type, index|
- MethodType.new(
- type_params: [],
- type: Function.new(
- params: Function::Params.build(required: [AST::Types::Literal.new(value: index), elem_type]),
- return_type: elem_type,
- location: nil
+ overloads: tuple.types.map.with_index {|elem_type, index|
+ Shape::MethodOverload.new(
+ MethodType.new(
+ type_params: [],
+ type: Function.new(
+ params: Function::Params.build(required: [AST::Types::Literal.new(value: index), elem_type]),
+ return_type: elem_type,
+ location: nil
+ ),
+ block: nil
),
- block: nil,
- method_decls: Set[]
+ []
)
- } + update.method_types
+ } + update.overloads
)
end
fetch_entry = array_shape.methods[:fetch].yield_self do |fetch|
raise unless fetch
Shape::Entry.new(
+ method_name: :fetch,
private_method: false,
- method_types: tuple.types.flat_map.with_index {|elem_type, index|
+ overloads: tuple.types.flat_map.with_index {|elem_type, index|
[
MethodType.new(
type_params: [],
type: Function.new(
params: Function::Params.build(required: [AST::Types::Literal.new(value: index)]),
return_type: elem_type,
location: nil
),
- block: nil,
- method_decls: Set[]
+ block: nil
),
MethodType.new(
- type_params: [TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false)],
+ type_params: [TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false, default_type: nil)],
type: Function.new(
params: Function::Params.build(
required: [
AST::Types::Literal.new(value: index),
AST::Types::Var.new(name: :T)
]
),
return_type: AST::Types::Union.build(types: [elem_type, AST::Types::Var.new(name: :T)]),
location: nil
),
- block: nil,
- method_decls: Set[]
+ block: nil
),
MethodType.new(
- type_params: [TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false)],
+ type_params: [TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false, default_type: nil)],
type: Function.new(
params: Function::Params.build(required: [AST::Types::Literal.new(value: index)]),
return_type: AST::Types::Union.build(types: [elem_type, AST::Types::Var.new(name: :T)]),
location: nil
),
@@ -519,49 +520,54 @@
return_type: AST::Types::Var.new(name: :T),
location: nil
),
optional: false,
self_type: nil
- ),
- method_decls: Set[]
+ )
)
- ]
- } + fetch.method_types
+ ].map { Shape::MethodOverload.new(_1, []) }
+ } + fetch.overloads
)
end
first_entry = array_shape.methods[:first].yield_self do |first|
Shape::Entry.new(
+ method_name: :first,
private_method: false,
- method_types: [
- MethodType.new(
- type_params: [],
- type: Function.new(
- params: Function::Params.empty,
- return_type: tuple.types[0] || AST::Builtin.nil_type,
- location: nil
+ overloads: [
+ Shape::MethodOverload.new(
+ MethodType.new(
+ type_params: [],
+ type: Function.new(
+ params: Function::Params.empty,
+ return_type: tuple.types[0] || AST::Builtin.nil_type,
+ location: nil
+ ),
+ block: nil
),
- block: nil,
- method_decls: Set[]
+ []
)
]
)
end
last_entry = array_shape.methods[:last].yield_self do |last|
Shape::Entry.new(
+ method_name: :last,
private_method: false,
- method_types: [
- MethodType.new(
- type_params: [],
- type: Function.new(
- params: Function::Params.empty,
- return_type: tuple.types.last || AST::Builtin.nil_type,
- location: nil
+ overloads: [
+ Shape::MethodOverload.new(
+ MethodType.new(
+ type_params: [],
+ type: Function.new(
+ params: Function::Params.empty,
+ return_type: tuple.types.last || AST::Builtin.nil_type,
+ location: nil
+ ),
+ block: nil
),
- block: nil,
- method_decls: Set[]
+ []
)
]
)
end
@@ -574,92 +580,100 @@
shape
end
def record_shape(record)
all_key_type = AST::Types::Union.build(
- types: record.elements.each_key.map {|value| AST::Types::Literal.new(value: value, location: nil) },
- location: nil
+ types: record.elements.each_key.map {|value| AST::Types::Literal.new(value: value) }
)
- all_value_type = AST::Types::Union.build(types: record.elements.values, location: nil)
+ all_value_type = AST::Types::Union.build(types: record.elements.values)
hash_type = AST::Builtin::Hash.instance_type(all_key_type, all_value_type)
hash_shape = yield(hash_type) or raise
shape = Shape.new(type: record, private: true)
shape.methods.merge!(hash_shape.methods)
shape.methods[:[]] = hash_shape.methods[:[]].yield_self do |aref|
aref or raise
Shape::Entry.new(
+ method_name: :[],
private_method: false,
- method_types: record.elements.map do |key_value, value_type|
- key_type = AST::Types::Literal.new(value: key_value, location: nil)
+ overloads: record.elements.map do |key_value, value_type|
+ key_type = AST::Types::Literal.new(value: key_value)
- MethodType.new(
- type_params: [],
- type: Function.new(
- params: Function::Params.build(required: [key_type]),
- return_type: value_type,
- location: nil
+ if record.optional?(key_value)
+ value_type = AST::Builtin.optional(value_type)
+ end
+
+ Shape::MethodOverload.new(
+ MethodType.new(
+ type_params: [],
+ type: Function.new(
+ params: Function::Params.build(required: [key_type]),
+ return_type: value_type,
+ location: nil
+ ),
+ block: nil
),
- block: nil,
- method_decls: Set[]
+ []
)
- end + aref.method_types
+ end + aref.overloads
)
end
shape.methods[:[]=] = hash_shape.methods[:[]=].yield_self do |update|
update or raise
Shape::Entry.new(
+ method_name: :[]=,
private_method: false,
- method_types: record.elements.map do |key_value, value_type|
- key_type = AST::Types::Literal.new(value: key_value, location: nil)
- MethodType.new(
- type_params: [],
- type: Function.new(
- params: Function::Params.build(required: [key_type, value_type]),
- return_type: value_type,
- location: nil),
- block: nil,
- method_decls: Set[]
+ overloads: record.elements.map do |key_value, value_type|
+ key_type = AST::Types::Literal.new(value: key_value)
+ Shape::MethodOverload.new(
+ MethodType.new(
+ type_params: [],
+ type: Function.new(
+ params: Function::Params.build(required: [key_type, value_type]),
+ return_type: value_type,
+ location: nil),
+ block: nil
+ ),
+ []
)
- end + update.method_types
+ end + update.overloads
)
end
shape.methods[:fetch] = hash_shape.methods[:fetch].yield_self do |update|
update or raise
Shape::Entry.new(
+ method_name: :fetch,
private_method: false,
- method_types: record.elements.flat_map {|key_value, value_type|
- key_type = AST::Types::Literal.new(value: key_value, location: nil)
+ overloads: record.elements.flat_map {|key_value, value_type|
+ key_type = AST::Types::Literal.new(value: key_value)
[
MethodType.new(
type_params: [],
type: Function.new(
params: Function::Params.build(required: [key_type]),
return_type: value_type,
location: nil
),
- block: nil,
- method_decls: Set[]
+ block: nil
),
MethodType.new(
- type_params: [TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false)],
+ type_params: [TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false, default_type: nil)],
type: Function.new(
params: Function::Params.build(required: [key_type, AST::Types::Var.new(name: :T)]),
return_type: AST::Types::Union.build(types: [value_type, AST::Types::Var.new(name: :T)]),
location: nil
),
- block: nil,
- method_decls: Set[]
+ block: nil
),
MethodType.new(
- type_params: [TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false)],
+ type_params: [TypeParam.new(name: :T, upper_bound: nil, variance: :invariant, unchecked: false, default_type: nil)],
type: Function.new(
params: Function::Params.build(required: [key_type]),
return_type: AST::Types::Union.build(types: [value_type, AST::Types::Var.new(name: :T)]),
location: nil
),
@@ -669,29 +683,39 @@
return_type: AST::Types::Var.new(name: :T),
location: nil
),
optional: false,
self_type: nil
- ),
- method_decls: Set[]
+ )
)
- ]
- } + update.method_types
+ ].map { Shape::MethodOverload.new(_1, []) }
+ } + update.overloads
)
end
shape
end
def proc_shape(proc, proc_shape)
shape = Shape.new(type: proc, private: true)
shape.methods.merge!(proc_shape.methods)
- shape.methods[:[]] = shape.methods[:call] = Shape::Entry.new(
+ overload = Shape::MethodOverload.new(
+ MethodType.new(type_params: [], type: proc.type, block: proc.block),
+ []
+ )
+
+ shape.methods[:[]] = Shape::Entry.new(
+ method_name: :[],
private_method: false,
- method_types: [MethodType.new(type_params: [], type: proc.type, block: proc.block, method_decls: Set[])]
+ overloads: [overload]
)
+ shape.methods[:call] = Shape::Entry.new(
+ method_name: :call,
+ private_method: false,
+ overloads: [overload]
+ )
shape
end
def replace_primitive_method(method_name, method_def, method_type)
@@ -705,11 +729,11 @@
when RBS::BuiltinNames::Object.name,
RBS::BuiltinNames::Kernel.name
if member.instance?
return method_type.with(
type: method_type.type.with(
- return_type: AST::Types::Logic::ReceiverIsArg.new(location: method_type.type.return_type.location)
+ return_type: AST::Types::Logic::ReceiverIsArg.instance()
)
)
end
end
@@ -719,11 +743,11 @@
AST::Builtin::NilClass.module_name,
RBS::BuiltinNames::Kernel.name
if member.instance?
return method_type.with(
type: method_type.type.with(
- return_type: AST::Types::Logic::ReceiverIsNil.new(location: method_type.type.return_type.location)
+ return_type: AST::Types::Logic::ReceiverIsNil.instance()
)
)
end
end
@@ -733,21 +757,21 @@
RBS::BuiltinNames::TrueClass.name,
RBS::BuiltinNames::FalseClass.name,
AST::Builtin::NilClass.module_name
return method_type.with(
type: method_type.type.with(
- return_type: AST::Types::Logic::Not.new(location: method_type.type.return_type.location)
+ return_type: AST::Types::Logic::Not.instance()
)
)
end
when :===
case defined_in
when RBS::BuiltinNames::Module.name
return method_type.with(
type: method_type.type.with(
- return_type: AST::Types::Logic::ArgIsReceiver.new(location: method_type.type.return_type.location)
+ return_type: AST::Types::Logic::ArgIsReceiver.instance()
)
)
when RBS::BuiltinNames::Object.name,
RBS::BuiltinNames::Kernel.name,
RBS::BuiltinNames::String.name,
@@ -757,19 +781,19 @@
RBS::BuiltinNames::FalseClass.name,
TypeName("::NilClass")
# Value based type-case works on literal types which is available for String, Integer, Symbol, TrueClass, FalseClass, and NilClass
return method_type.with(
type: method_type.type.with(
- return_type: AST::Types::Logic::ArgEqualsReceiver.new(location: method_type.type.return_type.location)
+ return_type: AST::Types::Logic::ArgEqualsReceiver.instance()
)
)
end
when :<, :<=
case defined_in
when RBS::BuiltinNames::Module.name
return method_type.with(
type: method_type.type.with(
- return_type: AST::Types::Logic::ArgIsAncestor.new(location: method_type.type.return_type.location)
+ return_type: AST::Types::Logic::ArgIsAncestor.instance()
)
)
end
end
end