Merge: introduce and use MModuleData
[nit.git] / src / model / model.nit
index 894278a..e2f853a 100644 (file)
@@ -887,6 +887,16 @@ abstract class MType
                return res
        end
 
+       # Return the not nullable version of the type
+       # Is the type is already not nullable, then self is returned.
+       #
+       # Note: this just remove the `nullable` notation, but the result can still contains null.
+       # For instance if `self isa MNullType` or self is a a formal type bounded by a nullable type.
+       fun as_notnullable: MType
+       do
+               return self
+       end
+
        private var as_nullable_cache: nullable MType = null
 
 
@@ -1153,6 +1163,20 @@ class MVirtualType
                abort
        end
 
+       # Is the virtual type fixed for a given resolved_receiver?
+       fun is_fixed(mmodule: MModule, resolved_receiver: MType): Bool
+       do
+               assert not resolved_receiver.need_anchor
+               var props = self.mproperty.lookup_definitions(mmodule, resolved_receiver)
+               if props.is_empty then
+                       abort
+               end
+               for p in props do
+                       if p.as(MVirtualTypeDef).is_fixed then return true
+               end
+               return false
+       end
+
        redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
        do
                assert can_resolve_for(mtype, anchor, mmodule)
@@ -1181,6 +1205,8 @@ class MVirtualType
                if resolved_reciever.as(MClassType).mclass.kind == enum_kind then return res
                # If the resolved type isa MVirtualType, it means that self was bound to it, and cannot be unbound. self is just fixed. so return the resolution.
                if res isa MVirtualType then return res
+               # If we are final, just return the resolution
+               if is_fixed(mmodule, resolved_reciever) then return res
                # It the resolved type isa intern class, then there is no possible valid redefinition is any potentiel subclass. self is just fixed. so simply return the resolution
                if res isa MClassType and res.mclass.kind == enum_kind then return res
                # TODO: Add 'fixed' virtual type in the specification.
@@ -1276,7 +1302,13 @@ class MParameterType
                #print "{class_name}: {self}/{mtype}/{anchor}?"
 
                if mtype isa MGenericType and mtype.mclass == self.mclass then
-                       return mtype.arguments[self.rank]
+                       var res = mtype.arguments[self.rank]
+                       if anchor != null and res.need_anchor then
+                               # Maybe the result can be resolved more if are bound to a final class
+                               var r2 = res.anchor_to(mmodule, anchor)
+                               if r2 isa MClassType and r2.mclass.kind == enum_kind then return r2
+                       end
+                       return res
                end
 
                # self is a parameter type of mtype (or of a super-class of mtype)
@@ -1355,6 +1387,7 @@ class MNullableType
 
        redef fun need_anchor do return mtype.need_anchor
        redef fun as_nullable do return self
+       redef fun as_notnullable do return mtype
        redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
        do
                var res = self.mtype.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
@@ -1620,7 +1653,7 @@ abstract class MProperty
        fun lookup_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
        do
                assert not mtype.need_anchor
-               if mtype isa MNullableType then mtype = mtype.mtype
+               mtype = mtype.as_notnullable
 
                var cache = self.lookup_definitions_cache[mmodule, mtype]
                if cache != null then return cache
@@ -1659,7 +1692,7 @@ abstract class MProperty
        fun lookup_super_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
        do
                assert not mtype.need_anchor
-               if mtype isa MNullableType then mtype = mtype.mtype
+               mtype = mtype.as_notnullable
 
                # First, select all candidates
                var candidates = new Array[MPROPDEF]
@@ -1736,7 +1769,7 @@ abstract class MProperty
        fun lookup_all_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
        do
                assert not mtype.need_anchor
-               if mtype isa MNullableType then mtype = mtype.mtype
+               mtype = mtype.as_notnullable
 
                var cache = self.lookup_all_definitions_cache[mmodule, mtype]
                if cache != null then return cache