Merge: autosuperinit: do not crash on broken model
[nit.git] / src / model / model.nit
index e0c3280..ccb7522 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}:"
@@ -614,7 +615,7 @@ class MClassDef
                        # public gives 'p#A'
                        # private gives 'p::m#A'
                        return "{mmodule.namespace_for(mclass.visibility)}#{mclass.name}"
-               else if mclass.intro_mmodule.mproject != mmodule.mproject then
+               else if mclass.intro_mmodule.mpackage != mmodule.mpackage then
                        # public gives 'q::n#p::A'
                        # private gives 'q::n#p::m::A'
                        return "{mmodule.full_name}#{mclass.full_name}"
@@ -630,7 +631,7 @@ class MClassDef
        redef var c_name is lazy do
                if is_intro then
                        return "{mmodule.c_namespace_for(mclass.visibility)}___{mclass.c_name}"
-               else if mclass.intro_mmodule.mproject == mmodule.mproject and mclass.visibility > private_visibility then
+               else if mclass.intro_mmodule.mpackage == mmodule.mpackage and mclass.visibility > private_visibility then
                        return "{mmodule.c_name}___{mclass.name.to_cmangle}"
                else
                        return "{mmodule.c_name}___{mclass.c_name}"
@@ -808,19 +809,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 +1010,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 +1024,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 +1367,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 +1402,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 +1570,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
@@ -1932,7 +1937,7 @@ abstract class MProperty
        # The canonical name of the property.
        #
        # It is the short-`name` prefixed by the short-name of the class and the full-name of the module.
-       # Example: "my_project::my_module::MyClass::my_method"
+       # Example: "my_package::my_module::MyClass::my_method"
        redef var full_name is lazy do
                return "{intro_mclassdef.mmodule.namespace_for(visibility)}::{intro_mclassdef.mclass.name}::{name}"
        end
@@ -2250,14 +2255,14 @@ abstract class MPropDef
                        res.append name
                else
                        # Just try to simplify each part
-                       if mclassdef.mmodule.mproject != mproperty.intro_mclassdef.mmodule.mproject then
+                       if mclassdef.mmodule.mpackage != mproperty.intro_mclassdef.mmodule.mpackage then
                                # precise "p::m" only if "p" != "r"
                                res.append mproperty.intro_mclassdef.mmodule.full_name
                                res.append "::"
                        else if mproperty.visibility <= private_visibility then
-                               # Same project ("p"=="q"), but private visibility,
+                               # Same package ("p"=="q"), but private visibility,
                                # does the module part ("::m") need to be displayed
-                               if mclassdef.mmodule.namespace_for(mclassdef.mclass.visibility) != mproperty.intro_mclassdef.mmodule.mproject then
+                               if mclassdef.mmodule.namespace_for(mclassdef.mclass.visibility) != mproperty.intro_mclassdef.mmodule.mpackage then
                                        res.append "::"
                                        res.append mproperty.intro_mclassdef.mmodule.name
                                        res.append "::"
@@ -2301,7 +2306,7 @@ abstract class MPropDef
        redef var to_s: String is noinit
 
        # Is self the definition that introduce the property?
-       fun is_intro: Bool do return mproperty.intro == self
+       fun is_intro: Bool do return isset mproperty._intro and mproperty.intro == self
 
        # Return the next definition in linearization of `mtype`.
        #