-
Notifications
You must be signed in to change notification settings - Fork 234
Closed
Milestone
Description
DefinitionBuilder defines Class#new method if it doesn't exist and initialize is available for the instance.
rbs/lib/rbs/definition_builder.rb
Lines 902 to 951 in 8247716
| unless definition.methods.key?(:new) | |
| instance = build_instance(type_name) | |
| initialize = instance.methods[:initialize] | |
| if initialize | |
| class_params = entry.type_params.each.map(&:name) | |
| initialize_defs = initialize.defs | |
| definition.methods[:new] = Definition::Method.new( | |
| super_method: nil, | |
| defs: initialize_defs.map do |initialize_def| | |
| method_type = initialize_def.type | |
| class_type_param_vars = Set.new(class_params) | |
| method_type_param_vars = Set.new(method_type.type_params) | |
| if class_type_param_vars.intersect?(method_type_param_vars) | |
| renamed_method_params = method_type.type_params.map do |name| | |
| if class_type_param_vars.include?(name) | |
| Types::Variable.fresh(name).name | |
| else | |
| name | |
| end | |
| end | |
| method_params = class_params + renamed_method_params | |
| sub = Substitution.build(method_type.type_params, Types::Variable.build(renamed_method_params)) | |
| else | |
| method_params = class_params + method_type.type_params | |
| sub = Substitution.build([], []) | |
| end | |
| method_type = method_type.map_type {|ty| ty.sub(sub) } | |
| method_type = method_type.update( | |
| type_params: method_params, | |
| type: method_type.type.with_return_type(Types::Bases::Instance.new(location: nil)) | |
| ) | |
| Definition::Method::TypeDef.new( | |
| type: method_type, | |
| member: initialize_def.member, | |
| defined_in: initialize_def.defined_in, | |
| implemented_in: initialize_def.implemented_in | |
| ) | |
| end, | |
| accessibility: :public, | |
| annotations: [AST::Annotation.new(location: nil, string: "rbs:test:target")] | |
| ) | |
| end | |
| end |
But it has two problems.
First, it conceals new method that is defined in an ancestor.
For example:
# RBS
class C
def self.new: (String) -> untyped
end
class C2 < C
end# it is ok.
$ rbs -I . method --singleton C new
::C.new
defined_in: ::C
implementation: ::C
accessibility: public
types:
(::String) -> untyped
# It should be `(::String) -> untyped`, but doesn't.
$ rbs -I . method --singleton C2 new
::C2.new
defined_in:
implementation:
accessibility: public
types:
() -> ::C2Second, it defines new method for Module unexpectedly.
For example:
# RBS
module M
def initialize: (String, Integer) -> void
end# M.new should not exist, but it exists.
$ rbs -I . method --singleton M new
::M.new
defined_in:
implementation:
accessibility: public
types:
(::String, ::Integer) -> ::MReactions are currently unavailable