parser: `Visitor::visit` does not accepts `null`
[nit.git] / src / typing.nit
index fb169f8..bf5cc99 100644 (file)
 module typing
 
 import flow
-import modelbuilder
+import modelize_property
+import phase
+import local_var_init
+
+redef class ToolContext
+       var typing_phase: Phase = new TypingPhase(self, [flow_phase, modelize_property_phase, local_var_init_phase])
+end
+
+private class TypingPhase
+       super Phase
+       redef fun process_npropdef(npropdef) do npropdef.do_typing(toolcontext.modelbuilder)
+end
 
 private class TypeVisitor
        var modelbuilder:  ModelBuilder
@@ -237,19 +248,33 @@ private class TypeVisitor
                end
 
                var propdefs = mproperty.lookup_definitions(self.mmodule, unsafe_type)
+               var mpropdef
                if propdefs.length == 0 then
                        self.modelbuilder.error(node, "Type error: no definition found for property {name} in {unsafe_type}")
                        return null
-               else if propdefs.length > 1 then
-                       self.modelbuilder.error(node, "Error: confliting property definitions for property {name} in {unsafe_type}: {propdefs.join(" ")}")
-                       return null
+               else if propdefs.length == 1 then
+                       mpropdef = propdefs.first
+               else
+                       self.modelbuilder.warning(node, "Warning: confliting property definitions for property {name} in {unsafe_type}: {propdefs.join(" ")}")
+                       mpropdef = mproperty.intro
                end
 
-               var mpropdef = propdefs.first
 
                var msignature = self.resolve_signature_for(mpropdef, recvtype, recv_is_self)
 
-               var callsite = new CallSite(node, recvtype, recv_is_self, mproperty, mpropdef, msignature)
+               var erasure_cast = false
+               var rettype = mpropdef.msignature.return_mtype
+               if not recv_is_self and rettype != null then
+                       if rettype isa MNullableType then rettype = rettype.mtype
+                       if rettype isa MParameterType then
+                               var erased_rettype = msignature.return_mtype
+                               assert erased_rettype != null
+                               #node.debug("Erasure cast: Really a {rettype} but unsafely a {erased_rettype}")
+                               erasure_cast = true
+                       end
+               end
+
+               var callsite = new CallSite(node, recvtype, recv_is_self, mproperty, mpropdef, msignature, erasure_cast)
                return callsite
        end
 
@@ -379,6 +404,9 @@ class CallSite
        # The resolved signature for the receiver
        var msignature: MSignature
 
+       # Is a implicit cast required on erasure typing policy?
+       var erasure_cast: Bool
+
        private fun check_signature(v: TypeVisitor, args: Array[AExpr]): Bool
        do
                return v.check_signature(self.node, args, self.mproperty.name, self.msignature)
@@ -558,11 +586,13 @@ redef class AVardeclExpr
                        end
                end
 
-               if mtype == null then
-                       mtype = v.get_mclass(self, "Object").mclass_type.as_nullable
+               var decltype = mtype
+               if mtype == null or mtype isa MNullType then
+                       decltype = v.get_mclass(self, "Object").mclass_type.as_nullable
+                       if mtype == null then mtype = decltype
                end
 
-               variable.declared_type = mtype
+               variable.declared_type = decltype
                v.set_variable(self, variable, mtype)
 
                #debug("var {variable}: {mtype}")
@@ -604,8 +634,11 @@ redef class AVarAssignExpr
 end
 
 redef class AReassignFormExpr
+       # @depreciated use `reassign_callsite`
+       fun reassign_property: nullable MMethodDef do return self.reassign_callsite.mpropdef
+
        # The method designed by the reassign operator.
-       var reassign_property: nullable MMethodDef = null
+       var reassign_callsite: nullable CallSite
 
        var read_type: nullable MType = null
 
@@ -634,9 +667,7 @@ redef class AReassignFormExpr
 
                var callsite = v.get_method(self, readtype, reassign_name, false)
                if callsite == null then return null # Skip error
-               var mpropdef = callsite.mpropdef
-
-               self.reassign_property = mpropdef
+               self.reassign_callsite = callsite
 
                var msignature = callsite.msignature
                var rettype = msignature.return_mtype
@@ -1131,8 +1162,11 @@ end
 ## MESSAGE SENDING AND PROPERTY
 
 redef class ASendExpr
+       # @depreciated: use `callsite`
+       fun mproperty: nullable MMethod do return callsite.mproperty
+
        # The property invoked by the send.
-       var mproperty: nullable MMethod
+       var callsite: nullable CallSite
 
        redef fun accept_typing(v)
        do
@@ -1147,8 +1181,7 @@ redef class ASendExpr
 
                var callsite = v.get_method(self, recvtype, name, self.n_expr isa ASelfExpr)
                if callsite == null then return
-               var mproperty = callsite.mproperty
-               self.mproperty = mproperty
+               self.callsite = callsite
                var msignature = callsite.msignature
 
                var args = compute_raw_arguments
@@ -1156,7 +1189,7 @@ redef class ASendExpr
 
                callsite.check_signature(v, args)
 
-               if mproperty.is_init then
+               if callsite.mproperty.is_init then
                        var vmpropdef = v.mpropdef
                        if not (vmpropdef isa MMethodDef and vmpropdef.mproperty.is_init) then
                                v.error(self, "Can call a init only in another init")
@@ -1300,8 +1333,11 @@ redef class ABraAssignExpr
 end
 
 redef class ASendReassignFormExpr
+       # @depreciated use `write_callsite`
+       fun write_mproperty: nullable MMethod do return write_callsite.mproperty
+
        # The property invoked for the writing
-       var write_mproperty: nullable MMethod = null
+       var write_callsite: nullable CallSite
 
        redef fun accept_typing(v)
        do
@@ -1318,8 +1354,7 @@ redef class ASendReassignFormExpr
                var callsite = v.get_method(self, recvtype, name, for_self)
 
                if callsite == null then return
-               var mproperty = callsite.mproperty
-               self.mproperty = mproperty
+               self.callsite = callsite
 
                var args = compute_raw_arguments
                self.raw_arguments = args
@@ -1334,8 +1369,7 @@ redef class ASendReassignFormExpr
 
                var wcallsite = v.get_method(self, recvtype, name + "=", self.n_expr isa ASelfExpr)
                if wcallsite == null then return
-               var wmproperty = wcallsite.mproperty
-               self.write_mproperty = wmproperty
+               self.write_callsite = wcallsite
 
                var wtype = self.resolve_reassignment(v, readtype, wcallsite.msignature.mparameters.last.mtype)
                if wtype == null then return
@@ -1390,10 +1424,8 @@ redef class ASuperExpr
                        end
                        v.error(self, "Error: No super method to call for {mproperty}.")
                        return
-               else if superprops.length > 1 then
-                       v.modelbuilder.warning(self, "Warning: NOT YET IMPLEMENTED: Conflicting super method to call for {mproperty}: {superprops.join(", ")}.")
-                       return
                end
+               # FIXME: covariance of return type in linear extension?
                var superprop = superprops.first
                assert superprop isa MMethodDef
 
@@ -1454,8 +1486,11 @@ end
 ####
 
 redef class ANewExpr
+       # @depreciated use `callsite`
+       fun mproperty: nullable MMethod do return self.callsite.mproperty
+
        # The constructor invoked by the new.
-       var mproperty: nullable MMethod
+       var callsite: nullable CallSite
 
        redef fun accept_typing(v)
        do
@@ -1483,7 +1518,7 @@ redef class ANewExpr
                var callsite = v.get_method(self, recvtype, name, false)
                if callsite == null then return
 
-               self.mproperty = callsite.mproperty
+               self.callsite = callsite
 
                if not callsite.mproperty.is_init_for(recvtype.mclass) then
                        v.error(self, "Error: {name} is not a constructor.")