Merge remote-tracking branch 'origin/master' into init_auto
[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` an return null.
106 # If `sub` is a safe subtype of `sup` then return `sub`.
107 # If `sub` is an unsafe subtype (ie 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 MBottomType 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 = "autoinit"
322 mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
323 if mproperty == null then
324 name = "init"
325 mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
326 end
327 end
328
329 if mproperty == null then
330 if recv_is_self then
331 self.modelbuilder.error(node, "Error: method or variable `{name}` unknown in `{recvtype}`.")
332 else if recvtype.need_anchor then
333 self.modelbuilder.error(node, "Error: method `{name}` does not exists in `{recvtype}: {unsafe_type}`.")
334 else
335 self.modelbuilder.error(node, "Error: method `{name}` does not exists in `{recvtype}`.")
336 end
337 return null
338 end
339
340 assert mproperty isa MMethod
341
342 # `null` only accepts some methods of object.
343 if recvtype isa MNullType and not mproperty.is_null_safe then
344 self.error(node, "Error: method `{name}` called on `null`.")
345 return null
346 else if unsafe_type isa MNullableType and not mproperty.is_null_safe then
347 modelbuilder.advice(node, "call-on-nullable", "Warning: method call on a nullable receiver `{recvtype}`.")
348 end
349
350 if is_toplevel_context and recv_is_self and not mproperty.is_toplevel then
351 error(node, "Error: `{name}` is not a top-level method, thus need a receiver.")
352 end
353 if not recv_is_self and mproperty.is_toplevel then
354 error(node, "Error: cannot call `{name}`, a top-level method, with a receiver.")
355 end
356
357 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
358 self.modelbuilder.error(node, "Error: method `{name}` is protected and can only accessed by `self`.")
359 return null
360 end
361
362 var info = mproperty.deprecation
363 if info != null and self.mpropdef.mproperty.deprecation == null then
364 var mdoc = info.mdoc
365 if mdoc != null then
366 self.modelbuilder.warning(node, "deprecated-method", "Deprecation Warning: method `{name}` is deprecated: {mdoc.content.first}")
367 else
368 self.modelbuilder.warning(node, "deprecated-method", "Deprecation Warning: method `{name}` is deprecated.")
369 end
370 end
371
372 var propdefs = mproperty.lookup_definitions(self.mmodule, unsafe_type)
373 var mpropdef
374 if propdefs.length == 0 then
375 self.modelbuilder.error(node, "Type Error: no definition found for property `{name}` in `{unsafe_type}`.")
376 return null
377 else if propdefs.length == 1 then
378 mpropdef = propdefs.first
379 else
380 self.modelbuilder.warning(node, "property-conflict", "Warning: conflicting property definitions for property `{name}` in `{unsafe_type}`: {propdefs.join(" ")}")
381 mpropdef = mproperty.intro
382 end
383
384
385 var msignature = mpropdef.msignature
386 if msignature == null then return null # skip error
387 msignature = resolve_for(msignature, recvtype, recv_is_self).as(MSignature)
388
389 var erasure_cast = false
390 var rettype = mpropdef.msignature.return_mtype
391 if not recv_is_self and rettype != null then
392 rettype = rettype.undecorate
393 if rettype isa MParameterType then
394 var erased_rettype = msignature.return_mtype
395 assert erased_rettype != null
396 #node.debug("Erasure cast: Really a {rettype} but unsafely a {erased_rettype}")
397 erasure_cast = true
398 end
399 end
400
401 var callsite = new CallSite(node.hot_location, recvtype, mmodule, anchor, recv_is_self, mproperty, mpropdef, msignature, erasure_cast)
402 return callsite
403 end
404
405 fun try_get_method(node: ANode, recvtype: MType, name: String, recv_is_self: Bool): nullable CallSite
406 do
407 var unsafe_type = self.anchor_to(recvtype)
408 var mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
409 if mproperty == null then return null
410 return get_method(node, recvtype, name, recv_is_self)
411 end
412
413
414 # Visit the expressions of args and check their conformity with the corresponding type in signature
415 # The point of this method is to handle varargs correctly
416 # Note: The signature must be correctly adapted
417 fun check_signature(node: ANode, args: Array[AExpr], mproperty: MProperty, msignature: MSignature): nullable SignatureMap
418 do
419 var vararg_rank = msignature.vararg_rank
420 if vararg_rank >= 0 then
421 if args.length < msignature.arity then
422 modelbuilder.error(node, "Error: expected at least {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
423 return null
424 end
425 else if args.length != msignature.arity then
426 # Too much argument
427 if args.length > msignature.arity then
428 modelbuilder.error(node, "Error: expected {msignature.arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
429 return null
430 end
431 # Other cases are managed later
432 end
433
434
435 #debug("CALL {unsafe_type}.{msignature}")
436
437 # Associate each parameter to a position in the arguments
438 var map = new SignatureMap
439
440 # Special case for the isolated last argument
441 # TODO: reify this method characteristics (where? the param, the signature, the method?)
442 var last_is_padded = mproperty.name.chars.last == '='
443 var nbargs = args.length
444 if last_is_padded then
445 nbargs -= 1
446 assert not args.last isa ANamedargExpr
447 map.map[msignature.arity - 1] = args.length - 1
448 self.visit_expr_subtype(args.last, msignature.mparameters.last.mtype)
449 end
450
451 # First, handle named arguments
452 for i in [0..args.length[ do
453 var e = args[i]
454 if not e isa ANamedargExpr then continue
455 var name = e.n_id.text
456 var param = msignature.mparameter_by_name(name)
457 if param == null then
458 modelbuilder.error(e.n_id, "Error: no parameter `{name}` for `{mproperty}{msignature}`.")
459 return null
460 end
461 var idx = msignature.mparameters.index_of(param)
462 var prev = map.map.get_or_null(idx)
463 if prev != null then
464 modelbuilder.error(e, "Error: parameter `{name}` already associated with argument #{prev} for `{mproperty}{msignature}`.")
465 return null
466 end
467 map.map[idx] = i
468 e.mtype = self.visit_expr_subtype(e.n_expr, param.mtype)
469 end
470
471 # Number of minimum mandatory remaining parameters
472 var min_arity = 0
473
474 # Second, associate remaining parameters
475 var vararg_decl = args.length - msignature.arity
476 var j = 0
477 for i in [0..msignature.arity[ do
478 # Skip parameters associated by name
479 if map.map.has_key(i) then continue
480
481 var param = msignature.mparameters[i]
482
483 # Search the next free argument: skip named arguments since they are already associated
484 while j < nbargs and args[j] isa ANamedargExpr do j += 1
485 if j >= nbargs then
486 if not param.mtype isa MNullableType then
487 min_arity = j + 1
488 end
489 j += 1
490 continue
491 end
492 var arg = args[j]
493 map.map[i] = j
494 j += 1
495
496 if i == vararg_rank then
497 j += vararg_decl
498 continue # skip the vararg
499 end
500
501 if not param.is_vararg then
502 var paramtype = param.mtype
503 self.visit_expr_subtype(arg, paramtype)
504 else
505 check_one_vararg(arg, param)
506 end
507 end
508
509 if min_arity > 0 then
510 if last_is_padded then min_arity += 1
511 if min_arity < msignature.arity then
512 modelbuilder.error(node, "Error: expected at least {min_arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
513 else
514 modelbuilder.error(node, "Error: expected {min_arity} argument(s) for `{mproperty}{msignature}`; got {args.length}. See introduction at `{mproperty.full_name}`.")
515 end
516 return null
517 end
518
519 # Third, check varargs
520 if vararg_rank >= 0 then
521 var paramtype = msignature.mparameters[vararg_rank].mtype
522 var first = args[vararg_rank]
523 if vararg_decl == 0 then
524 if not check_one_vararg(first, msignature.mparameters[vararg_rank]) then return null
525 else
526 first.vararg_decl = vararg_decl + 1
527 for i in [vararg_rank..vararg_rank+vararg_decl] do
528 self.visit_expr_subtype(args[i], paramtype)
529 end
530 end
531 end
532
533 return map
534 end
535
536 # Check an expression as a single vararg.
537 # The main point of the method if to handle the case of reversed vararg (see `AVarargExpr`)
538 fun check_one_vararg(arg: AExpr, param: MParameter): Bool
539 do
540 var paramtype = param.mtype
541 var mclass = get_mclass(arg, "Array")
542 if mclass == null then return false # Forward error
543 var array_mtype = mclass.get_mtype([paramtype])
544 if arg isa AVarargExpr then
545 self.visit_expr_subtype(arg.n_expr, array_mtype)
546 arg.mtype = arg.n_expr.mtype
547 else
548 # only one vararg, maybe `...` was forgot, so be gentle!
549 var t = visit_expr(arg)
550 if t == null then return false # Forward error
551 if not is_subtype(t, paramtype) and is_subtype(t, array_mtype) then
552 # Not acceptable but could be a `...`
553 error(arg, "Type Error: expected `{paramtype}`, got `{t}`. Is an ellipsis `...` missing on the argument?")
554 return false
555 end
556 # Standard valid vararg, finish the job
557 arg.vararg_decl = 1
558 self.visit_expr_subtype(arg, paramtype)
559 end
560 return true
561 end
562
563 fun error(node: ANode, message: String)
564 do
565 self.modelbuilder.error(node, message)
566 end
567
568 fun get_variable(node: AExpr, variable: Variable): nullable MType
569 do
570 if not variable.is_adapted then return variable.declared_type
571
572 var flow = node.after_flow_context
573 if flow == null then return null # skip error
574
575 if flow.vars.has_key(variable) then
576 return flow.vars[variable]
577 else
578 #node.debug("*** START Collected for {variable}")
579 var mtypes = flow.collect_types(variable)
580 #node.debug("**** END Collected for {variable}")
581 if mtypes.length == 0 then
582 return variable.declared_type
583 else if mtypes.length == 1 then
584 return mtypes.first
585 else
586 var res = merge_types(node,mtypes)
587 if res == null then res = variable.declared_type
588 return res
589 end
590 end
591 end
592
593 # Some variables where type-adapted during the visit
594 var dirty = false
595
596 # Some loops had been visited during the visit
597 var has_loop = false
598
599 fun set_variable(node: AExpr, variable: Variable, mtype: nullable MType)
600 do
601 var flow = node.after_flow_context
602 assert flow != null
603
604 flow.set_var(self, variable, mtype)
605 end
606
607 fun merge_types(node: ANode, col: Array[nullable MType]): nullable MType
608 do
609 if col.length == 1 then return col.first
610 for t1 in col do
611 if t1 == null then continue # return null
612 var found = true
613 for t2 in col do
614 if t2 == null then continue # return null
615 if can_be_null(t2) and not can_be_null(t1) then
616 t1 = t1.as_nullable
617 end
618 if not is_subtype(t2, t1) then found = false
619 end
620 if found then
621 #print "merge {col.join(" ")} -> {t1}"
622 return t1
623 end
624 end
625 #self.modelbuilder.warning(node, "Type Error: {col.length} conflicting types: <{col.join(", ")}>")
626 return null
627 end
628 end
629
630 # Mapping between parameters and arguments in a call.
631 #
632 # Parameters and arguments are not stored in the class but referenced by their position (starting from 0)
633 #
634 # The point of this class is to help engine and other things to map arguments in the AST to parameters of the model.
635 class SignatureMap
636 # Associate a parameter to an argument
637 var map = new ArrayMap[Int, Int]
638 end
639
640 # A specific method call site with its associated informations.
641 class CallSite
642 super MEntity
643
644 # The associated location of the callsite
645 var location: Location
646
647 # The static type of the receiver (possibly unresolved)
648 var recv: MType
649
650 # The module where the callsite is present
651 var mmodule: MModule
652
653 # The anchor to use with `recv` or `msignature`
654 var anchor: nullable MClassType
655
656 # Is the receiver self?
657 # If "for_self", virtual types of the signature are kept
658 # If "not_for_self", virtual type are erased
659 var recv_is_self: Bool
660
661 # The designated method
662 var mproperty: MMethod
663
664 # The statically designated method definition
665 # The most specif one, it is.
666 var mpropdef: MMethodDef
667
668 # The resolved signature for the receiver
669 var msignature: MSignature
670
671 # Is a implicit cast required on erasure typing policy?
672 var erasure_cast: Bool
673
674 # The mapping used on the call to associate arguments to parameters
675 # If null then no specific association is required.
676 var signaturemap: nullable SignatureMap = null
677
678 private fun check_signature(v: TypeVisitor, node: ANode, args: Array[AExpr]): Bool
679 do
680 var map = v.check_signature(node, args, self.mproperty, self.msignature)
681 signaturemap = map
682 if map == null then is_broken = true
683 return map == null
684 end
685 end
686
687 redef class Variable
688 # The declared type of the variable
689 var declared_type: nullable MType is writable
690
691 # Was the variable type-adapted?
692 # This is used to speedup type retrieval while it remains `false`
693 private var is_adapted = false
694 end
695
696 redef class FlowContext
697 # Store changes of types because of type evolution
698 private var vars = new HashMap[Variable, nullable MType]
699
700 # Adapt the variable to a static type
701 # Warning1: do not modify vars directly.
702 # Warning2: sub-flow may have cached a unadapted variable
703 private fun set_var(v: TypeVisitor, variable: Variable, mtype: nullable MType)
704 do
705 if variable.declared_type == mtype and not variable.is_adapted then return
706 if vars.has_key(variable) and vars[variable] == mtype then return
707 self.vars[variable] = mtype
708 v.dirty = true
709 variable.is_adapted = true
710 #node.debug "set {variable} to {mtype or else "X"}"
711 end
712
713 # Look in the flow and previous flow and collect all first reachable type adaptation of a local variable
714 private fun collect_types(variable: Variable): Array[nullable MType]
715 do
716 #node.debug "flow for {variable}"
717 var res = new Array[nullable MType]
718
719 var todo = [self]
720 var seen = new HashSet[FlowContext]
721 while not todo.is_empty do
722 var f = todo.pop
723 if f.is_unreachable then continue
724 if seen.has(f) then continue
725 seen.add f
726
727 if f.vars.has_key(variable) then
728 # Found something. Collect it and do not process further on this path
729 res.add f.vars[variable]
730 #f.node.debug "process {variable}: got {f.vars[variable] or else "X"}"
731 else
732 todo.add_all f.previous
733 todo.add_all f.loops
734 if f.previous.is_empty then
735 # Root flowcontext mean a parameter or something related
736 res.add variable.declared_type
737 #f.node.debug "root process {variable}: got {variable.declared_type or else "X"}"
738 end
739 end
740 end
741 #self.node.debug "##### end flow for {variable}: {res.join(" ")}"
742 return res
743 end
744 end
745
746 redef class APropdef
747 # The entry point of the whole typing analysis
748 fun do_typing(modelbuilder: ModelBuilder)
749 do
750 end
751
752 # The variable associated to the receiver (if any)
753 var selfvariable: nullable Variable
754 end
755
756 redef class AMethPropdef
757 redef fun do_typing(modelbuilder: ModelBuilder)
758 do
759 var mpropdef = self.mpropdef
760 if mpropdef == null then return # skip error
761
762 var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
763 self.selfvariable = v.selfvariable
764
765 var mmethoddef = self.mpropdef.as(not null)
766 var msignature = mmethoddef.msignature
767 if msignature == null then return # skip error
768 for i in [0..msignature.arity[ do
769 var mtype = msignature.mparameters[i].mtype
770 if msignature.vararg_rank == i then
771 var arrayclass = v.get_mclass(self.n_signature.n_params[i], "Array")
772 if arrayclass == null then return # Skip error
773 mtype = arrayclass.get_mtype([mtype])
774 end
775 var variable = self.n_signature.n_params[i].variable
776 assert variable != null
777 variable.declared_type = mtype
778 end
779
780 var nblock = self.n_block
781 if nblock == null then return
782
783 loop
784 v.dirty = false
785 v.visit_stmt(nblock)
786 if not v.has_loop or not v.dirty then break
787 end
788
789 var post_visitor = new PostTypingVisitor(v)
790 post_visitor.enter_visit(self)
791
792 if not nblock.after_flow_context.is_unreachable and msignature.return_mtype != null then
793 # We reach the end of the function without having a return, it is bad
794 v.error(self, "Error: reached end of function; expected `return` with a value.")
795 end
796 end
797 end
798
799 private class PostTypingVisitor
800 super Visitor
801 var type_visitor: TypeVisitor
802 redef fun visit(n) do
803 n.visit_all(self)
804 n.accept_post_typing(type_visitor)
805 if n isa AExpr and n.mtype == null and not n.is_typed then
806 n.is_broken = true
807 end
808 end
809 end
810
811 redef class ANode
812 private fun accept_post_typing(v: TypeVisitor) do end
813
814 # An additional information message to explain the role of a child expression.
815 #
816 # The point of the method is to allow some kind of double dispatch so the parent
817 # choose how to describe its children.
818 private fun bad_expr_message(child: AExpr): nullable String do return null
819 end
820
821 redef class AAttrPropdef
822 redef fun do_typing(modelbuilder: ModelBuilder)
823 do
824 if not has_value then return
825
826 var mpropdef = self.mreadpropdef
827 if mpropdef == null or mpropdef.msignature == null then return # skip error
828
829 var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
830 self.selfvariable = v.selfvariable
831
832 var nexpr = self.n_expr
833 if nexpr != null then
834 var mtype = self.mtype
835 v.visit_expr_subtype(nexpr, mtype)
836 end
837 var nblock = self.n_block
838 if nblock != null then
839 v.visit_stmt(nblock)
840 if not nblock.after_flow_context.is_unreachable then
841 # We reach the end of the init without having a return, it is bad
842 v.error(self, "Error: reached end of block; expected `return`.")
843 end
844 end
845 end
846 end
847
848 ###
849
850 redef class AExpr
851 # The static type of the expression.
852 # null if self is a statement or in case of error
853 var mtype: nullable MType = null
854
855 # Is the statement correctly typed?
856 # Used to distinguish errors and statements when `mtype == null`
857 var is_typed: Bool = false
858
859 # If required, the following implicit cast `.as(XXX)`
860 # Such a cast may by required after evaluating the expression when
861 # a unsafe operation is detected (silently accepted by the Nit language).
862 # The attribute is computed by `check_subtype`
863 var implicit_cast_to: nullable MType = null
864
865 # Return the variable read (if any)
866 # Used to perform adaptive typing
867 fun its_variable: nullable Variable do return null
868
869 private fun accept_typing(v: TypeVisitor)
870 do
871 v.error(self, "no implemented accept_typing for {self.class_name}")
872 end
873
874 # Is non-null if `self` is a leaf of a comprehension array construction.
875 # In this case, the enclosing literal array node is designated.
876 # The result of the evaluation of `self` must be
877 # stored inside the designated array (there is an implicit `push`)
878 var comprehension: nullable AArrayExpr = null
879
880 # It indicates the number of arguments collected as a vararg.
881 #
882 # When 0, the argument is used as is, without transformation.
883 # When 1, the argument is transformed into an singleton array.
884 # Above 1, the arguments and the next ones are transformed into a common array.
885 #
886 # This attribute is meaning less on expressions not used as attributes.
887 var vararg_decl: Int = 0
888 end
889
890 redef class ABlockExpr
891 redef fun accept_typing(v)
892 do
893 for e in self.n_expr do v.visit_stmt(e)
894 self.is_typed = true
895 end
896
897 # The type of a blockexpr is the one of the last expression (or null if empty)
898 redef fun mtype
899 do
900 if self.n_expr.is_empty then return null
901 return self.n_expr.last.mtype
902 end
903 end
904
905 redef class AVardeclExpr
906 redef fun accept_typing(v)
907 do
908 var variable = self.variable
909 if variable == null then return # Skip error
910
911 var ntype = self.n_type
912 var mtype: nullable MType
913 if ntype == null then
914 mtype = null
915 else
916 mtype = v.resolve_mtype(ntype)
917 if mtype == null then return # Skip error
918 end
919
920 var nexpr = self.n_expr
921 if nexpr != null then
922 if mtype != null then
923 var etype = v.visit_expr_subtype(nexpr, mtype)
924 if etype == mtype then
925 assert ntype != null
926 v.modelbuilder.advice(ntype, "useless-type", "Warning: useless type definition for variable `{variable.name}`")
927 end
928 else
929 mtype = v.visit_expr(nexpr)
930 if mtype == null then return # Skip error
931 end
932 end
933
934 var decltype = mtype
935 if mtype == null or mtype isa MNullType then
936 var objclass = v.get_mclass(self, "Object")
937 if objclass == null then return # skip error
938 decltype = objclass.mclass_type.as_nullable
939 if mtype == null then mtype = decltype
940 end
941
942 variable.declared_type = decltype
943 v.set_variable(self, variable, mtype)
944
945 #debug("var {variable}: {mtype}")
946
947 self.mtype = mtype
948 self.is_typed = true
949 end
950 end
951
952 redef class AVarExpr
953 redef fun its_variable do return self.variable
954 redef fun accept_typing(v)
955 do
956 var variable = self.variable
957 if variable == null then return # Skip error
958
959 var mtype = v.get_variable(self, variable)
960 if mtype != null then
961 #debug("{variable} is {mtype}")
962 else
963 #debug("{variable} is untyped")
964 end
965
966 self.mtype = mtype
967 end
968 end
969
970 redef class AVarAssignExpr
971 redef fun accept_typing(v)
972 do
973 var variable = self.variable
974 assert variable != null
975
976 var mtype = v.visit_expr_subtype(n_value, variable.declared_type)
977
978 v.set_variable(self, variable, mtype)
979
980 self.is_typed = true
981 end
982 end
983
984 redef class AReassignFormExpr
985 # The method designed by the reassign operator.
986 var reassign_callsite: nullable CallSite
987
988 var read_type: nullable MType = null
989
990 # Determine the `reassign_property`
991 # `readtype` is the type of the reading of the left value.
992 # `writetype` is the type of the writing of the left value.
993 # (Because of `ACallReassignExpr`, both can be different.
994 # Return the static type of the value to store.
995 private fun resolve_reassignment(v: TypeVisitor, readtype, writetype: MType): nullable MType
996 do
997 var reassign_name = self.n_assign_op.operator
998
999 self.read_type = readtype
1000
1001 var callsite = v.get_method(self.n_assign_op, readtype, reassign_name, false)
1002 if callsite == null then return null # Skip error
1003 self.reassign_callsite = callsite
1004
1005 var msignature = callsite.msignature
1006 var rettype = msignature.return_mtype
1007 assert msignature.arity == 1 and rettype != null
1008
1009 var value_type = v.visit_expr_subtype(self.n_value, msignature.mparameters.first.mtype)
1010 if value_type == null then return null # Skip error
1011
1012 v.check_subtype(self, rettype, writetype, false)
1013 return rettype
1014 end
1015 end
1016
1017 redef class AVarReassignExpr
1018 redef fun accept_typing(v)
1019 do
1020 var variable = self.variable
1021 assert variable != null
1022
1023 var readtype = v.get_variable(self, variable)
1024 if readtype == null then return
1025
1026 read_type = readtype
1027
1028 var writetype = variable.declared_type
1029 if writetype == null then return
1030
1031 var rettype = self.resolve_reassignment(v, readtype, writetype)
1032
1033 v.set_variable(self, variable, rettype)
1034
1035 self.is_typed = rettype != null
1036 end
1037 end
1038
1039
1040 redef class AContinueExpr
1041 redef fun accept_typing(v)
1042 do
1043 var nexpr = self.n_expr
1044 if nexpr != null then
1045 v.visit_expr(nexpr)
1046 end
1047 self.is_typed = true
1048 end
1049 end
1050
1051 redef class ABreakExpr
1052 redef fun accept_typing(v)
1053 do
1054 var nexpr = self.n_expr
1055 if nexpr != null then
1056 v.visit_expr(nexpr)
1057 end
1058 self.is_typed = true
1059 end
1060 end
1061
1062 redef class AReturnExpr
1063 redef fun accept_typing(v)
1064 do
1065 var nexpr = self.n_expr
1066 var ret_type
1067 var mpropdef = v.mpropdef
1068 if mpropdef isa MMethodDef then
1069 ret_type = mpropdef.msignature.return_mtype
1070 else if mpropdef isa MAttributeDef then
1071 ret_type = mpropdef.static_mtype
1072 else
1073 abort
1074 end
1075 if nexpr != null then
1076 if ret_type != null then
1077 v.visit_expr_subtype(nexpr, ret_type)
1078 else
1079 v.visit_expr(nexpr)
1080 v.error(nexpr, "Error: `return` with value in a procedure.")
1081 return
1082 end
1083 else if ret_type != null then
1084 v.error(self, "Error: `return` without value in a function.")
1085 return
1086 end
1087 self.is_typed = true
1088 end
1089 end
1090
1091 redef class AAbortExpr
1092 redef fun accept_typing(v)
1093 do
1094 self.is_typed = true
1095 end
1096 end
1097
1098 redef class AIfExpr
1099 redef fun accept_typing(v)
1100 do
1101 v.visit_expr_bool(n_expr)
1102
1103 v.visit_stmt(n_then)
1104 v.visit_stmt(n_else)
1105
1106 self.is_typed = true
1107
1108 if n_then != null and n_else == null then
1109 self.mtype = n_then.mtype
1110 end
1111 end
1112 end
1113
1114 redef class AIfexprExpr
1115 redef fun accept_typing(v)
1116 do
1117 v.visit_expr_bool(n_expr)
1118
1119 var t1 = v.visit_expr(n_then)
1120 var t2 = v.visit_expr(n_else)
1121
1122 if t1 == null or t2 == null then
1123 return # Skip error
1124 end
1125
1126 var t = v.merge_types(self, [t1, t2])
1127 if t == null then
1128 v.error(self, "Type Error: ambiguous type `{t1}` vs `{t2}`.")
1129 end
1130 self.mtype = t
1131 end
1132 end
1133
1134 redef class ADoExpr
1135 redef fun accept_typing(v)
1136 do
1137 v.visit_stmt(n_block)
1138 self.is_typed = true
1139 end
1140 end
1141
1142 redef class AWhileExpr
1143 redef fun accept_typing(v)
1144 do
1145 v.has_loop = true
1146 v.visit_expr_bool(n_expr)
1147 v.visit_stmt(n_block)
1148 self.is_typed = true
1149 end
1150 end
1151
1152 redef class ALoopExpr
1153 redef fun accept_typing(v)
1154 do
1155 v.has_loop = true
1156 v.visit_stmt(n_block)
1157 self.is_typed = true
1158 end
1159 end
1160
1161 redef class AForExpr
1162 redef fun accept_typing(v)
1163 do
1164 v.has_loop = true
1165
1166 for g in n_groups do
1167 var mtype = v.visit_expr(g.n_expr)
1168 if mtype == null then return
1169 g.do_type_iterator(v, mtype)
1170 if g.is_broken then is_broken = true
1171 end
1172
1173 v.visit_stmt(n_block)
1174
1175 self.mtype = n_block.mtype
1176 self.is_typed = true
1177 end
1178 end
1179
1180 redef class AForGroup
1181 var coltype: nullable MClassType
1182
1183 var method_iterator: nullable CallSite
1184 var method_is_ok: nullable CallSite
1185 var method_item: nullable CallSite
1186 var method_next: nullable CallSite
1187 var method_key: nullable CallSite
1188 var method_finish: nullable CallSite
1189
1190 var method_lt: nullable CallSite
1191 var method_successor: nullable CallSite
1192
1193 private fun do_type_iterator(v: TypeVisitor, mtype: MType)
1194 do
1195 if mtype isa MNullType then
1196 v.error(self, "Type Error: `for` cannot iterate over `null`.")
1197 return
1198 end
1199
1200 # get obj class
1201 var objcla = v.get_mclass(self, "Object")
1202 if objcla == null then return
1203
1204 # check iterator method
1205 var itdef = v.get_method(self, mtype, "iterator", n_expr isa ASelfExpr)
1206 if itdef == null then
1207 v.error(self, "Type Error: `for` expects a type providing an `iterator` method, got `{mtype}`.")
1208 return
1209 end
1210 self.method_iterator = itdef
1211
1212 # check that iterator return something
1213 var ittype = itdef.msignature.return_mtype
1214 if ittype == null then
1215 v.error(self, "Type Error: `for` expects the method `iterator` to return an `Iterator` or `MapIterator` type.")
1216 return
1217 end
1218
1219 # get iterator type
1220 var colit_cla = v.try_get_mclass(self, "Iterator")
1221 var mapit_cla = v.try_get_mclass(self, "MapIterator")
1222 var is_col = false
1223 var is_map = false
1224
1225 if colit_cla != null and v.is_subtype(ittype, colit_cla.get_mtype([objcla.mclass_type.as_nullable])) then
1226 # Iterator
1227 var coltype = ittype.supertype_to(v.mmodule, v.anchor, colit_cla)
1228 var variables = self.variables
1229 if variables.length != 1 then
1230 v.error(self, "Type Error: `for` expects only one variable when using `Iterator`.")
1231 else
1232 variables.first.declared_type = coltype.arguments.first
1233 end
1234 is_col = true
1235 end
1236
1237 if mapit_cla != null and v.is_subtype(ittype, mapit_cla.get_mtype([objcla.mclass_type.as_nullable, objcla.mclass_type.as_nullable])) then
1238 # Map Iterator
1239 var coltype = ittype.supertype_to(v.mmodule, v.anchor, mapit_cla)
1240 var variables = self.variables
1241 if variables.length != 2 then
1242 v.error(self, "Type Error: `for` expects two variables when using `MapIterator`.")
1243 else
1244 variables[0].declared_type = coltype.arguments[0]
1245 variables[1].declared_type = coltype.arguments[1]
1246 end
1247 is_map = true
1248 end
1249
1250 if not is_col and not is_map then
1251 v.error(self, "Type Error: `for` expects the method `iterator` to return an `Iterator` or `MapIterator` type.")
1252 return
1253 end
1254
1255 # anchor formal and virtual types
1256 if mtype.need_anchor then mtype = v.anchor_to(mtype)
1257
1258 mtype = mtype.undecorate
1259 self.coltype = mtype.as(MClassType)
1260
1261 # get methods is_ok, next, item
1262 var ikdef = v.get_method(self, ittype, "is_ok", false)
1263 if ikdef == null then
1264 v.error(self, "Type Error: `for` expects a method `is_ok` in type `{ittype}`.")
1265 return
1266 end
1267 self.method_is_ok = ikdef
1268
1269 var itemdef = v.get_method(self, ittype, "item", false)
1270 if itemdef == null then
1271 v.error(self, "Type Error: `for` expects a method `item` in type `{ittype}`.")
1272 return
1273 end
1274 self.method_item = itemdef
1275
1276 var nextdef = v.get_method(self, ittype, "next", false)
1277 if nextdef == null then
1278 v.error(self, "Type Error: `for` expects a method `next` in type {ittype}.")
1279 return
1280 end
1281 self.method_next = nextdef
1282
1283 self.method_finish = v.try_get_method(self, ittype, "finish", false)
1284
1285 if is_map then
1286 var keydef = v.get_method(self, ittype, "key", false)
1287 if keydef == null then
1288 v.error(self, "Type Error: `for` expects a method `key` in type `{ittype}`.")
1289 return
1290 end
1291 self.method_key = keydef
1292 end
1293
1294 if self.variables.length == 1 and n_expr isa ARangeExpr then
1295 var variable = variables.first
1296 var vtype = variable.declared_type.as(not null)
1297
1298 if n_expr isa AOrangeExpr then
1299 self.method_lt = v.get_method(self, vtype, "<", false)
1300 else
1301 self.method_lt = v.get_method(self, vtype, "<=", false)
1302 end
1303
1304 self.method_successor = v.get_method(self, vtype, "successor", false)
1305 end
1306 end
1307 end
1308
1309 redef class AWithExpr
1310 var method_start: nullable CallSite
1311 var method_finish: nullable CallSite
1312
1313 redef fun accept_typing(v: TypeVisitor)
1314 do
1315 var mtype = v.visit_expr(n_expr)
1316 if mtype == null then return
1317
1318 method_start = v.get_method(self, mtype, "start", n_expr isa ASelfExpr)
1319 method_finish = v.get_method(self, mtype, "finish", n_expr isa ASelfExpr)
1320
1321 v.visit_stmt(n_block)
1322 self.mtype = n_block.mtype
1323 self.is_typed = true
1324 end
1325 end
1326
1327 redef class AAssertExpr
1328 redef fun accept_typing(v)
1329 do
1330 v.visit_expr_bool(n_expr)
1331
1332 v.visit_stmt(n_else)
1333 self.is_typed = true
1334 end
1335 end
1336
1337 redef class AOrExpr
1338 redef fun accept_typing(v)
1339 do
1340 v.visit_expr_bool(n_expr)
1341 v.visit_expr_bool(n_expr2)
1342 self.mtype = v.type_bool(self)
1343 end
1344 end
1345
1346 redef class AImpliesExpr
1347 redef fun accept_typing(v)
1348 do
1349 v.visit_expr_bool(n_expr)
1350 v.visit_expr_bool(n_expr2)
1351 self.mtype = v.type_bool(self)
1352 end
1353 end
1354
1355 redef class AAndExpr
1356 redef fun accept_typing(v)
1357 do
1358 v.visit_expr_bool(n_expr)
1359 v.visit_expr_bool(n_expr2)
1360 self.mtype = v.type_bool(self)
1361 end
1362 end
1363
1364
1365 redef class ANotExpr
1366 redef fun accept_typing(v)
1367 do
1368 v.visit_expr_bool(n_expr)
1369 self.mtype = v.type_bool(self)
1370 end
1371 end
1372
1373 redef class AOrElseExpr
1374 redef fun accept_typing(v)
1375 do
1376 var t1 = v.visit_expr(n_expr)
1377 var t2 = v.visit_expr(n_expr2)
1378
1379 if t1 == null or t2 == null then
1380 return # Skip error
1381 end
1382
1383 if t1 isa MNullType then
1384 self.mtype = t2
1385 return
1386 else if v.can_be_null(t1) then
1387 t1 = t1.as_notnull
1388 end
1389
1390 var t = v.merge_types(self, [t1, t2])
1391 if t == null then
1392 var c = v.get_mclass(self, "Object")
1393 if c == null then return # forward error
1394 t = c.mclass_type
1395 if v.can_be_null(t2) then
1396 t = t.as_nullable
1397 end
1398 #v.error(self, "Type Error: ambiguous type {t1} vs {t2}")
1399 end
1400 self.mtype = t
1401 end
1402
1403 redef fun accept_post_typing(v)
1404 do
1405 var t1 = n_expr.mtype
1406 if t1 == null then
1407 return
1408 else
1409 v.check_can_be_null(n_expr, t1)
1410 end
1411 end
1412 end
1413
1414 redef class ATrueExpr
1415 redef fun accept_typing(v)
1416 do
1417 self.mtype = v.type_bool(self)
1418 end
1419 end
1420
1421 redef class AFalseExpr
1422 redef fun accept_typing(v)
1423 do
1424 self.mtype = v.type_bool(self)
1425 end
1426 end
1427
1428 redef class AIntegerExpr
1429 redef fun accept_typing(v)
1430 do
1431 var mclass: nullable MClass = null
1432 if value isa Byte then
1433 mclass = v.get_mclass(self, "Byte")
1434 else if value isa Int then
1435 mclass = v.get_mclass(self, "Int")
1436 else if value isa Int8 then
1437 mclass = v.get_mclass(self, "Int8")
1438 else if value isa Int16 then
1439 mclass = v.get_mclass(self, "Int16")
1440 else if value isa UInt16 then
1441 mclass = v.get_mclass(self, "UInt16")
1442 else if value isa Int32 then
1443 mclass = v.get_mclass(self, "Int32")
1444 else if value isa UInt32 then
1445 mclass = v.get_mclass(self, "UInt32")
1446 end
1447 if mclass == null then return # Forward error
1448 self.mtype = mclass.mclass_type
1449 end
1450 end
1451
1452 redef class AFloatExpr
1453 redef fun accept_typing(v)
1454 do
1455 var mclass = v.get_mclass(self, "Float")
1456 if mclass == null then return # Forward error
1457 self.mtype = mclass.mclass_type
1458 end
1459 end
1460
1461 redef class ACharExpr
1462 redef fun accept_typing(v) do
1463 var mclass: nullable MClass = null
1464 if is_ascii then
1465 mclass = v.get_mclass(self, "Byte")
1466 else if is_code_point then
1467 mclass = v.get_mclass(self, "Int")
1468 else
1469 mclass = v.get_mclass(self, "Char")
1470 end
1471 if mclass == null then return # Forward error
1472 self.mtype = mclass.mclass_type
1473 end
1474 end
1475
1476 redef class AStringFormExpr
1477 redef fun accept_typing(v)
1478 do
1479 var mclass = v.get_mclass(self, "String")
1480 if mclass == null then return # Forward error
1481 self.mtype = mclass.mclass_type
1482 end
1483 end
1484
1485 redef class ASuperstringExpr
1486 redef fun accept_typing(v)
1487 do
1488 var mclass = v.get_mclass(self, "String")
1489 if mclass == null then return # Forward error
1490 self.mtype = mclass.mclass_type
1491 var objclass = v.get_mclass(self, "Object")
1492 if objclass == null then return # Forward error
1493 var objtype = objclass.mclass_type
1494 for nexpr in self.n_exprs do
1495 v.visit_expr_subtype(nexpr, objtype)
1496 end
1497 end
1498 end
1499
1500 redef class AArrayExpr
1501 # The `with_capacity` method on Array
1502 var with_capacity_callsite: nullable CallSite
1503
1504 # The `push` method on arrays
1505 var push_callsite: nullable CallSite
1506
1507 # The element of each type
1508 var element_mtype: nullable MType
1509
1510 # Set that `self` is a part of comprehension array `na`
1511 # If `self` is a `for`, or a `if`, then `set_comprehension` is recursively applied.
1512 private fun set_comprehension(n: nullable AExpr)
1513 do
1514 if n == null then
1515 return
1516 else if n isa AForExpr then
1517 set_comprehension(n.n_block)
1518 else if n isa AIfExpr then
1519 set_comprehension(n.n_then)
1520 set_comprehension(n.n_else)
1521 else
1522 # is a leave
1523 n.comprehension = self
1524 end
1525 end
1526 redef fun accept_typing(v)
1527 do
1528 var mtype: nullable MType = null
1529 var ntype = self.n_type
1530 if ntype != null then
1531 mtype = v.resolve_mtype(ntype)
1532 if mtype == null then return # Skip error
1533 end
1534 var mtypes = new Array[nullable MType]
1535 var useless = false
1536 for e in self.n_exprs do
1537 var t = v.visit_expr(e)
1538 if t == null then
1539 return # Skip error
1540 end
1541 set_comprehension(e)
1542 if mtype != null then
1543 if v.check_subtype(e, t, mtype, false) == null then return # Forward error
1544 if t == mtype then useless = true
1545 else
1546 mtypes.add(t)
1547 end
1548 end
1549 if mtype == null then
1550 # Ensure monotony for type adaptation on loops
1551 if self.element_mtype != null then mtypes.add self.element_mtype
1552 mtype = v.merge_types(self, mtypes)
1553 end
1554 if mtype == null or mtype isa MNullType then
1555 v.error(self, "Type Error: ambiguous array type {mtypes.join(" ")}")
1556 return
1557 end
1558 if useless then
1559 assert ntype != null
1560 v.modelbuilder.warning(ntype, "useless-type", "Warning: useless type declaration `{mtype}` in literal Array since it can be inferred from the elements type.")
1561 end
1562
1563 self.element_mtype = mtype
1564
1565 var mclass = v.get_mclass(self, "Array")
1566 if mclass == null then return # Forward error
1567 var array_mtype = mclass.get_mtype([mtype])
1568
1569 with_capacity_callsite = v.get_method(self, array_mtype, "with_capacity", false)
1570 push_callsite = v.get_method(self, array_mtype, "push", false)
1571
1572 self.mtype = array_mtype
1573 end
1574 end
1575
1576 redef class ARangeExpr
1577 var init_callsite: nullable CallSite
1578
1579 redef fun accept_typing(v)
1580 do
1581 var discrete_class = v.get_mclass(self, "Discrete")
1582 if discrete_class == null then return # Forward error
1583 var discrete_type = discrete_class.intro.bound_mtype
1584 var t1 = v.visit_expr_subtype(self.n_expr, discrete_type)
1585 var t2 = v.visit_expr_subtype(self.n_expr2, discrete_type)
1586 if t1 == null or t2 == null then return
1587 var mclass = v.get_mclass(self, "Range")
1588 if mclass == null then return # Forward error
1589 var mtype
1590 if v.is_subtype(t1, t2) then
1591 mtype = mclass.get_mtype([t2])
1592 else if v.is_subtype(t2, t1) then
1593 mtype = mclass.get_mtype([t1])
1594 else
1595 v.error(self, "Type Error: cannot create range: `{t1}` vs `{t2}`.")
1596 return
1597 end
1598
1599 self.mtype = mtype
1600
1601 # get the constructor
1602 var callsite
1603 if self isa ACrangeExpr then
1604 callsite = v.get_method(self, mtype, "autoinit", false)
1605 else if self isa AOrangeExpr then
1606 callsite = v.get_method(self, mtype, "without_last", false)
1607 else
1608 abort
1609 end
1610 init_callsite = callsite
1611 end
1612 end
1613
1614 redef class ANullExpr
1615 redef fun accept_typing(v)
1616 do
1617 self.mtype = v.mmodule.model.null_type
1618 end
1619 end
1620
1621 redef class AIsaExpr
1622 # The static type to cast to.
1623 # (different from the static type of the expression that is `Bool`).
1624 var cast_type: nullable MType
1625 redef fun accept_typing(v)
1626 do
1627 v.visit_expr(n_expr)
1628
1629 var mtype = v.resolve_mtype(n_type)
1630
1631 self.cast_type = mtype
1632
1633 var variable = self.n_expr.its_variable
1634 if variable != null then
1635 #var orig = self.n_expr.mtype
1636 #var from = if orig != null then orig.to_s else "invalid"
1637 #var to = if mtype != null then mtype.to_s else "invalid"
1638 #debug("adapt {variable}: {from} -> {to}")
1639 self.after_flow_context.when_true.set_var(v, variable, mtype)
1640 end
1641
1642 self.mtype = v.type_bool(self)
1643 end
1644
1645 redef fun accept_post_typing(v)
1646 do
1647 v.check_expr_cast(self, self.n_expr, self.n_type)
1648 end
1649 end
1650
1651 redef class AAsCastExpr
1652 redef fun accept_typing(v)
1653 do
1654 v.visit_expr(n_expr)
1655
1656 self.mtype = v.resolve_mtype(n_type)
1657 end
1658
1659 redef fun accept_post_typing(v)
1660 do
1661 v.check_expr_cast(self, self.n_expr, self.n_type)
1662 end
1663 end
1664
1665 redef class AAsNotnullExpr
1666 redef fun accept_typing(v)
1667 do
1668 var mtype = v.visit_expr(self.n_expr)
1669 if mtype == null then return # Forward error
1670
1671 if mtype isa MNullType then
1672 v.error(self, "Type Error: `as(not null)` on `null`.")
1673 return
1674 end
1675
1676 if v.can_be_null(mtype) then
1677 mtype = mtype.as_notnull
1678 end
1679
1680 self.mtype = mtype
1681 end
1682
1683 redef fun accept_post_typing(v)
1684 do
1685 var mtype = n_expr.mtype
1686 if mtype == null then return
1687 v.check_can_be_null(n_expr, mtype)
1688 end
1689 end
1690
1691 redef class AParExpr
1692 redef fun accept_typing(v)
1693 do
1694 self.mtype = v.visit_expr(self.n_expr)
1695 end
1696 end
1697
1698 redef class AOnceExpr
1699 redef fun accept_typing(v)
1700 do
1701 self.mtype = v.visit_expr(self.n_expr)
1702 end
1703 end
1704
1705 redef class ASelfExpr
1706 redef var its_variable: nullable Variable
1707 redef fun accept_typing(v)
1708 do
1709 if v.is_toplevel_context and not self isa AImplicitSelfExpr then
1710 v.error(self, "Error: `self` cannot be used in top-level method.")
1711 end
1712 var variable = v.selfvariable
1713 self.its_variable = variable
1714 self.mtype = v.get_variable(self, variable)
1715 end
1716 end
1717
1718 redef class AImplicitSelfExpr
1719 # Is the implicit receiver `sys`?
1720 #
1721 # By default, the implicit receiver is `self`.
1722 # But when there is not method for `self`, `sys` is used as a fall-back.
1723 # Is this case this flag is set to `true`.
1724 var is_sys = false
1725 end
1726
1727 ## MESSAGE SENDING AND PROPERTY
1728
1729 redef class ASendExpr
1730 # The property invoked by the send.
1731 var callsite: nullable CallSite
1732
1733 redef fun bad_expr_message(child)
1734 do
1735 if child == self.n_expr then
1736 return "to be the receiver of `{self.property_name}`"
1737 end
1738 return null
1739 end
1740
1741 redef fun accept_typing(v)
1742 do
1743 var nrecv = self.n_expr
1744 var recvtype = v.visit_expr(nrecv)
1745 var name = self.property_name
1746 var node = self.property_node
1747
1748 if recvtype == null then return # Forward error
1749
1750 var callsite = null
1751 var unsafe_type = v.anchor_to(recvtype)
1752 var mproperty = v.try_get_mproperty_by_name2(node, unsafe_type, name)
1753 if mproperty == null and nrecv isa AImplicitSelfExpr then
1754 # Special fall-back search in `sys` when noting found in the implicit receiver.
1755 var sysclass = v.try_get_mclass(node, "Sys")
1756 if sysclass != null then
1757 var systype = sysclass.mclass_type
1758 mproperty = v.try_get_mproperty_by_name2(node, systype, name)
1759 if mproperty != null then
1760 callsite = v.get_method(node, systype, name, false)
1761 if callsite == null then return # Forward error
1762 # Update information, we are looking at `sys` now, not `self`
1763 nrecv.is_sys = true
1764 nrecv.its_variable = null
1765 nrecv.mtype = systype
1766 recvtype = systype
1767 end
1768 end
1769 end
1770 if callsite == null then
1771 # If still nothing, just exit
1772 callsite = v.get_method(node, recvtype, name, nrecv isa ASelfExpr)
1773 if callsite == null then return
1774 end
1775
1776 self.callsite = callsite
1777 var msignature = callsite.msignature
1778
1779 var args = compute_raw_arguments
1780
1781 callsite.check_signature(v, node, args)
1782
1783 if callsite.mproperty.is_init then
1784 var vmpropdef = v.mpropdef
1785 if not (vmpropdef isa MMethodDef and vmpropdef.mproperty.is_init) then
1786 v.error(node, "Error: an `init` can only be called from another `init`.")
1787 end
1788 if vmpropdef isa MMethodDef and vmpropdef.mproperty.is_root_init and not callsite.mproperty.is_root_init then
1789 v.error(node, "Error: `{vmpropdef}` cannot call a factory `{callsite.mproperty}`.")
1790 end
1791 end
1792
1793 var ret = msignature.return_mtype
1794 if ret != null then
1795 self.mtype = ret
1796 else
1797 self.is_typed = true
1798 end
1799 end
1800
1801 # The name of the property
1802 # Each subclass simply provide the correct name.
1803 private fun property_name: String is abstract
1804
1805 # The node identifying the name (id, operator, etc) for messages.
1806 #
1807 # Is `self` by default
1808 private fun property_node: ANode do return self
1809
1810 # An array of all arguments (excluding self)
1811 fun raw_arguments: Array[AExpr] do return compute_raw_arguments
1812
1813 private fun compute_raw_arguments: Array[AExpr] is abstract
1814 end
1815
1816 redef class ABinopExpr
1817 redef fun compute_raw_arguments do return [n_expr2]
1818 redef fun property_name do return operator
1819 redef fun property_node do return n_op
1820 end
1821
1822 redef class AEqFormExpr
1823 redef fun accept_typing(v)
1824 do
1825 super
1826 v.null_test(self)
1827 end
1828
1829 redef fun accept_post_typing(v)
1830 do
1831 var mtype = n_expr.mtype
1832 var mtype2 = n_expr2.mtype
1833
1834 if mtype == null or mtype2 == null then return
1835
1836 if not mtype2 isa MNullType then return
1837
1838 v.check_can_be_null(n_expr, mtype)
1839 end
1840 end
1841
1842 redef class AUnaryopExpr
1843 redef fun property_name do return "unary {operator}"
1844 redef fun compute_raw_arguments do return new Array[AExpr]
1845 end
1846
1847
1848 redef class ACallExpr
1849 redef fun property_name do return n_qid.n_id.text
1850 redef fun property_node do return n_qid
1851 redef fun compute_raw_arguments do return n_args.to_a
1852 end
1853
1854 redef class ACallAssignExpr
1855 redef fun property_name do return n_qid.n_id.text + "="
1856 redef fun property_node do return n_qid
1857 redef fun compute_raw_arguments
1858 do
1859 var res = n_args.to_a
1860 res.add(n_value)
1861 return res
1862 end
1863 end
1864
1865 redef class ABraExpr
1866 redef fun property_name do return "[]"
1867 redef fun compute_raw_arguments do return n_args.to_a
1868 end
1869
1870 redef class ABraAssignExpr
1871 redef fun property_name do return "[]="
1872 redef fun compute_raw_arguments
1873 do
1874 var res = n_args.to_a
1875 res.add(n_value)
1876 return res
1877 end
1878 end
1879
1880 redef class ASendReassignFormExpr
1881 # The property invoked for the writing
1882 var write_callsite: nullable CallSite
1883
1884 redef fun accept_typing(v)
1885 do
1886 var recvtype = v.visit_expr(self.n_expr)
1887 var name = self.property_name
1888 var node = self.property_node
1889
1890 if recvtype == null then return # Forward error
1891
1892 var for_self = self.n_expr isa ASelfExpr
1893 var callsite = v.get_method(node, recvtype, name, for_self)
1894
1895 if callsite == null then return
1896 self.callsite = callsite
1897
1898 var args = compute_raw_arguments
1899
1900 callsite.check_signature(v, node, args)
1901
1902 var readtype = callsite.msignature.return_mtype
1903 if readtype == null then
1904 v.error(node, "Error: `{name}` is not a function.")
1905 return
1906 end
1907
1908 var wcallsite = v.get_method(node, recvtype, name + "=", self.n_expr isa ASelfExpr)
1909 if wcallsite == null then return
1910 self.write_callsite = wcallsite
1911
1912 var wtype = self.resolve_reassignment(v, readtype, wcallsite.msignature.mparameters.last.mtype)
1913 if wtype == null then return
1914
1915 args = args.to_a # duplicate so raw_arguments keeps only the getter args
1916 args.add(self.n_value)
1917 wcallsite.check_signature(v, node, args)
1918
1919 self.is_typed = true
1920 end
1921 end
1922
1923 redef class ACallReassignExpr
1924 redef fun property_name do return n_qid.n_id.text
1925 redef fun property_node do return n_qid.n_id
1926 redef fun compute_raw_arguments do return n_args.to_a
1927 end
1928
1929 redef class ABraReassignExpr
1930 redef fun property_name do return "[]"
1931 redef fun compute_raw_arguments do return n_args.to_a
1932 end
1933
1934 redef class AInitExpr
1935 redef fun property_name do if n_args.n_exprs.is_empty then return "init" else return "autoinit"
1936 redef fun property_node do return n_kwinit
1937 redef fun compute_raw_arguments do return n_args.to_a
1938 end
1939
1940 redef class AExprs
1941 fun to_a: Array[AExpr] do return self.n_exprs.to_a
1942 end
1943
1944 ###
1945
1946 redef class ASuperExpr
1947 # The method to call if the super is in fact a 'super init call'
1948 # Note: if the super is a normal call-next-method, then this attribute is null
1949 var callsite: nullable CallSite
1950
1951 # The method to call is the super is a standard `call-next-method` super-call
1952 # Note: if the super is a special super-init-call, then this attribute is null
1953 var mpropdef: nullable MMethodDef
1954
1955 redef fun accept_typing(v)
1956 do
1957 var anchor = v.anchor
1958 assert anchor != null
1959 var recvtype = v.get_variable(self, v.selfvariable)
1960 assert recvtype != null
1961 var mproperty = v.mpropdef.mproperty
1962 if not mproperty isa MMethod then
1963 v.error(self, "Error: `super` only usable in a `method`.")
1964 return
1965 end
1966 var superprops = mproperty.lookup_super_definitions(v.mmodule, anchor)
1967 if superprops.length == 0 then
1968 if mproperty.is_init and v.mpropdef.is_intro then
1969 process_superinit(v)
1970 return
1971 end
1972 v.error(self, "Error: no super method to call for `{mproperty}`.")
1973 return
1974 end
1975 # FIXME: covariance of return type in linear extension?
1976 var superprop = superprops.first
1977
1978 var msignature = superprop.msignature.as(not null)
1979 msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
1980 var args = self.n_args.to_a
1981 if args.length > 0 then
1982 signaturemap = v.check_signature(self, args, mproperty, msignature)
1983 end
1984 self.mtype = msignature.return_mtype
1985 self.is_typed = true
1986 v.mpropdef.has_supercall = true
1987 mpropdef = v.mpropdef.as(MMethodDef)
1988 end
1989
1990 # The mapping used on the call to associate arguments to parameters.
1991 # If null then no specific association is required.
1992 var signaturemap: nullable SignatureMap
1993
1994 private fun process_superinit(v: TypeVisitor)
1995 do
1996 var anchor = v.anchor
1997 assert anchor != null
1998 var recvtype = v.get_variable(self, v.selfvariable)
1999 assert recvtype != null
2000 var mpropdef = v.mpropdef
2001 assert mpropdef isa MMethodDef
2002 var mproperty = mpropdef.mproperty
2003 var superprop: nullable MMethodDef = null
2004 for msupertype in mpropdef.mclassdef.supertypes do
2005 msupertype = msupertype.anchor_to(v.mmodule, anchor)
2006 var errcount = v.modelbuilder.toolcontext.error_count
2007 var candidate = v.try_get_mproperty_by_name2(self, msupertype, mproperty.name).as(nullable MMethod)
2008 if candidate == null then
2009 if v.modelbuilder.toolcontext.error_count > errcount then return # Forward error
2010 continue # Try next super-class
2011 end
2012 if superprop != null and candidate.is_root_init then
2013 continue
2014 end
2015 if superprop != null and superprop.mproperty != candidate and not superprop.mproperty.is_root_init then
2016 v.error(self, "Error: conflicting super constructor to call for `{mproperty}`: `{candidate.full_name}`, `{superprop.mproperty.full_name}`")
2017 return
2018 end
2019 var candidatedefs = candidate.lookup_definitions(v.mmodule, anchor)
2020 if superprop != null and superprop.mproperty == candidate then
2021 if superprop == candidatedefs.first then continue
2022 candidatedefs.add(superprop)
2023 end
2024 if candidatedefs.length > 1 then
2025 v.error(self, "Error: conflicting property definitions for property `{mproperty}` in `{recvtype}`: {candidatedefs.join(", ")}")
2026 return
2027 end
2028 superprop = candidatedefs.first
2029 end
2030 if superprop == null then
2031 v.error(self, "Error: no super method to call for `{mproperty}`.")
2032 return
2033 end
2034
2035 var msignature = superprop.msignature.as(not null)
2036 msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
2037
2038 var callsite = new CallSite(hot_location, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)
2039 self.callsite = callsite
2040
2041 var args = self.n_args.to_a
2042 if args.length > 0 then
2043 callsite.check_signature(v, self, args)
2044 else
2045 # Check there is at least enough parameters
2046 if mpropdef.msignature.arity < msignature.arity then
2047 v.error(self, "Error: not enough implicit arguments to pass. Got `{mpropdef.msignature.arity}`, expected at least `{msignature.arity}`. Signature is `{msignature}`.")
2048 return
2049 end
2050 # Check that each needed parameter is conform
2051 var i = 0
2052 for sp in msignature.mparameters do
2053 var p = mpropdef.msignature.mparameters[i]
2054 if not v.is_subtype(p.mtype, sp.mtype) then
2055 v.error(self, "Type Error: expected argument #{i} of type `{sp.mtype}`, got implicit argument `{p.name}` of type `{p.mtype}`. Signature is {msignature}")
2056 return
2057 end
2058 i += 1
2059 end
2060 end
2061
2062 self.is_typed = true
2063 end
2064 end
2065
2066 ####
2067
2068 redef class ANewExpr
2069 # The constructor invoked by the new.
2070 var callsite: nullable CallSite
2071
2072 # The designated type
2073 var recvtype: nullable MClassType
2074
2075 redef fun accept_typing(v)
2076 do
2077 var recvtype = v.resolve_mtype(self.n_type)
2078 if recvtype == null then return
2079
2080 if not recvtype isa MClassType then
2081 if recvtype isa MNullableType then
2082 v.error(self, "Type Error: cannot instantiate the nullable type `{recvtype}`.")
2083 return
2084 else if recvtype isa MFormalType then
2085 v.error(self, "Type Error: cannot instantiate the formal type `{recvtype}`.")
2086 return
2087 else
2088 v.error(self, "Type Error: cannot instantiate the type `{recvtype}`.")
2089 return
2090 end
2091 end
2092
2093 self.recvtype = recvtype
2094 var kind = recvtype.mclass.kind
2095
2096 var name: String
2097 var nqid = self.n_qid
2098 var node: ANode
2099 if nqid != null then
2100 name = nqid.n_id.text
2101 node = nqid
2102 else
2103 name = "new"
2104 node = self.n_kwnew
2105 end
2106 if name == "intern" then
2107 if kind != concrete_kind then
2108 v.error(self, "Type Error: cannot instantiate {kind} {recvtype}.")
2109 return
2110 end
2111 if n_args.n_exprs.not_empty then
2112 v.error(n_args, "Type Error: the intern constructor expects no arguments.")
2113 return
2114 end
2115 # Our job is done
2116 self.mtype = recvtype
2117 return
2118 end
2119
2120 var callsite = v.get_method(node, recvtype, name, false)
2121 if callsite == null then return
2122
2123 if not callsite.mproperty.is_new then
2124 if kind != concrete_kind then
2125 v.error(self, "Type Error: cannot instantiate {kind} `{recvtype}`.")
2126 return
2127 end
2128 self.mtype = recvtype
2129 else
2130 self.mtype = callsite.msignature.return_mtype
2131 assert self.mtype != null
2132 end
2133
2134 self.callsite = callsite
2135
2136 if not callsite.mproperty.is_init_for(recvtype.mclass) then
2137 v.error(self, "Error: `{name}` is not a constructor.")
2138 return
2139 end
2140
2141 var args = n_args.to_a
2142 callsite.check_signature(v, node, args)
2143 end
2144 end
2145
2146 ####
2147
2148 redef class AAttrFormExpr
2149 # The attribute accessed.
2150 var mproperty: nullable MAttribute
2151
2152 # The static type of the attribute.
2153 var attr_type: nullable MType
2154
2155 # Resolve the attribute accessed.
2156 private fun resolve_property(v: TypeVisitor)
2157 do
2158 var recvtype = v.visit_expr(self.n_expr)
2159 if recvtype == null then return # Skip error
2160 var node = self.n_id
2161 var name = node.text
2162 if recvtype isa MNullType then
2163 v.error(node, "Error: attribute `{name}` access on `null`.")
2164 return
2165 end
2166
2167 var unsafe_type = v.anchor_to(recvtype)
2168 var mproperty = v.try_get_mproperty_by_name2(node, unsafe_type, name)
2169 if mproperty == null then
2170 v.modelbuilder.error(node, "Error: attribute `{name}` does not exist in `{recvtype}`.")
2171 return
2172 end
2173 assert mproperty isa MAttribute
2174 self.mproperty = mproperty
2175
2176 var mpropdefs = mproperty.lookup_definitions(v.mmodule, unsafe_type)
2177 assert mpropdefs.length == 1
2178 var mpropdef = mpropdefs.first
2179 var attr_type = mpropdef.static_mtype
2180 if attr_type == null then return # skip error
2181 attr_type = v.resolve_for(attr_type, recvtype, self.n_expr isa ASelfExpr)
2182 self.attr_type = attr_type
2183 end
2184 end
2185
2186 redef class AAttrExpr
2187 redef fun accept_typing(v)
2188 do
2189 self.resolve_property(v)
2190 self.mtype = self.attr_type
2191 end
2192 end
2193
2194
2195 redef class AAttrAssignExpr
2196 redef fun accept_typing(v)
2197 do
2198 self.resolve_property(v)
2199 var mtype = self.attr_type
2200
2201 v.visit_expr_subtype(self.n_value, mtype)
2202 self.is_typed = mtype != null
2203 end
2204 end
2205
2206 redef class AAttrReassignExpr
2207 redef fun accept_typing(v)
2208 do
2209 self.resolve_property(v)
2210 var mtype = self.attr_type
2211 if mtype == null then return # Skip error
2212
2213 var rettype = self.resolve_reassignment(v, mtype, mtype)
2214
2215 self.is_typed = rettype != null
2216 end
2217 end
2218
2219 redef class AIssetAttrExpr
2220 redef fun accept_typing(v)
2221 do
2222 self.resolve_property(v)
2223 var mtype = self.attr_type
2224 if mtype == null then return # Skip error
2225
2226 var recvtype = self.n_expr.mtype.as(not null)
2227 var bound = v.resolve_for(mtype, recvtype, false)
2228 if bound isa MNullableType then
2229 v.error(n_id, "Type Error: `isset` on a nullable attribute.")
2230 end
2231 self.mtype = v.type_bool(self)
2232 end
2233 end
2234
2235 redef class AVarargExpr
2236 redef fun accept_typing(v)
2237 do
2238 # This kind of pseudo-expression can be only processed trough a signature
2239 # See `check_signature`
2240 # Other cases are a syntax error.
2241 v.error(self, "Syntax Error: unexpected `...`.")
2242 end
2243 end
2244
2245 ###
2246
2247 redef class ADebugTypeExpr
2248 redef fun accept_typing(v)
2249 do
2250 var expr = v.visit_expr(self.n_expr)
2251 if expr == null then return
2252 var unsafe = v.anchor_to(expr)
2253 var ntype = self.n_type
2254 var mtype = v.resolve_mtype(ntype)
2255 if mtype != null and mtype != expr then
2256 var umtype = v.anchor_to(mtype)
2257 v.modelbuilder.warning(self, "debug", "Found type {expr} (-> {unsafe}), expected {mtype} (-> {umtype})")
2258 end
2259 self.is_typed = true
2260 end
2261 end