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