nitc: adaptive typing apply non-nullness when fallbacking
[nit.git] / src / semantize / typing.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Intraprocedural resolution of static types and OO-services
18 # By OO-services we mean message sending, attribute access, instantiation, etc.
19 module typing
20
21 import modelize
22 import local_var_init
23 import literal
24
25 redef class ToolContext
26 var typing_phase: Phase = new TypingPhase(self, [flow_phase, modelize_property_phase, local_var_init_phase])
27 end
28
29 private class TypingPhase
30 super Phase
31 redef fun process_npropdef(npropdef) do npropdef.do_typing(toolcontext.modelbuilder)
32 end
33
34 private class TypeVisitor
35 var modelbuilder: ModelBuilder
36
37 # The module of the analysis
38 # Used to correctly query the model
39 var mmodule: MModule
40
41 # The static type of the receiver
42 # Mainly used for type tests and type resolutions
43 var anchor: nullable MClassType = null
44
45 # The analyzed mclassdef
46 var mclassdef: nullable MClassDef = null
47
48 # The analyzed property
49 var mpropdef: nullable MPropDef
50
51 var selfvariable = new Variable("self")
52
53 # Is `self` use restricted?
54 # * no explicit `self`
55 # * method called on the implicit self must be top-level
56 # Currently only used for `new` factory since there is no valid receiver inside
57 var is_toplevel_context = false
58
59 init
60 do
61 var mpropdef = self.mpropdef
62
63 if mpropdef != null then
64 self.mpropdef = mpropdef
65 var mclassdef = mpropdef.mclassdef
66 self.mclassdef = mclassdef
67 self.anchor = mclassdef.bound_mtype
68
69 var mclass = mclassdef.mclass
70
71 var selfvariable = new Variable("self")
72 self.selfvariable = selfvariable
73 selfvariable.declared_type = mclass.mclass_type
74
75 var mprop = mpropdef.mproperty
76 if mprop isa MMethod and mprop.is_new then
77 is_toplevel_context = true
78 end
79 end
80 end
81
82 fun anchor_to(mtype: MType): MType
83 do
84 var anchor = anchor
85 if anchor == null then
86 assert not mtype.need_anchor
87 return mtype
88 end
89 return mtype.anchor_to(mmodule, anchor)
90 end
91
92 fun is_subtype(sub, sup: MType): Bool
93 do
94 return sub.is_subtype(mmodule, anchor, sup)
95 end
96
97 fun resolve_for(mtype, subtype: MType, for_self: Bool): MType
98 do
99 #print "resolve_for {mtype} sub={subtype} forself={for_self} mmodule={mmodule} anchor={anchor}"
100 var res = mtype.resolve_for(subtype, anchor, mmodule, not for_self)
101 return res
102 end
103
104 # Check that `sub` is a subtype of `sup`.
105 # If `sub` is not a valid suptype, then display an error on `node` and return `null`.
106 # If `sub` is a safe subtype of `sup`, then return `sub`.
107 # If `sub` is an unsafe subtype (i.e., an implicit cast is required), then return `sup`.
108 #
109 # The point of the return type is to determinate the usable type on an expression when `autocast` is true:
110 # If the suptype is safe, then the return type is the one on the expression typed by `sub`.
111 # Is the subtype is unsafe, then the return type is the one of an implicit cast on `sup`.
112 fun check_subtype(node: ANode, sub, sup: MType, autocast: Bool): nullable MType
113 do
114 if self.is_subtype(sub, sup) then return sub
115 if autocast and self.is_subtype(sub, self.anchor_to(sup)) then
116 # FIXME workaround to the current unsafe typing policy. To remove once fixed virtual types exists.
117 #node.debug("Unsafe typing: expected {sup}, got {sub}")
118 return sup
119 end
120 if sup isa MErrorType then return null # Skip error
121 if sub.need_anchor then
122 var u = anchor_to(sub)
123 self.modelbuilder.error(node, "Type Error: expected `{sup}`, got `{sub}: {u}`.")
124 else
125 self.modelbuilder.error(node, "Type Error: expected `{sup}`, got `{sub}`.")
126 end
127 return null
128 end
129
130 # Visit an expression and do not care about the return value
131 fun visit_stmt(nexpr: nullable AExpr)
132 do
133 if nexpr == null then return
134 nexpr.accept_typing(self)
135 end
136
137 # Visit an expression and expects that it is not a statement
138 # Return the type of the expression
139 # Display an error and return null if:
140 # * the type cannot be determined or
141 # * `nexpr` is a statement
142 fun visit_expr(nexpr: AExpr): nullable MType
143 do
144 nexpr.accept_typing(self)
145 var mtype = nexpr.mtype
146 if mtype != null then return mtype
147 if not nexpr.is_typed then
148 if not self.modelbuilder.toolcontext.error_count > 0 then # check that there is really an error
149 if self.modelbuilder.toolcontext.verbose_level > 1 then
150 nexpr.debug("No return type but no error.")
151 end
152 end
153 return null # forward error
154 end
155 var more_message = null
156 var p = nexpr.parent
157 if p != null then more_message = p.bad_expr_message(nexpr)
158 if more_message == null then more_message = "" else more_message = " " + more_message
159 self.error(nexpr, "Error: expected an expression{more_message}.")
160 return null
161 end
162
163 # Visit an expression and expect its static type is a least a `sup`
164 # Return the type of the expression or null if
165 # * the type cannot be determined or
166 # * `nexpr` is a statement or
167 # * `nexpr` is not a `sup`
168 fun visit_expr_subtype(nexpr: AExpr, sup: nullable MType): nullable MType
169 do
170 var sub = visit_expr(nexpr)
171 if sub == null then return null # Forward error
172
173 if sup == null then return null # Forward error
174
175 var res = check_subtype(nexpr, sub, sup, true)
176 if res != sub then
177 nexpr.implicit_cast_to = res
178 end
179 return res
180 end
181
182 # Visit an expression and expect its static type is a `Bool`
183 # Return the type of the expression or null if
184 # * the type cannot be determined or
185 # * `nexpr` is a statement or
186 # * `nexpr` is not a `Bool`
187 fun visit_expr_bool(nexpr: AExpr): nullable MType
188 do
189 return self.visit_expr_subtype(nexpr, self.type_bool(nexpr))
190 end
191
192
193 fun check_expr_cast(node: ANode, nexpr: AExpr, ntype: AType): nullable MType
194 do
195 var sub = nexpr.mtype
196 if sub == null then return null # Forward error
197
198 var sup = ntype.mtype
199 if sup == null then return null # Forward error
200
201 if sup == sub then
202 self.modelbuilder.warning(node, "useless-type-test", "Warning: expression is already a `{sup}`.")
203 else if self.is_subtype(sub, sup) then
204 self.modelbuilder.warning(node, "useless-type-test", "Warning: expression is already a `{sup}` since it is a `{sub}`.")
205 end
206 return sup
207 end
208
209 # Can `mtype` be null (up to the current knowledge)?
210 fun can_be_null(mtype: MType): Bool
211 do
212 if mtype isa MNullableType or mtype isa MNullType then return true
213 if mtype isa MFormalType then
214 var x = anchor_to(mtype)
215 if x isa MNullableType or x isa MNullType then return true
216 end
217 return false
218 end
219
220 # Check that `mtype` can be null (up to the current knowledge).
221 #
222 # If not then display a `useless-null-test` warning on node and return false.
223 # Else return true.
224 fun check_can_be_null(anode: ANode, mtype: MType): Bool
225 do
226 if mtype isa MNullType then
227 modelbuilder.warning(anode, "useless-null-test", "Warning: expression is always `null`.")
228 return true
229 end
230 if can_be_null(mtype) then return true
231
232 if mtype isa MFormalType then
233 var res = anchor_to(mtype)
234 modelbuilder.warning(anode, "useless-null-test", "Warning: expression is not null, since it is a `{mtype}: {res}`.")
235 else
236 modelbuilder.warning(anode, "useless-null-test", "Warning: expression is not null, since it is a `{mtype}`.")
237 end
238 return false
239 end
240
241 # Special verification on != and == for null
242 # Return true
243 fun null_test(anode: ABinopExpr)
244 do
245 var mtype = anode.n_expr.mtype
246 var mtype2 = anode.n_expr2.mtype
247
248 if mtype == null or mtype2 == null then return
249
250 if not mtype2 isa MNullType then return
251
252 # Check of useless null
253 if not can_be_null(mtype) then return
254
255 if mtype isa MNullType then
256 # Because of type adaptation, we cannot just stop here
257 # so return use `null` as a bottom type that will be merged easily (cf) `merge_types`
258 mtype = null
259 else
260 mtype = mtype.as_notnull
261 end
262
263 # Check for type adaptation
264 var variable = anode.n_expr.its_variable
265 if variable == null then return
266
267 # One is null (mtype2 see above) the other is not null
268 if anode isa AEqExpr then
269 anode.after_flow_context.when_true.set_var(self, variable, mtype2)
270 anode.after_flow_context.when_false.set_var(self, variable, mtype)
271 else if anode isa ANeExpr then
272 anode.after_flow_context.when_false.set_var(self, variable, mtype2)
273 anode.after_flow_context.when_true.set_var(self, variable, mtype)
274 else
275 abort
276 end
277 end
278
279 fun try_get_mproperty_by_name2(anode: ANode, mtype: MType, name: String): nullable MProperty
280 do
281 return self.modelbuilder.try_get_mproperty_by_name2(anode, mmodule, mtype, name)
282 end
283
284 fun resolve_mtype(node: AType): nullable MType
285 do
286 return self.modelbuilder.resolve_mtype(mmodule, mclassdef, node)
287 end
288
289 fun try_get_mclass(node: ANode, name: String): nullable MClass
290 do
291 var mclass = modelbuilder.try_get_mclass_by_name(node, mmodule, name)
292 return mclass
293 end
294
295 fun get_mclass(node: ANode, name: String): nullable MClass
296 do
297 var mclass = modelbuilder.get_mclass_by_name(node, mmodule, name)
298 return mclass
299 end
300
301 fun type_bool(node: ANode): nullable MType
302 do
303 var mclass = self.get_mclass(node, "Bool")
304 if mclass == null then return null
305 return mclass.mclass_type
306 end
307
308 fun get_method(node: ANode, recvtype: MType, name: String, recv_is_self: Bool): nullable CallSite
309 do
310 var unsafe_type = self.anchor_to(recvtype)
311
312 #debug("recv: {recvtype} (aka {unsafe_type})")
313 if recvtype isa MNullType then
314 var objclass = get_mclass(node, "Object")
315 if objclass == null then return null # Forward error
316 unsafe_type = objclass.mclass_type
317 end
318
319 var mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
320 if name == "new" and mproperty == null then
321 name = "init"
322 mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
323 end
324
325 if mproperty == null then
326 if recv_is_self then
327 self.modelbuilder.error(node, "Error: method or variable `{name}` unknown in `{recvtype}`.")
328 else if recvtype.need_anchor then
329 self.modelbuilder.error(node, "Error: method `{name}` does not exists in `{recvtype}: {unsafe_type}`.")
330 else
331 self.modelbuilder.error(node, "Error: method `{name}` does not exists in `{recvtype}`.")
332 end
333 return null
334 end
335
336 assert mproperty isa MMethod
337
338 # `null` only accepts some methods of object.
339 if recvtype isa MNullType and not mproperty.is_null_safe then
340 self.error(node, "Error: method `{name}` called on `null`.")
341 return null
342 else if unsafe_type isa MNullableType and not mproperty.is_null_safe then
343 modelbuilder.advice(node, "call-on-nullable", "Warning: method call on a nullable receiver `{recvtype}`.")
344 end
345
346 if is_toplevel_context and recv_is_self and not mproperty.is_toplevel then
347 error(node, "Error: `{name}` is not a top-level method, thus need a receiver.")
348 end
349 if not recv_is_self and mproperty.is_toplevel then
350 error(node, "Error: cannot call `{name}`, a top-level method, with a receiver.")
351 end
352
353 if mproperty.visibility == protected_visibility and not recv_is_self and self.mmodule.visibility_for(mproperty.intro_mclassdef.mmodule) < intrude_visibility and not modelbuilder.toolcontext.opt_ignore_visibility.value then
354 self.modelbuilder.error(node, "Error: method `{name}` is protected and can only accessed by `self`.")
355 return null
356 end
357
358 var info = mproperty.deprecation
359 if info != null and self.mpropdef.mproperty.deprecation == null then
360 var mdoc = info.mdoc
361 if mdoc != null then
362 self.modelbuilder.warning(node, "deprecated-method", "Deprecation Warning: method `{name}` is deprecated: {mdoc.content.first}")
363 else
364 self.modelbuilder.warning(node, "deprecated-method", "Deprecation Warning: method `{name}` is deprecated.")
365 end
366 end
367
368 var propdefs = mproperty.lookup_definitions(self.mmodule, unsafe_type)
369 var mpropdef
370 if propdefs.length == 0 then
371 self.modelbuilder.error(node, "Type Error: no definition found for property `{name}` in `{unsafe_type}`.")
372 return null
373 else if propdefs.length == 1 then
374 mpropdef = propdefs.first
375 else
376 self.modelbuilder.warning(node, "property-conflict", "Warning: conflicting property definitions for property `{name}` in `{unsafe_type}`: {propdefs.join(" ")}")
377 mpropdef = mproperty.intro
378 end
379
380
381 var msignature = mpropdef.new_msignature or else mpropdef.msignature
382 if msignature == null then return null # skip error
383 msignature = resolve_for(msignature, recvtype, recv_is_self).as(MSignature)
384
385 var erasure_cast = false
386 var rettype = mpropdef.msignature.return_mtype
387 if not recv_is_self and rettype != null then
388 rettype = rettype.undecorate
389 if rettype isa MParameterType then
390 var erased_rettype = msignature.return_mtype
391 assert erased_rettype != null
392 #node.debug("Erasure cast: Really a {rettype} but unsafely a {erased_rettype}")
393 erasure_cast = true
394 end
395 end
396
397 var callsite = new CallSite(node.hot_location, recvtype, mmodule, anchor, recv_is_self, mproperty, mpropdef, msignature, erasure_cast)
398 return callsite
399 end
400
401 fun try_get_method(node: ANode, recvtype: MType, name: String, recv_is_self: Bool): nullable CallSite
402 do
403 var unsafe_type = self.anchor_to(recvtype)
404 var mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
405 if mproperty == null then return null
406 return get_method(node, recvtype, name, recv_is_self)
407 end
408
409
410 # Visit the expressions of args and check their conformity with the corresponding type in signature
411 # The point of this method is to handle varargs correctly
412 # Note: The signature must be correctly adapted
413 fun check_signature(node: ANode, args: Array[AExpr], mproperty: MProperty, msignature: MSignature): nullable SignatureMap
414 do
415 var vararg_rank = msignature.vararg_rank
416 if vararg_rank >= 0 then
417 if args.length < msignature.arity then
418 modelbuilder.error(node, "Error: expected at least {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
419 return null
420 end
421 else if args.length != msignature.arity then
422 # Too much argument
423 if args.length > msignature.arity then
424 modelbuilder.error(node, "Error: expected {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
425 return null
426 end
427 # Other cases are managed later
428 end
429
430
431 #debug("CALL {unsafe_type}.{msignature}")
432
433 # Associate each parameter to a position in the arguments
434 var map = new SignatureMap
435
436 # Special case for the isolated last argument
437 # TODO: reify this method characteristics (where? the param, the signature, the method?)
438 var last_is_padded = mproperty.name.chars.last == '='
439 var nbargs = args.length
440 if last_is_padded then
441 nbargs -= 1
442 assert not args.last isa ANamedargExpr
443 map.map[msignature.arity - 1] = args.length - 1
444 self.visit_expr_subtype(args.last, msignature.mparameters.last.mtype)
445 end
446
447 # First, handle named arguments
448 for i in [0..args.length[ do
449 var e = args[i]
450 if not e isa ANamedargExpr then continue
451 var name = e.n_id.text
452 var param = msignature.mparameter_by_name(name)
453 if param == null then
454 modelbuilder.error(e.n_id, "Error: no parameter `{name}` for `{mproperty}{msignature}`.")
455 return null
456 end
457 var idx = msignature.mparameters.index_of(param)
458 var prev = map.map.get_or_null(idx)
459 if prev != null then
460 modelbuilder.error(e, "Error: parameter `{name}` already associated with argument #{prev} for `{mproperty}{msignature}`.")
461 return null
462 end
463 map.map[idx] = i
464 e.mtype = self.visit_expr_subtype(e.n_expr, param.mtype)
465 end
466
467 # Number of minimum mandatory remaining parameters
468 var min_arity = 0
469
470 # Second, associate remaining parameters
471 var vararg_decl = args.length - msignature.arity
472 var j = 0
473 for i in [0..msignature.arity[ do
474 # Skip parameters associated by name
475 if map.map.has_key(i) then continue
476
477 var param = msignature.mparameters[i]
478
479 # Search the next free argument: skip named arguments since they are already associated
480 while j < nbargs and args[j] isa ANamedargExpr do j += 1
481 if j >= nbargs then
482 if not param.mtype isa MNullableType then
483 min_arity = j + 1
484 end
485 j += 1
486 continue
487 end
488 var arg = args[j]
489 map.map[i] = j
490 j += 1
491
492 if i == vararg_rank then
493 j += vararg_decl
494 continue # skip the vararg
495 end
496
497 if not param.is_vararg then
498 var paramtype = param.mtype
499 self.visit_expr_subtype(arg, paramtype)
500 else
501 check_one_vararg(arg, param)
502 end
503 end
504
505 if min_arity > 0 then
506 if last_is_padded then min_arity += 1
507 if min_arity < msignature.arity then
508 modelbuilder.error(node, "Error: expected at least {min_arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
509 else
510 modelbuilder.error(node, "Error: expected {min_arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
511 end
512 return null
513 end
514
515 # Third, check varargs
516 if vararg_rank >= 0 then
517 var paramtype = msignature.mparameters[vararg_rank].mtype
518 var first = args[vararg_rank]
519 if vararg_decl == 0 then
520 if not check_one_vararg(first, msignature.mparameters[vararg_rank]) then return null
521 else
522 first.vararg_decl = vararg_decl + 1
523 for i in [vararg_rank..vararg_rank+vararg_decl] do
524 self.visit_expr_subtype(args[i], paramtype)
525 end
526 end
527 end
528
529 return map
530 end
531
532 # Check an expression as a single vararg.
533 # The main point of the method if to handle the case of reversed vararg (see `AVarargExpr`)
534 fun check_one_vararg(arg: AExpr, param: MParameter): Bool
535 do
536 var paramtype = param.mtype
537 var mclass = get_mclass(arg, "Array")
538 if mclass == null then return false # Forward error
539 var array_mtype = mclass.get_mtype([paramtype])
540 if arg isa AVarargExpr then
541 self.visit_expr_subtype(arg.n_expr, array_mtype)
542 arg.mtype = arg.n_expr.mtype
543 else
544 # only one vararg, maybe `...` was forgot, so be gentle!
545 var t = visit_expr(arg)
546 if t == null then return false # Forward error
547 if not is_subtype(t, paramtype) and is_subtype(t, array_mtype) then
548 # Not acceptable but could be a `...`
549 error(arg, "Type Error: expected `{paramtype}`, got `{t}`. Is an ellipsis `...` missing on the argument?")
550 return false
551 end
552 # Standard valid vararg, finish the job
553 arg.vararg_decl = 1
554 self.visit_expr_subtype(arg, paramtype)
555 end
556 return true
557 end
558
559 fun error(node: ANode, message: String)
560 do
561 self.modelbuilder.error(node, message)
562 end
563
564 fun get_variable(node: AExpr, variable: Variable): nullable MType
565 do
566 if not variable.is_adapted then return variable.declared_type
567
568 var flow = node.after_flow_context
569 if flow == null then return null # skip error
570
571 if flow.vars.has_key(variable) then
572 return flow.vars[variable]
573 else
574 #node.debug("*** START Collected for {variable}")
575 var mtypes = flow.collect_types(variable)
576 #node.debug("**** END Collected for {variable}")
577 if mtypes.length == 0 then
578 return variable.declared_type
579 else if mtypes.length == 1 then
580 return mtypes.first
581 else
582 var res = merge_types(node,mtypes)
583 if res == null then
584 res = variable.declared_type
585 # Try to fallback to a non-null version
586 if res != null and can_be_null(res) then do
587 for t in mtypes do
588 if t != null and can_be_null(t) then break label
589 end
590 res = res.as_notnull
591 end label
592 end
593 return res
594 end
595 end
596 end
597
598 # Some variables where type-adapted during the visit
599 var dirty = false
600
601 # Some loops had been visited during the visit
602 var has_loop = false
603
604 fun set_variable(node: AExpr, variable: Variable, mtype: nullable MType)
605 do
606 var flow = node.after_flow_context
607 assert flow != null
608
609 flow.set_var(self, variable, mtype)
610 end
611
612 # Find the exact representable most specific common super-type in `col`.
613 #
614 # Try to find the most specific common type that is a super-type of each types
615 # in `col`.
616 # In most cases, the result is simply the most general type in `col`.
617 # If nullables types are involved, then the nullable information is correctly preserved.
618 # If incomparable super-types exists in `col`, them no solution is given and the `null`
619 # value is returned (since union types are non representable in Nit)
620 #
621 # The `null` values in `col` are ignored, nulltypes (MNullType) are considered.
622 #
623 # Returns the `null` value if:
624 #
625 # * `col` is empty
626 # * `col` only have null values
627 # * there is a conflict
628 #
629 # Example (with a diamond A,B,C,D):
630 #
631 # * merge(A,B,C) -> A, because A is the most general type in {A,B,C}
632 # * merge(C,B) -> null, there is conflict, because `B or C` cannot be represented
633 # * merge(A,nullable B) -> nullable A, because A is the most general type and
634 # the nullable information is preserved
635 fun merge_types(node: ANode, col: Array[nullable MType]): nullable MType
636 do
637 if col.length == 1 then return col.first
638 for t1 in col do
639 if t1 == null then continue # return null
640 var found = true
641 for t2 in col do
642 if t2 == null then continue # return null
643 if can_be_null(t2) and not can_be_null(t1) then
644 t1 = t1.as_nullable
645 end
646 if not is_subtype(t2, t1) then found = false
647 end
648 if found then
649 #print "merge {col.join(" ")} -> {t1}"
650 return t1
651 end
652 end
653 #self.modelbuilder.warning(node, "Type Error: {col.length} conflicting types: <{col.join(", ")}>")
654 return null
655 end
656
657 # Find a most general common subtype between `type1` and `type2`.
658 #
659 # Find the most general type that is a subtype of `type2` and, if possible, a subtype of `type1`.
660 # Basically, this return the most specific type between `type1` and `type2`.
661 # If nullable types are involved, the information is correctly preserved.
662 # If `type1` and `type2` are incomparable then `type2` is preferred (since intersection types
663 # are not representable in Nit).
664 #
665 # The `null` value is returned if both `type1` and `type2` are null.
666 #
667 # Examples (with diamond A,B,C,D):
668 #
669 # * intersect_types(A,B) -> B, because B is a subtype of A
670 # * intersect_types(B,A) -> B, because B is a subtype of A
671 # * intersect_types(B,C) -> C, B and C are incomparable,
672 # `type2` is then preferred (`B and C` cannot be represented)
673 # * intersect_types(nullable B,A) -> B, because B<:A and the non-null information is preserved
674 # * intersect_types(B,nullable C) -> C, `type2` is preferred and the non-null information is preserved
675 fun intersect_types(node: ANode, type1, type2: nullable MType): nullable MType
676 do
677 if type1 == null then return type2
678 if type2 == null then return type1
679
680 if not can_be_null(type2) or not can_be_null(type1) then
681 type1 = type1.as_notnull
682 type2 = type2.as_notnull
683 end
684
685 var res
686 if is_subtype(type1, type2) then
687 res = type1
688 else
689 res = type2
690 end
691 return res
692 end
693
694 # Find a most general type that is a subtype of `type1` but not one of `type2`.
695 #
696 # Basically, this returns `type1`-`type2` but since there is no substraction type
697 # in Nit this just returns `type1` most of the case.
698 #
699 # The few other cases are if `type2` is a super-type and if some nullable information
700 # is present.
701 #
702 # The `null` value is returned if `type1` is null.
703 #
704 # Examples (with diamond A,B,C,D):
705 #
706 # * diff_types(A,B) -> A, because the notB cannot be represented
707 # * diff_types(B,A) -> None (absurd type), because B<:A
708 # * diff_types(nullable A, nullable B) -> A, because null is removed
709 # * diff_types(nullable B, A) -> Null, because anything but null is removed
710 fun diff_types(node: ANode, type1, type2: nullable MType): nullable MType
711 do
712 if type1 == null then return null
713 if type2 == null then return type1
714
715 # if t1 <: t2 then t1-t2 = bottom
716 if is_subtype(type1, type2) then
717 return modelbuilder.model.null_type.as_notnull
718 end
719
720 # else if t1 <: nullable t2 then t1-t2 = nulltype
721 if is_subtype(type1, type2.as_nullable) then
722 return modelbuilder.model.null_type
723 end
724
725 # else t2 can be null and type2 must accept null then null is excluded in t1
726 if can_be_null(type1) and (type2 isa MNullableType or type2 isa MNullType) then
727 return type1.as_notnull
728 end
729
730 return type1
731 end
732 end
733
734 # Mapping between parameters and arguments in a call.
735 #
736 # Parameters and arguments are not stored in the class but referenced by their position (starting from 0)
737 #
738 # The point of this class is to help engine and other things to map arguments in the AST to parameters of the model.
739 class SignatureMap
740 # Associate a parameter to an argument
741 var map = new ArrayMap[Int, Int]
742 end
743
744 # A specific method call site with its associated informations.
745 class CallSite
746 super MEntity
747
748 redef var location: Location
749
750 # The static type of the receiver (possibly unresolved)
751 var recv: MType
752
753 # The module where the callsite is present
754 var mmodule: MModule
755
756 # The anchor to use with `recv` or `msignature`
757 var anchor: nullable MClassType
758
759 # Is the receiver self?
760 # If "for_self", virtual types of the signature are kept
761 # If "not_for_self", virtual type are erased
762 var recv_is_self: Bool
763
764 # The designated method
765 var mproperty: MMethod
766
767 # The statically designated method definition
768 # The most specif one, it is.
769 var mpropdef: MMethodDef
770
771 # The resolved signature for the receiver
772 var msignature: MSignature
773
774 # Is a implicit cast required on erasure typing policy?
775 var erasure_cast: Bool
776
777 # The mapping used on the call to associate arguments to parameters
778 # If null then no specific association is required.
779 var signaturemap: nullable SignatureMap = null
780
781 private fun check_signature(v: TypeVisitor, node: ANode, args: Array[AExpr]): Bool
782 do
783 var map = v.check_signature(node, args, self.mproperty, self.msignature)
784 signaturemap = map
785 if map == null then is_broken = true
786 return map == null
787 end
788
789 # Information about the callsite to display on a node
790 fun dump_info(v: ASTDump): String do
791 return "{recv}.{mpropdef}{msignature}"
792 end
793 end
794
795 redef class Variable
796 # The declared type of the variable
797 var declared_type: nullable MType is writable
798
799 # Was the variable type-adapted?
800 # This is used to speedup type retrieval while it remains `false`
801 private var is_adapted = false
802 end
803
804 redef class FlowContext
805 # Store changes of types because of type evolution
806 private var vars = new HashMap[Variable, nullable MType]
807
808 # Adapt the variable to a static type
809 # Warning1: do not modify vars directly.
810 # Warning2: sub-flow may have cached a unadapted variable
811 private fun set_var(v: TypeVisitor, variable: Variable, mtype: nullable MType)
812 do
813 if variable.declared_type == mtype and not variable.is_adapted then return
814 if vars.has_key(variable) and vars[variable] == mtype then return
815 self.vars[variable] = mtype
816 v.dirty = true
817 variable.is_adapted = true
818 #node.debug "set {variable} to {mtype or else "X"}"
819 end
820
821 # Look in the flow and previous flow and collect all first reachable type adaptation of a local variable
822 private fun collect_types(variable: Variable): Array[nullable MType]
823 do
824 #node.debug "flow for {variable}"
825 var res = new Array[nullable MType]
826
827 var todo = [self]
828 var seen = new HashSet[FlowContext]
829 while not todo.is_empty do
830 var f = todo.pop
831 if f.is_unreachable then continue
832 if seen.has(f) then continue
833 seen.add f
834
835 if f.vars.has_key(variable) then
836 # Found something. Collect it and do not process further on this path
837 res.add f.vars[variable]
838 #f.node.debug "process {variable}: got {f.vars[variable] or else "X"}"
839 else
840 todo.add_all f.previous
841 todo.add_all f.loops
842 if f.previous.is_empty then
843 # Root flowcontext mean a parameter or something related
844 res.add variable.declared_type
845 #f.node.debug "root process {variable}: got {variable.declared_type or else "X"}"
846 end
847 end
848 end
849 #self.node.debug "##### end flow for {variable}: {res.join(" ")}"
850 return res
851 end
852 end
853
854 redef class APropdef
855 # The entry point of the whole typing analysis
856 fun do_typing(modelbuilder: ModelBuilder)
857 do
858 end
859
860 # The variable associated to the receiver (if any)
861 var selfvariable: nullable Variable
862 end
863
864 redef class AMethPropdef
865 redef fun do_typing(modelbuilder: ModelBuilder)
866 do
867 var mpropdef = self.mpropdef
868 if mpropdef == null then return # skip error
869
870 var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
871 self.selfvariable = v.selfvariable
872
873 var mmethoddef = self.mpropdef.as(not null)
874 var msignature = mmethoddef.msignature
875 if msignature == null then return # skip error
876 for i in [0..msignature.arity[ do
877 var mtype = msignature.mparameters[i].mtype
878 if msignature.vararg_rank == i then
879 var arrayclass = v.get_mclass(self.n_signature.n_params[i], "Array")
880 if arrayclass == null then return # Skip error
881 mtype = arrayclass.get_mtype([mtype])
882 end
883 var variable = self.n_signature.n_params[i].variable
884 assert variable != null
885 variable.declared_type = mtype
886 end
887
888 var nblock = self.n_block
889 if nblock == null then return
890
891 loop
892 v.dirty = false
893 v.visit_stmt(nblock)
894 if not v.has_loop or not v.dirty then break
895 end
896
897 var post_visitor = new PostTypingVisitor(v)
898 post_visitor.enter_visit(self)
899
900 if not nblock.after_flow_context.is_unreachable and msignature.return_mtype != null then
901 # We reach the end of the function without having a return, it is bad
902 v.error(self, "Error: reached end of function; expected `return` with a value.")
903 end
904 end
905 end
906
907 private class PostTypingVisitor
908 super Visitor
909 var type_visitor: TypeVisitor
910 redef fun visit(n) do
911 n.visit_all(self)
912 n.accept_post_typing(type_visitor)
913 if n isa AExpr and n.mtype == null and not n.is_typed then
914 n.is_broken = true
915 end
916 end
917 end
918
919 redef class ANode
920 private fun accept_post_typing(v: TypeVisitor) do end
921
922 # An additional information message to explain the role of a child expression.
923 #
924 # The point of the method is to allow some kind of double dispatch so the parent
925 # choose how to describe its children.
926 private fun bad_expr_message(child: AExpr): nullable String do return null
927 end
928
929 redef class AAttrPropdef
930 redef fun do_typing(modelbuilder: ModelBuilder)
931 do
932 if not has_value then return
933
934 var mpropdef = self.mreadpropdef
935 if mpropdef == null or mpropdef.msignature == null then return # skip error
936
937 var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
938 self.selfvariable = v.selfvariable
939
940 var nexpr = self.n_expr
941 if nexpr != null then
942 var mtype = self.mtype
943 v.visit_expr_subtype(nexpr, mtype)
944 end
945 var nblock = self.n_block
946 if nblock != null then
947 v.visit_stmt(nblock)
948 if not nblock.after_flow_context.is_unreachable then
949 # We reach the end of the init without having a return, it is bad
950 v.error(self, "Error: reached end of block; expected `return`.")
951 end
952 end
953 end
954 end
955
956 ###
957
958 redef class AExpr
959 # The static type of the expression.
960 # null if self is a statement or in case of error
961 var mtype: nullable MType = null
962
963 # Is the statement correctly typed?
964 # Used to distinguish errors and statements when `mtype == null`
965 var is_typed: Bool = false
966
967 # If required, the following implicit cast `.as(XXX)`
968 # Such a cast may by required after evaluating the expression when
969 # a unsafe operation is detected (silently accepted by the Nit language).
970 # The attribute is computed by `check_subtype`
971 var implicit_cast_to: nullable MType = null
972
973 # Return the variable read (if any)
974 # Used to perform adaptive typing
975 fun its_variable: nullable Variable do return null
976
977 private fun accept_typing(v: TypeVisitor)
978 do
979 v.error(self, "no implemented accept_typing for {self.class_name}")
980 end
981
982 # Is non-null if `self` is a leaf of a comprehension array construction.
983 # In this case, the enclosing literal array node is designated.
984 # The result of the evaluation of `self` must be
985 # stored inside the designated array (there is an implicit `push`)
986 var comprehension: nullable AArrayExpr = null
987
988 # It indicates the number of arguments collected as a vararg.
989 #
990 # When 0, the argument is used as is, without transformation.
991 # When 1, the argument is transformed into an singleton array.
992 # Above 1, the arguments and the next ones are transformed into a common array.
993 #
994 # This attribute is meaning less on expressions not used as attributes.
995 var vararg_decl: Int = 0
996
997 redef fun dump_info(v) do
998 var res = super
999 var mtype = self.mtype
1000 if mtype != null then
1001 res += v.yellow(":{mtype}")
1002 end
1003 var ict = self.implicit_cast_to
1004 if ict != null then
1005 res += v.yellow("(.as({ict}))")
1006 end
1007 return res
1008 end
1009 end
1010
1011 redef class ABlockExpr
1012 redef fun accept_typing(v)
1013 do
1014 for e in self.n_expr do v.visit_stmt(e)
1015 self.is_typed = true
1016 end
1017
1018 # The type of a blockexpr is the one of the last expression (or null if empty)
1019 redef fun mtype
1020 do
1021 if self.n_expr.is_empty then return null
1022 return self.n_expr.last.mtype
1023 end
1024 end
1025
1026 redef class AVardeclExpr
1027 redef fun accept_typing(v)
1028 do
1029 var variable = self.variable
1030 if variable == null then return # Skip error
1031
1032 var ntype = self.n_type
1033 var mtype: nullable MType
1034 if ntype == null then
1035 mtype = null
1036 else
1037 mtype = v.resolve_mtype(ntype)
1038 if mtype == null then return # Skip error
1039 end
1040
1041 var nexpr = self.n_expr
1042 if nexpr != null then
1043 if mtype != null then
1044 var etype = v.visit_expr_subtype(nexpr, mtype)
1045 if etype == mtype then
1046 assert ntype != null
1047 v.modelbuilder.advice(ntype, "useless-type", "Warning: useless type definition for variable `{variable.name}`")
1048 end
1049 else
1050 mtype = v.visit_expr(nexpr)
1051 if mtype == null then return # Skip error
1052 end
1053 end
1054
1055 var decltype = mtype
1056 if mtype == null or mtype isa MNullType then
1057 var objclass = v.get_mclass(self, "Object")
1058 if objclass == null then return # skip error
1059 decltype = objclass.mclass_type.as_nullable
1060 if mtype == null then mtype = decltype
1061 end
1062
1063 variable.declared_type = decltype
1064 v.set_variable(self, variable, mtype)
1065
1066 #debug("var {variable}: {mtype}")
1067
1068 self.mtype = mtype
1069 self.is_typed = true
1070 end
1071 end
1072
1073 redef class AVarExpr
1074 redef fun its_variable do return self.variable
1075 redef fun accept_typing(v)
1076 do
1077 var variable = self.variable
1078 if variable == null then return # Skip error
1079
1080 var mtype = v.get_variable(self, variable)
1081 if mtype != null then
1082 #debug("{variable} is {mtype}")
1083 else
1084 #debug("{variable} is untyped")
1085 end
1086
1087 self.mtype = mtype
1088 end
1089 end
1090
1091 redef class AVarAssignExpr
1092 redef fun accept_typing(v)
1093 do
1094 var variable = self.variable
1095 assert variable != null
1096
1097 var mtype = v.visit_expr_subtype(n_value, variable.declared_type)
1098
1099 v.set_variable(self, variable, mtype)
1100
1101 self.is_typed = true
1102 end
1103 end
1104
1105 redef class AReassignFormExpr
1106 # The method designed by the reassign operator.
1107 var reassign_callsite: nullable CallSite
1108
1109 var read_type: nullable MType = null
1110
1111 # Determine the `reassign_property`
1112 # `readtype` is the type of the reading of the left value.
1113 # `writetype` is the type of the writing of the left value.
1114 # (Because of `ACallReassignExpr`, both can be different.
1115 # Return the static type of the value to store.
1116 private fun resolve_reassignment(v: TypeVisitor, readtype, writetype: MType): nullable MType
1117 do
1118 var reassign_name = self.n_assign_op.operator
1119
1120 self.read_type = readtype
1121
1122 var callsite = v.get_method(self.n_assign_op, readtype, reassign_name, false)
1123 if callsite == null then return null # Skip error
1124 self.reassign_callsite = callsite
1125
1126 var msignature = callsite.msignature
1127 var rettype = msignature.return_mtype
1128 assert msignature.arity == 1 and rettype != null
1129
1130 var value_type = v.visit_expr_subtype(self.n_value, msignature.mparameters.first.mtype)
1131 if value_type == null then return null # Skip error
1132
1133 v.check_subtype(self, rettype, writetype, false)
1134 return rettype
1135 end
1136 end
1137
1138 redef class AVarReassignExpr
1139 redef fun accept_typing(v)
1140 do
1141 var variable = self.variable
1142 assert variable != null
1143
1144 var readtype = v.get_variable(self, variable)
1145 if readtype == null then return
1146
1147 read_type = readtype
1148
1149 var writetype = variable.declared_type
1150 if writetype == null then return
1151
1152 var rettype = self.resolve_reassignment(v, readtype, writetype)
1153
1154 v.set_variable(self, variable, rettype)
1155
1156 self.is_typed = rettype != null
1157 end
1158 end
1159
1160
1161 redef class AContinueExpr
1162 redef fun accept_typing(v)
1163 do
1164 var nexpr = self.n_expr
1165 if nexpr != null then
1166 v.visit_expr(nexpr)
1167 end
1168 self.is_typed = true
1169 end
1170 end
1171
1172 redef class ABreakExpr
1173 redef fun accept_typing(v)
1174 do
1175 var nexpr = self.n_expr
1176 if nexpr != null then
1177 v.visit_expr(nexpr)
1178 end
1179 self.is_typed = true
1180 end
1181 end
1182
1183 redef class AReturnExpr
1184 redef fun accept_typing(v)
1185 do
1186 var nexpr = self.n_expr
1187 var ret_type
1188 var mpropdef = v.mpropdef
1189 if mpropdef isa MMethodDef then
1190 ret_type = mpropdef.msignature.return_mtype
1191 else if mpropdef isa MAttributeDef then
1192 ret_type = mpropdef.static_mtype
1193 else
1194 abort
1195 end
1196 if nexpr != null then
1197 if ret_type != null then
1198 v.visit_expr_subtype(nexpr, ret_type)
1199 else
1200 v.visit_expr(nexpr)
1201 v.error(nexpr, "Error: `return` with value in a procedure.")
1202 return
1203 end
1204 else if ret_type != null then
1205 v.error(self, "Error: `return` without value in a function.")
1206 return
1207 end
1208 self.is_typed = true
1209 end
1210 end
1211
1212 redef class AAbortExpr
1213 redef fun accept_typing(v)
1214 do
1215 self.is_typed = true
1216 end
1217 end
1218
1219 redef class AIfExpr
1220 redef fun accept_typing(v)
1221 do
1222 v.visit_expr_bool(n_expr)
1223
1224 v.visit_stmt(n_then)
1225 v.visit_stmt(n_else)
1226
1227 self.is_typed = true
1228
1229 if n_then != null and n_else == null then
1230 self.mtype = n_then.mtype
1231 end
1232 end
1233 end
1234
1235 redef class AIfexprExpr
1236 redef fun accept_typing(v)
1237 do
1238 v.visit_expr_bool(n_expr)
1239
1240 var t1 = v.visit_expr(n_then)
1241 var t2 = v.visit_expr(n_else)
1242
1243 if t1 == null or t2 == null then
1244 return # Skip error
1245 end
1246
1247 var t = v.merge_types(self, [t1, t2])
1248 if t == null then
1249 v.error(self, "Type Error: ambiguous type `{t1}` vs `{t2}`.")
1250 end
1251 self.mtype = t
1252 end
1253 end
1254
1255 redef class ADoExpr
1256 redef fun accept_typing(v)
1257 do
1258 v.visit_stmt(n_block)
1259 v.visit_stmt(n_catch)
1260 self.is_typed = true
1261 end
1262 end
1263
1264 redef class AWhileExpr
1265 redef fun accept_typing(v)
1266 do
1267 v.has_loop = true
1268 v.visit_expr_bool(n_expr)
1269 v.visit_stmt(n_block)
1270 self.is_typed = true
1271 end
1272 end
1273
1274 redef class ALoopExpr
1275 redef fun accept_typing(v)
1276 do
1277 v.has_loop = true
1278 v.visit_stmt(n_block)
1279 self.is_typed = true
1280 end
1281 end
1282
1283 redef class AForExpr
1284 redef fun accept_typing(v)
1285 do
1286 v.has_loop = true
1287
1288 for g in n_groups do
1289 var mtype = v.visit_expr(g.n_expr)
1290 if mtype == null then return
1291 g.do_type_iterator(v, mtype)
1292 if g.is_broken then is_broken = true
1293 end
1294
1295 v.visit_stmt(n_block)
1296
1297 self.mtype = n_block.mtype
1298 self.is_typed = true
1299 end
1300 end
1301
1302 redef class AForGroup
1303 var coltype: nullable MClassType
1304
1305 var method_iterator: nullable CallSite
1306 var method_is_ok: nullable CallSite
1307 var method_item: nullable CallSite
1308 var method_next: nullable CallSite
1309 var method_key: nullable CallSite
1310 var method_finish: nullable CallSite
1311
1312 var method_lt: nullable CallSite
1313 var method_successor: nullable CallSite
1314
1315 private fun do_type_iterator(v: TypeVisitor, mtype: MType)
1316 do
1317 if mtype isa MNullType then
1318 v.error(self, "Type Error: `for` cannot iterate over `null`.")
1319 return
1320 end
1321
1322 # get obj class
1323 var objcla = v.get_mclass(self, "Object")
1324 if objcla == null then return
1325
1326 # check iterator method
1327 var itdef = v.get_method(self, mtype, "iterator", n_expr isa ASelfExpr)
1328 if itdef == null then
1329 v.error(self, "Type Error: `for` expects a type providing an `iterator` method, got `{mtype}`.")
1330 return
1331 end
1332 self.method_iterator = itdef
1333
1334 # check that iterator return something
1335 var ittype = itdef.msignature.return_mtype
1336 if ittype == null then
1337 v.error(self, "Type Error: `for` expects the method `iterator` to return an `Iterator` or `MapIterator` type.")
1338 return
1339 end
1340
1341 # get iterator type
1342 var colit_cla = v.try_get_mclass(self, "Iterator")
1343 var mapit_cla = v.try_get_mclass(self, "MapIterator")
1344 var is_col = false
1345 var is_map = false
1346
1347 if colit_cla != null and v.is_subtype(ittype, colit_cla.get_mtype([objcla.mclass_type.as_nullable])) then
1348 # Iterator
1349 var coltype = ittype.supertype_to(v.mmodule, v.anchor, colit_cla)
1350 var variables = self.variables
1351 if variables.length != 1 then
1352 v.error(self, "Type Error: `for` expects only one variable when using `Iterator`.")
1353 else
1354 variables.first.declared_type = coltype.arguments.first
1355 end
1356 is_col = true
1357 end
1358
1359 if mapit_cla != null and v.is_subtype(ittype, mapit_cla.get_mtype([objcla.mclass_type.as_nullable, objcla.mclass_type.as_nullable])) then
1360 # Map Iterator
1361 var coltype = ittype.supertype_to(v.mmodule, v.anchor, mapit_cla)
1362 var variables = self.variables
1363 if variables.length != 2 then
1364 v.error(self, "Type Error: `for` expects two variables when using `MapIterator`.")
1365 else
1366 variables[0].declared_type = coltype.arguments[0]
1367 variables[1].declared_type = coltype.arguments[1]
1368 end
1369 is_map = true
1370 end
1371
1372 if not is_col and not is_map then
1373 v.error(self, "Type Error: `for` expects the method `iterator` to return an `Iterator` or `MapIterator` type.")
1374 return
1375 end
1376
1377 # anchor formal and virtual types
1378 if mtype.need_anchor then mtype = v.anchor_to(mtype)
1379
1380 mtype = mtype.undecorate
1381 self.coltype = mtype.as(MClassType)
1382
1383 # get methods is_ok, next, item
1384 var ikdef = v.get_method(self, ittype, "is_ok", false)
1385 if ikdef == null then
1386 v.error(self, "Type Error: `for` expects a method `is_ok` in type `{ittype}`.")
1387 return
1388 end
1389 self.method_is_ok = ikdef
1390
1391 var itemdef = v.get_method(self, ittype, "item", false)
1392 if itemdef == null then
1393 v.error(self, "Type Error: `for` expects a method `item` in type `{ittype}`.")
1394 return
1395 end
1396 self.method_item = itemdef
1397
1398 var nextdef = v.get_method(self, ittype, "next", false)
1399 if nextdef == null then
1400 v.error(self, "Type Error: `for` expects a method `next` in type {ittype}.")
1401 return
1402 end
1403 self.method_next = nextdef
1404
1405 self.method_finish = v.try_get_method(self, ittype, "finish", false)
1406
1407 if is_map then
1408 var keydef = v.get_method(self, ittype, "key", false)
1409 if keydef == null then
1410 v.error(self, "Type Error: `for` expects a method `key` in type `{ittype}`.")
1411 return
1412 end
1413 self.method_key = keydef
1414 end
1415
1416 if self.variables.length == 1 and n_expr isa ARangeExpr then
1417 var variable = variables.first
1418 var vtype = variable.declared_type.as(not null)
1419
1420 if n_expr isa AOrangeExpr then
1421 self.method_lt = v.get_method(self, vtype, "<", false)
1422 else
1423 self.method_lt = v.get_method(self, vtype, "<=", false)
1424 end
1425
1426 self.method_successor = v.get_method(self, vtype, "successor", false)
1427 end
1428 end
1429 end
1430
1431 redef class AWithExpr
1432 var method_start: nullable CallSite
1433 var method_finish: nullable CallSite
1434
1435 redef fun accept_typing(v: TypeVisitor)
1436 do
1437 var mtype = v.visit_expr(n_expr)
1438 if mtype == null then return
1439
1440 method_start = v.get_method(self, mtype, "start", n_expr isa ASelfExpr)
1441 method_finish = v.get_method(self, mtype, "finish", n_expr isa ASelfExpr)
1442
1443 v.visit_stmt(n_block)
1444 self.mtype = n_block.mtype
1445 self.is_typed = true
1446 end
1447 end
1448
1449 redef class AAssertExpr
1450 redef fun accept_typing(v)
1451 do
1452 v.visit_expr_bool(n_expr)
1453
1454 v.visit_stmt(n_else)
1455 self.is_typed = true
1456 end
1457 end
1458
1459 redef class AOrExpr
1460 redef fun accept_typing(v)
1461 do
1462 v.visit_expr_bool(n_expr)
1463 v.visit_expr_bool(n_expr2)
1464 self.mtype = v.type_bool(self)
1465 end
1466 end
1467
1468 redef class AImpliesExpr
1469 redef fun accept_typing(v)
1470 do
1471 v.visit_expr_bool(n_expr)
1472 v.visit_expr_bool(n_expr2)
1473 self.mtype = v.type_bool(self)
1474 end
1475 end
1476
1477 redef class AAndExpr
1478 redef fun accept_typing(v)
1479 do
1480 v.visit_expr_bool(n_expr)
1481 v.visit_expr_bool(n_expr2)
1482 self.mtype = v.type_bool(self)
1483 end
1484 end
1485
1486
1487 redef class ANotExpr
1488 redef fun accept_typing(v)
1489 do
1490 v.visit_expr_bool(n_expr)
1491 self.mtype = v.type_bool(self)
1492 end
1493 end
1494
1495 redef class AOrElseExpr
1496 redef fun accept_typing(v)
1497 do
1498 var t1 = v.visit_expr(n_expr)
1499 var t2 = v.visit_expr(n_expr2)
1500
1501 if t1 == null or t2 == null then
1502 return # Skip error
1503 end
1504
1505 if t1 isa MNullType then
1506 self.mtype = t2
1507 return
1508 else if v.can_be_null(t1) then
1509 t1 = t1.as_notnull
1510 end
1511
1512 var t = v.merge_types(self, [t1, t2])
1513 if t == null then
1514 var c = v.get_mclass(self, "Object")
1515 if c == null then return # forward error
1516 t = c.mclass_type
1517 if v.can_be_null(t2) then
1518 t = t.as_nullable
1519 end
1520 #v.error(self, "Type Error: ambiguous type {t1} vs {t2}")
1521 end
1522 self.mtype = t
1523 end
1524
1525 redef fun accept_post_typing(v)
1526 do
1527 var t1 = n_expr.mtype
1528 if t1 == null then
1529 return
1530 else
1531 v.check_can_be_null(n_expr, t1)
1532 end
1533 end
1534 end
1535
1536 redef class ATrueExpr
1537 redef fun accept_typing(v)
1538 do
1539 self.mtype = v.type_bool(self)
1540 end
1541 end
1542
1543 redef class AFalseExpr
1544 redef fun accept_typing(v)
1545 do
1546 self.mtype = v.type_bool(self)
1547 end
1548 end
1549
1550 redef class AIntegerExpr
1551 redef fun accept_typing(v)
1552 do
1553 var mclass: nullable MClass = null
1554 if value isa Byte then
1555 mclass = v.get_mclass(self, "Byte")
1556 else if value isa Int then
1557 mclass = v.get_mclass(self, "Int")
1558 else if value isa Int8 then
1559 mclass = v.get_mclass(self, "Int8")
1560 else if value isa Int16 then
1561 mclass = v.get_mclass(self, "Int16")
1562 else if value isa UInt16 then
1563 mclass = v.get_mclass(self, "UInt16")
1564 else if value isa Int32 then
1565 mclass = v.get_mclass(self, "Int32")
1566 else if value isa UInt32 then
1567 mclass = v.get_mclass(self, "UInt32")
1568 end
1569 if mclass == null then return # Forward error
1570 self.mtype = mclass.mclass_type
1571 end
1572 end
1573
1574 redef class AFloatExpr
1575 redef fun accept_typing(v)
1576 do
1577 var mclass = v.get_mclass(self, "Float")
1578 if mclass == null then return # Forward error
1579 self.mtype = mclass.mclass_type
1580 end
1581 end
1582
1583 redef class ACharExpr
1584 redef fun accept_typing(v) do
1585 var mclass: nullable MClass = null
1586 if is_ascii then
1587 mclass = v.get_mclass(self, "Byte")
1588 else if is_code_point then
1589 mclass = v.get_mclass(self, "Int")
1590 else
1591 mclass = v.get_mclass(self, "Char")
1592 end
1593 if mclass == null then return # Forward error
1594 self.mtype = mclass.mclass_type
1595 end
1596 end
1597
1598 redef class AugmentedStringFormExpr
1599 super AExpr
1600
1601 # Text::to_re, used for prefix `re`
1602 var to_re: nullable CallSite = null
1603 # Regex::ignore_case, used for suffix `i` on `re`
1604 var ignore_case: nullable CallSite = null
1605 # Regex::newline, used for suffix `m` on `re`
1606 var newline: nullable CallSite = null
1607 # Regex::extended, used for suffix `b` on `re`
1608 var extended: nullable CallSite = null
1609 # CString::to_bytes_with_copy, used for prefix `b`
1610 var to_bytes_with_copy: nullable CallSite = null
1611
1612 redef fun accept_typing(v) do
1613 var mclass = v.get_mclass(self, "String")
1614 if mclass == null then return # Forward error
1615 if is_bytestring then
1616 to_bytes_with_copy = v.get_method(self, v.mmodule.c_string_type, "to_bytes_with_copy", false)
1617 mclass = v.get_mclass(self, "Bytes")
1618 else if is_re then
1619 to_re = v.get_method(self, mclass.mclass_type, "to_re", false)
1620 for i in suffix.chars do
1621 mclass = v.get_mclass(self, "Regex")
1622 if mclass == null then
1623 v.error(self, "Error: `Regex` class unknown")
1624 return
1625 end
1626 var service = ""
1627 if i == 'i' then
1628 service = "ignore_case="
1629 ignore_case = v.get_method(self, mclass.mclass_type, service, false)
1630 else if i == 'm' then
1631 service = "newline="
1632 newline = v.get_method(self, mclass.mclass_type, service, false)
1633 else if i == 'b' then
1634 service = "extended="
1635 extended = v.get_method(self, mclass.mclass_type, service, false)
1636 else
1637 v.error(self, "Type Error: Unrecognized suffix {i} in prefixed Regex")
1638 abort
1639 end
1640 end
1641 end
1642 if mclass == null then return # Forward error
1643 mtype = mclass.mclass_type
1644 end
1645 end
1646
1647 redef class ASuperstringExpr
1648 redef fun accept_typing(v)
1649 do
1650 super
1651 var objclass = v.get_mclass(self, "Object")
1652 if objclass == null then return # Forward error
1653 var objtype = objclass.mclass_type
1654 for nexpr in self.n_exprs do
1655 v.visit_expr_subtype(nexpr, objtype)
1656 end
1657 end
1658 end
1659
1660 redef class AArrayExpr
1661 # The `with_capacity` method on Array
1662 var with_capacity_callsite: nullable CallSite
1663
1664 # The `push` method on arrays
1665 var push_callsite: nullable CallSite
1666
1667 # The element of each type
1668 var element_mtype: nullable MType
1669
1670 # Set that `self` is a part of comprehension array `na`
1671 # If `self` is a `for`, or a `if`, then `set_comprehension` is recursively applied.
1672 private fun set_comprehension(n: nullable AExpr)
1673 do
1674 if n == null then
1675 return
1676 else if n isa AForExpr then
1677 set_comprehension(n.n_block)
1678 else if n isa AIfExpr then
1679 set_comprehension(n.n_then)
1680 set_comprehension(n.n_else)
1681 else
1682 # is a leave
1683 n.comprehension = self
1684 end
1685 end
1686 redef fun accept_typing(v)
1687 do
1688 var mtype: nullable MType = null
1689 var ntype = self.n_type
1690 if ntype != null then
1691 mtype = v.resolve_mtype(ntype)
1692 if mtype == null then return # Skip error
1693 end
1694 var mtypes = new Array[nullable MType]
1695 var useless = false
1696 for e in self.n_exprs do
1697 var t = v.visit_expr(e)
1698 if t == null then
1699 return # Skip error
1700 end
1701 set_comprehension(e)
1702 if mtype != null then
1703 if v.check_subtype(e, t, mtype, false) == null then return # Forward error
1704 if t == mtype then useless = true
1705 else
1706 mtypes.add(t)
1707 end
1708 end
1709 if mtype == null then
1710 # Ensure monotony for type adaptation on loops
1711 if self.element_mtype != null then mtypes.add self.element_mtype
1712 mtype = v.merge_types(self, mtypes)
1713 end
1714 if mtype == null or mtype isa MNullType then
1715 v.error(self, "Type Error: ambiguous array type {mtypes.join(" ")}")
1716 return
1717 end
1718 if useless then
1719 assert ntype != null
1720 v.modelbuilder.warning(ntype, "useless-type", "Warning: useless type declaration `{mtype}` in literal Array since it can be inferred from the elements type.")
1721 end
1722
1723 self.element_mtype = mtype
1724
1725 var mclass = v.get_mclass(self, "Array")
1726 if mclass == null then return # Forward error
1727 var array_mtype = mclass.get_mtype([mtype])
1728
1729 with_capacity_callsite = v.get_method(self, array_mtype, "with_capacity", false)
1730 push_callsite = v.get_method(self, array_mtype, "push", false)
1731
1732 self.mtype = array_mtype
1733 end
1734 end
1735
1736 redef class ARangeExpr
1737 var init_callsite: nullable CallSite
1738
1739 redef fun accept_typing(v)
1740 do
1741 var discrete_class = v.get_mclass(self, "Discrete")
1742 if discrete_class == null then return # Forward error
1743 var discrete_type = discrete_class.intro.bound_mtype
1744 var t1 = v.visit_expr_subtype(self.n_expr, discrete_type)
1745 var t2 = v.visit_expr_subtype(self.n_expr2, discrete_type)
1746 if t1 == null or t2 == null then return
1747 var mclass = v.get_mclass(self, "Range")
1748 if mclass == null then return # Forward error
1749 var mtype
1750 if v.is_subtype(t1, t2) then
1751 mtype = mclass.get_mtype([t2])
1752 else if v.is_subtype(t2, t1) then
1753 mtype = mclass.get_mtype([t1])
1754 else
1755 v.error(self, "Type Error: cannot create range: `{t1}` vs `{t2}`.")
1756 return
1757 end
1758
1759 self.mtype = mtype
1760
1761 # get the constructor
1762 var callsite
1763 if self isa ACrangeExpr then
1764 callsite = v.get_method(self, mtype, "init", false)
1765 else if self isa AOrangeExpr then
1766 callsite = v.get_method(self, mtype, "without_last", false)
1767 else
1768 abort
1769 end
1770 init_callsite = callsite
1771 end
1772 end
1773
1774 redef class ANullExpr
1775 redef fun accept_typing(v)
1776 do
1777 self.mtype = v.mmodule.model.null_type
1778 end
1779 end
1780
1781 redef class AIsaExpr
1782 # The static type to cast to.
1783 # (different from the static type of the expression that is `Bool`).
1784 var cast_type: nullable MType
1785 redef fun accept_typing(v)
1786 do
1787 v.visit_expr(n_expr)
1788
1789 var mtype = v.resolve_mtype(n_type)
1790
1791 self.cast_type = mtype
1792
1793 var variable = self.n_expr.its_variable
1794 if variable != null then
1795 var orig = self.n_expr.mtype
1796 #var from = if orig != null then orig.to_s else "invalid"
1797 #var to = if mtype != null then mtype.to_s else "invalid"
1798 #debug("adapt {variable}: {from} -> {to}")
1799
1800 var thentype = v.intersect_types(self, orig, mtype)
1801 if thentype != orig then
1802 self.after_flow_context.when_true.set_var(v, variable, thentype)
1803 #debug "{variable}:{orig or else "?"} isa {mtype or else "?"} -> then {thentype or else "?"}"
1804 end
1805
1806 var elsetype = v.diff_types(self, orig, mtype)
1807 if elsetype != orig then
1808 self.after_flow_context.when_false.set_var(v, variable, elsetype)
1809 #debug "{variable}:{orig or else "?"} isa {mtype or else "?"} -> else {elsetype or else "?"}"
1810 end
1811 end
1812
1813 self.mtype = v.type_bool(self)
1814 end
1815
1816 redef fun accept_post_typing(v)
1817 do
1818 v.check_expr_cast(self, self.n_expr, self.n_type)
1819 end
1820
1821 redef fun dump_info(v) do
1822 var res = super
1823 var mtype = self.cast_type
1824 if mtype != null then
1825 res += v.yellow(".as({mtype})")
1826 end
1827 return res
1828 end
1829
1830 end
1831
1832 redef class AAsCastExpr
1833 redef fun accept_typing(v)
1834 do
1835 v.visit_expr(n_expr)
1836
1837 self.mtype = v.resolve_mtype(n_type)
1838 end
1839
1840 redef fun accept_post_typing(v)
1841 do
1842 v.check_expr_cast(self, self.n_expr, self.n_type)
1843 end
1844 end
1845
1846 redef class AAsNotnullExpr
1847 redef fun accept_typing(v)
1848 do
1849 var mtype = v.visit_expr(self.n_expr)
1850 if mtype == null then return # Forward error
1851
1852 if mtype isa MNullType then
1853 v.error(self, "Type Error: `as(not null)` on `null`.")
1854 return
1855 end
1856
1857 if v.can_be_null(mtype) then
1858 mtype = mtype.as_notnull
1859 end
1860
1861 self.mtype = mtype
1862 end
1863
1864 redef fun accept_post_typing(v)
1865 do
1866 var mtype = n_expr.mtype
1867 if mtype == null then return
1868 v.check_can_be_null(n_expr, mtype)
1869 end
1870 end
1871
1872 redef class AParExpr
1873 redef fun accept_typing(v)
1874 do
1875 self.mtype = v.visit_expr(self.n_expr)
1876 end
1877 end
1878
1879 redef class AOnceExpr
1880 redef fun accept_typing(v)
1881 do
1882 self.mtype = v.visit_expr(self.n_expr)
1883 end
1884 end
1885
1886 redef class ASelfExpr
1887 redef var its_variable: nullable Variable
1888 redef fun accept_typing(v)
1889 do
1890 if v.is_toplevel_context and not self isa AImplicitSelfExpr then
1891 v.error(self, "Error: `self` cannot be used in top-level method.")
1892 end
1893 var variable = v.selfvariable
1894 self.its_variable = variable
1895 self.mtype = v.get_variable(self, variable)
1896 end
1897 end
1898
1899 redef class AImplicitSelfExpr
1900 # Is the implicit receiver `sys`?
1901 #
1902 # By default, the implicit receiver is `self`.
1903 # But when there is not method for `self`, `sys` is used as a fall-back.
1904 # Is this case this flag is set to `true`.
1905 var is_sys = false
1906 end
1907
1908 ## MESSAGE SENDING AND PROPERTY
1909
1910 redef class ASendExpr
1911 # The property invoked by the send.
1912 var callsite: nullable CallSite
1913
1914 redef fun bad_expr_message(child)
1915 do
1916 if child == self.n_expr then
1917 return "to be the receiver of `{self.property_name}`"
1918 end
1919 return null
1920 end
1921
1922 redef fun accept_typing(v)
1923 do
1924 var nrecv = self.n_expr
1925 var recvtype = v.visit_expr(nrecv)
1926 var name = self.property_name
1927 var node = self.property_node
1928
1929 if recvtype == null then return # Forward error
1930
1931 var callsite = null
1932 var unsafe_type = v.anchor_to(recvtype)
1933 var mproperty = v.try_get_mproperty_by_name2(node, unsafe_type, name)
1934 if mproperty == null and nrecv isa AImplicitSelfExpr then
1935 # Special fall-back search in `sys` when noting found in the implicit receiver.
1936 var sysclass = v.try_get_mclass(node, "Sys")
1937 if sysclass != null then
1938 var systype = sysclass.mclass_type
1939 mproperty = v.try_get_mproperty_by_name2(node, systype, name)
1940 if mproperty != null then
1941 callsite = v.get_method(node, systype, name, false)
1942 if callsite == null then return # Forward error
1943 # Update information, we are looking at `sys` now, not `self`
1944 nrecv.is_sys = true
1945 nrecv.its_variable = null
1946 nrecv.mtype = systype
1947 recvtype = systype
1948 end
1949 end
1950 end
1951 if callsite == null then
1952 # If still nothing, just exit
1953 callsite = v.get_method(node, recvtype, name, nrecv isa ASelfExpr)
1954 if callsite == null then return
1955 end
1956
1957 self.callsite = callsite
1958 var msignature = callsite.msignature
1959
1960 var args = compute_raw_arguments
1961
1962 callsite.check_signature(v, node, args)
1963
1964 if callsite.mproperty.is_init then
1965 var vmpropdef = v.mpropdef
1966 if not (vmpropdef isa MMethodDef and vmpropdef.mproperty.is_init) then
1967 v.error(node, "Error: an `init` can only be called from another `init`.")
1968 end
1969 if vmpropdef isa MMethodDef and vmpropdef.mproperty.is_root_init and not callsite.mproperty.is_root_init then
1970 v.error(node, "Error: `{vmpropdef}` cannot call a factory `{callsite.mproperty}`.")
1971 end
1972 end
1973
1974 var ret = msignature.return_mtype
1975 if ret != null then
1976 self.mtype = ret
1977 else
1978 self.is_typed = true
1979 end
1980 end
1981
1982 # The name of the property
1983 # Each subclass simply provide the correct name.
1984 private fun property_name: String is abstract
1985
1986 # The node identifying the name (id, operator, etc) for messages.
1987 #
1988 # Is `self` by default
1989 private fun property_node: ANode do return self
1990
1991 # An array of all arguments (excluding self)
1992 fun raw_arguments: Array[AExpr] do return compute_raw_arguments
1993
1994 private fun compute_raw_arguments: Array[AExpr] is abstract
1995
1996 redef fun dump_info(v) do
1997 var res = super
1998 var callsite = self.callsite
1999 if callsite != null then
2000 res += v.yellow(" call="+callsite.dump_info(v))
2001 end
2002 return res
2003 end
2004 end
2005
2006 redef class ABinopExpr
2007 redef fun compute_raw_arguments do return [n_expr2]
2008 redef fun property_name do return operator
2009 redef fun property_node do return n_op
2010 end
2011
2012 redef class AEqFormExpr
2013 redef fun accept_typing(v)
2014 do
2015 super
2016 v.null_test(self)
2017 end
2018
2019 redef fun accept_post_typing(v)
2020 do
2021 var mtype = n_expr.mtype
2022 var mtype2 = n_expr2.mtype
2023
2024 if mtype == null or mtype2 == null then return
2025
2026 if not mtype2 isa MNullType then return
2027
2028 v.check_can_be_null(n_expr, mtype)
2029 end
2030 end
2031
2032 redef class AUnaryopExpr
2033 redef fun property_name do return "unary {operator}"
2034 redef fun compute_raw_arguments do return new Array[AExpr]
2035 end
2036
2037
2038 redef class ACallExpr
2039 redef fun property_name do return n_qid.n_id.text
2040 redef fun property_node do return n_qid
2041 redef fun compute_raw_arguments do return n_args.to_a
2042 end
2043
2044 redef class ACallAssignExpr
2045 redef fun property_name do return n_qid.n_id.text + "="
2046 redef fun property_node do return n_qid
2047 redef fun compute_raw_arguments
2048 do
2049 var res = n_args.to_a
2050 res.add(n_value)
2051 return res
2052 end
2053 end
2054
2055 redef class ABraExpr
2056 redef fun property_name do return "[]"
2057 redef fun compute_raw_arguments do return n_args.to_a
2058 end
2059
2060 redef class ABraAssignExpr
2061 redef fun property_name do return "[]="
2062 redef fun compute_raw_arguments
2063 do
2064 var res = n_args.to_a
2065 res.add(n_value)
2066 return res
2067 end
2068 end
2069
2070 redef class ASendReassignFormExpr
2071 # The property invoked for the writing
2072 var write_callsite: nullable CallSite
2073
2074 redef fun accept_typing(v)
2075 do
2076 var recvtype = v.visit_expr(self.n_expr)
2077 var name = self.property_name
2078 var node = self.property_node
2079
2080 if recvtype == null then return # Forward error
2081
2082 var for_self = self.n_expr isa ASelfExpr
2083 var callsite = v.get_method(node, recvtype, name, for_self)
2084
2085 if callsite == null then return
2086 self.callsite = callsite
2087
2088 var args = compute_raw_arguments
2089
2090 callsite.check_signature(v, node, args)
2091
2092 var readtype = callsite.msignature.return_mtype
2093 if readtype == null then
2094 v.error(node, "Error: `{name}` is not a function.")
2095 return
2096 end
2097
2098 var wcallsite = v.get_method(node, recvtype, name + "=", self.n_expr isa ASelfExpr)
2099 if wcallsite == null then return
2100 self.write_callsite = wcallsite
2101
2102 var wtype = self.resolve_reassignment(v, readtype, wcallsite.msignature.mparameters.last.mtype)
2103 if wtype == null then return
2104
2105 args = args.to_a # duplicate so raw_arguments keeps only the getter args
2106 args.add(self.n_value)
2107 wcallsite.check_signature(v, node, args)
2108
2109 self.is_typed = true
2110 end
2111 end
2112
2113 redef class ACallReassignExpr
2114 redef fun property_name do return n_qid.n_id.text
2115 redef fun property_node do return n_qid.n_id
2116 redef fun compute_raw_arguments do return n_args.to_a
2117 end
2118
2119 redef class ABraReassignExpr
2120 redef fun property_name do return "[]"
2121 redef fun compute_raw_arguments do return n_args.to_a
2122 end
2123
2124 redef class AInitExpr
2125 redef fun property_name do return "init"
2126 redef fun property_node do return n_kwinit
2127 redef fun compute_raw_arguments do return n_args.to_a
2128 end
2129
2130 redef class AExprs
2131 fun to_a: Array[AExpr] do return self.n_exprs.to_a
2132 end
2133
2134 ###
2135
2136 redef class ASuperExpr
2137 # The method to call if the super is in fact a 'super init call'
2138 # Note: if the super is a normal call-next-method, then this attribute is null
2139 var callsite: nullable CallSite
2140
2141 # The method to call is the super is a standard `call-next-method` super-call
2142 # Note: if the super is a special super-init-call, then this attribute is null
2143 var mpropdef: nullable MMethodDef
2144
2145 redef fun accept_typing(v)
2146 do
2147 var anchor = v.anchor
2148 assert anchor != null
2149 var recvtype = v.get_variable(self, v.selfvariable)
2150 assert recvtype != null
2151 var mproperty = v.mpropdef.mproperty
2152 if not mproperty isa MMethod then
2153 v.error(self, "Error: `super` only usable in a `method`.")
2154 return
2155 end
2156 var superprops = mproperty.lookup_super_definitions(v.mmodule, anchor)
2157 if superprops.length == 0 then
2158 if mproperty.is_init and v.mpropdef.is_intro then
2159 process_superinit(v)
2160 return
2161 end
2162 v.error(self, "Error: no super method to call for `{mproperty}`.")
2163 return
2164 end
2165 # FIXME: covariance of return type in linear extension?
2166 var superprop = superprops.first
2167
2168 var msignature = superprop.msignature.as(not null)
2169 msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
2170 var args = self.n_args.to_a
2171 if args.length > 0 then
2172 signaturemap = v.check_signature(self, args, mproperty, msignature)
2173 end
2174 self.mtype = msignature.return_mtype
2175 self.is_typed = true
2176 v.mpropdef.has_supercall = true
2177 mpropdef = v.mpropdef.as(MMethodDef)
2178 end
2179
2180 # The mapping used on the call to associate arguments to parameters.
2181 # If null then no specific association is required.
2182 var signaturemap: nullable SignatureMap
2183
2184 private fun process_superinit(v: TypeVisitor)
2185 do
2186 var anchor = v.anchor
2187 assert anchor != null
2188 var recvtype = v.get_variable(self, v.selfvariable)
2189 assert recvtype != null
2190 var mpropdef = v.mpropdef
2191 assert mpropdef isa MMethodDef
2192 var mproperty = mpropdef.mproperty
2193 var superprop: nullable MMethodDef = null
2194 for msupertype in mpropdef.mclassdef.supertypes do
2195 msupertype = msupertype.anchor_to(v.mmodule, anchor)
2196 var errcount = v.modelbuilder.toolcontext.error_count
2197 var candidate = v.try_get_mproperty_by_name2(self, msupertype, mproperty.name).as(nullable MMethod)
2198 if candidate == null then
2199 if v.modelbuilder.toolcontext.error_count > errcount then return # Forward error
2200 continue # Try next super-class
2201 end
2202 if superprop != null and candidate.is_root_init then
2203 continue
2204 end
2205 if superprop != null and superprop.mproperty != candidate and not superprop.mproperty.is_root_init then
2206 v.error(self, "Error: conflicting super constructor to call for `{mproperty}`: `{candidate.full_name}`, `{superprop.mproperty.full_name}`")
2207 return
2208 end
2209 var candidatedefs = candidate.lookup_definitions(v.mmodule, anchor)
2210 if superprop != null and superprop.mproperty == candidate then
2211 if superprop == candidatedefs.first then continue
2212 candidatedefs.add(superprop)
2213 end
2214 if candidatedefs.length > 1 then
2215 v.error(self, "Error: conflicting property definitions for property `{mproperty}` in `{recvtype}`: {candidatedefs.join(", ")}")
2216 return
2217 end
2218 superprop = candidatedefs.first
2219 end
2220 if superprop == null then
2221 v.error(self, "Error: no super method to call for `{mproperty}`.")
2222 return
2223 end
2224
2225 var msignature = superprop.new_msignature or else superprop.msignature.as(not null)
2226 msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
2227
2228 var callsite = new CallSite(hot_location, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)
2229 self.callsite = callsite
2230
2231 var args = self.n_args.to_a
2232 if args.length > 0 then
2233 callsite.check_signature(v, self, args)
2234 else
2235 # Check there is at least enough parameters
2236 if mpropdef.msignature.arity < msignature.arity then
2237 v.error(self, "Error: not enough implicit arguments to pass. Got `{mpropdef.msignature.arity}`, expected at least `{msignature.arity}`. Signature is `{msignature}`.")
2238 return
2239 end
2240 # Check that each needed parameter is conform
2241 var i = 0
2242 for sp in msignature.mparameters do
2243 var p = mpropdef.msignature.mparameters[i]
2244 if not v.is_subtype(p.mtype, sp.mtype) then
2245 v.error(self, "Type Error: expected argument #{i} of type `{sp.mtype}`, got implicit argument `{p.name}` of type `{p.mtype}`. Signature is {msignature}")
2246 return
2247 end
2248 i += 1
2249 end
2250 end
2251
2252 self.is_typed = true
2253 end
2254
2255 redef fun dump_info(v) do
2256 var res = super
2257 var callsite = self.callsite
2258 if callsite != null then
2259 res += v.yellow(" super-init="+callsite.dump_info(v))
2260 end
2261 var mpropdef = self.mpropdef
2262 if mpropdef != null then
2263 res += v.yellow(" call-next-method="+mpropdef.to_s)
2264 end
2265 return res
2266 end
2267 end
2268
2269 ####
2270
2271 redef class ANewExpr
2272 # The constructor invoked by the new.
2273 var callsite: nullable CallSite
2274
2275 # The designated type
2276 var recvtype: nullable MClassType
2277
2278 redef fun accept_typing(v)
2279 do
2280 var recvtype = v.resolve_mtype(self.n_type)
2281 if recvtype == null then return
2282
2283 if not recvtype isa MClassType then
2284 if recvtype isa MNullableType then
2285 v.error(self, "Type Error: cannot instantiate the nullable type `{recvtype}`.")
2286 return
2287 else if recvtype isa MFormalType then
2288 v.error(self, "Type Error: cannot instantiate the formal type `{recvtype}`.")
2289 return
2290 else
2291 v.error(self, "Type Error: cannot instantiate the type `{recvtype}`.")
2292 return
2293 end
2294 end
2295
2296 self.recvtype = recvtype
2297 var kind = recvtype.mclass.kind
2298
2299 var name: String
2300 var nqid = self.n_qid
2301 var node: ANode
2302 if nqid != null then
2303 name = nqid.n_id.text
2304 node = nqid
2305 else
2306 name = "new"
2307 node = self.n_kwnew
2308 end
2309 if name == "intern" then
2310 if kind != concrete_kind then
2311 v.error(self, "Type Error: cannot instantiate {kind} {recvtype}.")
2312 return
2313 end
2314 if n_args.n_exprs.not_empty then
2315 v.error(n_args, "Type Error: the intern constructor expects no arguments.")
2316 return
2317 end
2318 # Our job is done
2319 self.mtype = recvtype
2320 return
2321 end
2322
2323 var callsite = v.get_method(node, recvtype, name, false)
2324 if callsite == null then return
2325
2326 if not callsite.mproperty.is_new then
2327 if kind != concrete_kind then
2328 v.error(self, "Type Error: cannot instantiate {kind} `{recvtype}`.")
2329 return
2330 end
2331 self.mtype = recvtype
2332 else
2333 self.mtype = callsite.msignature.return_mtype
2334 assert self.mtype != null
2335 end
2336
2337 self.callsite = callsite
2338
2339 if not callsite.mproperty.is_init_for(recvtype.mclass) then
2340 v.error(self, "Error: `{name}` is not a constructor.")
2341 return
2342 end
2343
2344 var args = n_args.to_a
2345 callsite.check_signature(v, node, args)
2346 end
2347
2348 redef fun dump_info(v) do
2349 var res = super
2350 var callsite = self.callsite
2351 if callsite != null then
2352 res += v.yellow(" call="+callsite.dump_info(v))
2353 end
2354 return res
2355 end
2356 end
2357
2358 ####
2359
2360 redef class AAttrFormExpr
2361 # The attribute accessed.
2362 var mproperty: nullable MAttribute
2363
2364 # The static type of the attribute.
2365 var attr_type: nullable MType
2366
2367 # Resolve the attribute accessed.
2368 private fun resolve_property(v: TypeVisitor)
2369 do
2370 var recvtype = v.visit_expr(self.n_expr)
2371 if recvtype == null then return # Skip error
2372 var node = self.n_id
2373 var name = node.text
2374 if recvtype isa MNullType then
2375 v.error(node, "Error: attribute `{name}` access on `null`.")
2376 return
2377 end
2378
2379 var unsafe_type = v.anchor_to(recvtype)
2380 var mproperty = v.try_get_mproperty_by_name2(node, unsafe_type, name)
2381 if mproperty == null then
2382 v.modelbuilder.error(node, "Error: attribute `{name}` does not exist in `{recvtype}`.")
2383 return
2384 end
2385 assert mproperty isa MAttribute
2386 self.mproperty = mproperty
2387
2388 var mpropdefs = mproperty.lookup_definitions(v.mmodule, unsafe_type)
2389 assert mpropdefs.length == 1
2390 var mpropdef = mpropdefs.first
2391 var attr_type = mpropdef.static_mtype
2392 if attr_type == null then return # skip error
2393 attr_type = v.resolve_for(attr_type, recvtype, self.n_expr isa ASelfExpr)
2394 self.attr_type = attr_type
2395 end
2396
2397 redef fun dump_info(v) do
2398 var res = super
2399 var mproperty = self.mproperty
2400 var attr_type = self.attr_type
2401 if mproperty != null then
2402 res += v.yellow(" attr={mproperty}:{attr_type or else "BROKEN"}")
2403 end
2404 return res
2405 end
2406 end
2407
2408 redef class AAttrExpr
2409 redef fun accept_typing(v)
2410 do
2411 self.resolve_property(v)
2412 self.mtype = self.attr_type
2413 end
2414 end
2415
2416
2417 redef class AAttrAssignExpr
2418 redef fun accept_typing(v)
2419 do
2420 self.resolve_property(v)
2421 var mtype = self.attr_type
2422
2423 v.visit_expr_subtype(self.n_value, mtype)
2424 self.is_typed = mtype != null
2425 end
2426 end
2427
2428 redef class AAttrReassignExpr
2429 redef fun accept_typing(v)
2430 do
2431 self.resolve_property(v)
2432 var mtype = self.attr_type
2433 if mtype == null then return # Skip error
2434
2435 var rettype = self.resolve_reassignment(v, mtype, mtype)
2436
2437 self.is_typed = rettype != null
2438 end
2439 end
2440
2441 redef class AIssetAttrExpr
2442 redef fun accept_typing(v)
2443 do
2444 self.resolve_property(v)
2445 var mtype = self.attr_type
2446 if mtype == null then return # Skip error
2447
2448 var recvtype = self.n_expr.mtype.as(not null)
2449 var bound = v.resolve_for(mtype, recvtype, false)
2450 if bound isa MNullableType then
2451 v.error(n_id, "Type Error: `isset` on a nullable attribute.")
2452 end
2453 self.mtype = v.type_bool(self)
2454 end
2455 end
2456
2457 redef class AVarargExpr
2458 redef fun accept_typing(v)
2459 do
2460 # This kind of pseudo-expression can be only processed trough a signature
2461 # See `check_signature`
2462 # Other cases are a syntax error.
2463 v.error(self, "Syntax Error: unexpected `...`.")
2464 end
2465 end
2466
2467 ###
2468
2469 redef class ADebugTypeExpr
2470 redef fun accept_typing(v)
2471 do
2472 var expr = v.visit_expr(self.n_expr)
2473 if expr == null then return
2474 var unsafe = v.anchor_to(expr)
2475 var ntype = self.n_type
2476 var mtype = v.resolve_mtype(ntype)
2477 if mtype != null and mtype != expr then
2478 var umtype = v.anchor_to(mtype)
2479 v.modelbuilder.warning(self, "debug", "Found type {expr} (-> {unsafe}), expected {mtype} (-> {umtype})")
2480 end
2481 self.is_typed = true
2482 end
2483 end