Merge: Inline binops
[nit.git] / src / model / model.nit
index 941bae7..b9d6aa2 100644 (file)
@@ -283,6 +283,7 @@ redef class MModule
                        end
                        print("Fatal Error: no primitive class {name} in {self}")
                        exit(1)
+                       abort
                end
                if cla.length != 1 then
                        var msg = "Fatal Error: more than one primitive class {name} in {self}:"
@@ -299,18 +300,15 @@ redef class MModule
                var props = self.model.get_mproperties_by_name(name)
                if props == null then return null
                var res: nullable MMethod = null
+               var recvtype = recv.intro.bound_mtype
                for mprop in props do
                        assert mprop isa MMethod
-                       var intro = mprop.intro_mclassdef
-                       for mclassdef in recv.mclassdefs do
-                               if not self.in_importation.greaters.has(mclassdef.mmodule) then continue
-                               if not mclassdef.in_hierarchy.greaters.has(intro) then continue
-                               if res == null then
-                                       res = mprop
-                               else if res != mprop then
-                                       print("Fatal Error: ambigous property name '{name}'; conflict between {mprop.full_name} and {res.full_name}")
-                                       abort
-                               end
+                       if not recvtype.has_mproperty(self, mprop) then continue
+                       if res == null then
+                               res = mprop
+                       else if res != mprop then
+                               print("Fatal Error: ambigous property name '{name}'; conflict between {mprop.full_name} and {res.full_name}")
+                               abort
                        end
                end
                return res
@@ -808,19 +806,19 @@ abstract class MType
                end
                #print "4.is {sub} a {sup}? <- no more resolution"
 
-               assert sub isa MClassType else print "{sub} <? {sub}" # It is the only remaining type
-
-               # A unfixed formal type can only accept itself
-               if sup isa MFormalType then
-                       return false
+               if sub isa MBottomType then
+                       return true
                end
 
-               if sup isa MNullType then
-                       # `sup` accepts only null
+               assert sub isa MClassType else print "{sub} <? {sub}" # It is the only remaining type
+
+               # Handle sup-type when the sub-type is class-based (other cases must have be identified before).
+               if sup isa MFormalType or sup isa MNullType or sup isa MBottomType then
+                       # These types are not super-types of Class-based types.
                        return false
                end
 
-               assert sup isa MClassType # It is the only remaining type
+               assert sup isa MClassType else print "got {sup} {sub.inspect}" # It is the only remaining type
 
                # Now both are MClassType, we need to dig
 
@@ -1009,7 +1007,7 @@ abstract class MType
        # The result is returned exactly as declared in the "type" property (verbatim).
        # So it could be another formal type.
        #
-       # In case of conflict, the method aborts.
+       # In case of conflicts or inconsistencies in the model, the method returns a `MBottomType`.
        fun lookup_bound(mmodule: MModule, resolved_receiver: MType): MType do return self
 
        # Resolve the formal type to its simplest equivalent form.
@@ -1023,6 +1021,8 @@ abstract class MType
        #
        # By default, return self.
        # See the redefinitions for specific behavior in each kind of type.
+       #
+       # In case of conflicts or inconsistencies in the model, the method returns a `MBottomType`.
        fun lookup_fixed(mmodule: MModule, resolved_receiver: MType): MType do return self
 
        # Can the type be resolved?
@@ -1364,7 +1364,7 @@ class MVirtualType
 
        redef fun lookup_bound(mmodule: MModule, resolved_receiver: MType): MType
        do
-               return lookup_single_definition(mmodule, resolved_receiver).bound.as(not null)
+               return lookup_single_definition(mmodule, resolved_receiver).bound or else new MBottomType(model)
        end
 
        private fun lookup_single_definition(mmodule: MModule, resolved_receiver: MType): MVirtualTypeDef
@@ -1399,7 +1399,8 @@ class MVirtualType
                assert resolved_receiver isa MClassType # It is the only remaining type
 
                var prop = lookup_single_definition(mmodule, resolved_receiver)
-               var res = prop.bound.as(not null)
+               var res = prop.bound
+               if res == null then return new MBottomType(model)
 
                # Recursively lookup the fixed result
                res = res.lookup_fixed(mmodule, resolved_receiver)
@@ -1566,6 +1567,7 @@ class MParameterType
                end
                if resolved_receiver isa MNullableType then resolved_receiver = resolved_receiver.mtype
                if resolved_receiver isa MParameterType then
+                       assert anchor != null
                        assert resolved_receiver.mclass == anchor.mclass
                        resolved_receiver = anchor.arguments[resolved_receiver.rank]
                        if resolved_receiver isa MNullableType then resolved_receiver = resolved_receiver.mtype
@@ -1813,16 +1815,26 @@ class MSignature
                for i in [0..mparameters.length[ do
                        var parameter = mparameters[i]
                        if parameter.is_vararg then
-                               assert vararg_rank == -1
+                               if vararg_rank >= 0 then
+                                       # If there is more than one vararg,
+                                       # consider that additional arguments cannot be mapped.
+                                       vararg_rank = -1
+                                       break
+                               end
                                vararg_rank = i
                        end
                end
                self.vararg_rank = vararg_rank
        end
 
-       # The rank of the ellipsis (`...`) for vararg (starting from 0).
+       # The rank of the main ellipsis (`...`) for vararg (starting from 0).
        # value is -1 if there is no vararg.
        # Example: for "(a: Int, b: Bool..., c: Char)" #-> vararg_rank=1
+       #
+       # From a model POV, a signature can contain more than one vararg parameter,
+       # the `vararg_rank` just indicates the one that will receive the additional arguments.
+       # However, currently, if there is more that one vararg parameter, no one will be the main one,
+       # and additional arguments will be refused.
        var vararg_rank: Int is noinit
 
        # The number of parameters