@@ -144,8 +144,11 @@ module Crystal
144
144
145
145
program.types.each { |_ , t | types << t }
146
146
147
+ overridden_method_locations = [] of String
147
148
while type = types.shift?
148
149
type .types?.try & .each { |_ , t | types << t }
150
+ # pp! type, def_overrides_parent_def(type)
151
+ def_overrides_parent_def(type ).each { |loc | overridden_method_locations << loc }
149
152
150
153
# Check for class instance 'def's
151
154
if type .responds_to?(:def_instances )
@@ -167,9 +170,38 @@ module Crystal
167
170
end
168
171
end
169
172
173
+ # Now remove all overridden methods
174
+ overridden_method_locations.each do |loc |
175
+ ret.delete(loc)
176
+ end
177
+
170
178
ret
171
179
end
172
180
181
+ private def def_overrides_parent_def (type ) : Array (String )
182
+ overriden_locations = [] of String
183
+ type .defs.try & .each_value do |defs_with_metadata |
184
+ defs_with_metadata.each do |def_with_metadata |
185
+ next if def_with_metadata.def.location.to_s.starts_with?(" expanded macro:" )
186
+ type .ancestors.each do |ancestor |
187
+ other_defs_with_metadata = ancestor.defs.try & .[def_with_metadata.def.name]?
188
+ other_defs_with_metadata.try & .each do |other_def_with_metadata |
189
+ next if other_def_with_metadata.def.location.to_s.starts_with?(" expanded macro:" )
190
+ found_def_with_same_name = true
191
+
192
+ if def_with_metadata.compare_strictness(other_def_with_metadata, self_owner: type , other_owner: ancestor) == 0
193
+ # puts "Method #{type}##{def_with_metadata.def.name} overrides #{ancestor}##{def_with_metadata.def.name}"
194
+ # Found a method with the same name and same, stricter or weaker restriction,
195
+ # so it overrides
196
+ overriden_locations << def_with_metadata.def.location.to_s
197
+ end
198
+ end
199
+ end
200
+ end
201
+ end
202
+ overriden_locations
203
+ end
204
+
173
205
# Given an 'arg', return its type that's good for printing (VirtualTypes suffix themselves with a '+')
174
206
private def resolve_type (arg )
175
207
t = arg.type
@@ -188,10 +220,7 @@ module Crystal
188
220
189
221
# Generates a map of (parsed) Def#location => Signature for that Def
190
222
private def init_signatures (accepted_defs : Hash (String , Crystal ::Def )) : Hash (String , Signature )
191
- # This is hard to read, but transforms the def_instances array into a hash of def.location -> its full Signature
192
223
@_signatures ||= accepted_def_instances(accepted_defs).compact_map do |location , def_instances |
193
- # Finally, combine all def_instances for a single def_obj_id into a single signature
194
-
195
224
parsed = accepted_defs[location]
196
225
197
226
all_typed_args = Hash (String , Set (Crystal ::Type )).new { |h , k | h[k] = Set (Crystal ::Type ).new }
@@ -235,6 +264,13 @@ module Crystal
235
264
else
236
265
raise " Unknown handling of arg #{ arg } at #{ def_instance.location } in #{ def_instance } \n #{ parsed } "
237
266
end
267
+
268
+ # Special case - we can have default args that are never used be a different type than what was set.
269
+ # Ensure those default arg types also get respected (i.e. `arg = nil` => `arg : Int32? = nil` instead
270
+ # of `arg : Int32 = nil`)
271
+ if def_val = arg.default_value
272
+ all_typed_args[arg.external_name] << program.semantic(def_val).type
273
+ end
238
274
end
239
275
240
276
encountered_non_splat_arg_def_instance |= ! encountered_splat_arg
0 commit comments