model: extract infer_static_type to support recursive calls
[nit.git] / src / modelize / modelize_property.nit
index 1a95c3e..aabe809 100644 (file)
@@ -80,7 +80,6 @@ redef class ModelBuilder
        end
 
        # Build the properties of `nclassdef`.
-       # REQUIRE: all superclasses are built.
        private fun build_properties(nclassdef: AClassdef)
        do
                # Force building recursively
@@ -111,7 +110,7 @@ redef class ModelBuilder
                                if not check_virtual_types_circularity(npropdef, mpropdef.mproperty, mclassdef.bound_mtype, mclassdef.mmodule) then
                                        # Invalidate the bound
                                        mpropdef.is_broken = true
-                                       mpropdef.bound = new MBottomType(mclassdef.mmodule.model)
+                                       mpropdef.bound = new MErrorType(mclassdef.mmodule.model)
                                end
                        end
                        for npropdef in nclassdef2.n_propdefs do
@@ -145,7 +144,7 @@ redef class ModelBuilder
                # Look for the init in Object, or create it
                if mclassdef.mclass.name == "Object" and the_root_init_mmethod == null then
                        # Create the implicit root-init method
-                       var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility)
+                       var mprop = new MMethod(mclassdef, "init", nclassdef.location, mclassdef.mclass.visibility)
                        mprop.is_root_init = true
                        var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
                        var mparameters = new Array[MParameter]
@@ -384,6 +383,8 @@ redef class ModelBuilder
                        # nothing to do.
                else if mtype isa MBottomType then
                        # nothing to do.
+               else if mtype isa MErrorType then
+                       # nothing to do.
                else
                        node.debug "Unexpected type {mtype}"
                        abort
@@ -589,7 +590,7 @@ redef class APropdef
                        var mdoc = ndoc.to_mdoc
                        mpropdef.mdoc = mdoc
                        mdoc.original_mentity = mpropdef
-               else if mpropdef.is_intro and mpropdef.mproperty.visibility >= protected_visibility then
+               else if mpropdef.is_intro and mpropdef.mproperty.visibility >= protected_visibility and mpropdef.name != "new" then
                        modelbuilder.advice(self, "missing-doc", "Documentation warning: Undocumented property `{mpropdef.mproperty}`")
                end
 
@@ -670,14 +671,13 @@ redef class ASignature
        # Visit and fill information about a signature
        private fun visit_signature(modelbuilder: ModelBuilder, mclassdef: MClassDef): Bool
        do
-               var mmodule = mclassdef.mmodule
                var param_names = self.param_names
                var param_types = self.param_types
                for np in self.n_params do
                        param_names.add(np.n_id.text)
                        var ntype = np.n_type
                        if ntype != null then
-                               var mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, ntype, true)
+                               var mtype = modelbuilder.resolve_mtype_unchecked(mclassdef, ntype, true)
                                if mtype == null then return false # Skip error
                                for i in [0..param_names.length-param_types.length[ do
                                        param_types.add(mtype)
@@ -694,7 +694,7 @@ redef class ASignature
                end
                var ntype = self.n_type
                if ntype != null then
-                       self.ret_type = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, ntype, true)
+                       self.ret_type = modelbuilder.resolve_mtype_unchecked(mclassdef, ntype, true)
                        if self.ret_type == null then return false # Skip error
                end
 
@@ -708,14 +708,14 @@ redef class ASignature
                for np in self.n_params do
                        var ntype = np.n_type
                        if ntype != null then
-                               if modelbuilder.resolve_mtype(mclassdef.mmodule, mclassdef, ntype) == null then
+                               if modelbuilder.resolve_mtype(mclassdef, ntype) == null then
                                        res = false
                                end
                        end
                end
                var ntype = self.n_type
                if ntype != null then
-                       if modelbuilder.resolve_mtype(mclassdef.mmodule, mclassdef, ntype) == null then
+                       if modelbuilder.resolve_mtype(mclassdef, ntype) == null then
                                res = false
                        end
                end
@@ -769,22 +769,21 @@ redef class AMethPropdef
        do
                var n_kwinit = n_kwinit
                var n_kwnew = n_kwnew
-               var is_init = n_kwinit != null or n_kwnew != null
+               var is_new = n_kwnew != null
+               var is_init = n_kwinit != null or is_new
                var name: String
                var amethodid = self.n_methid
                var name_node: ANode
                if amethodid == null then
-                       if not is_init then
-                               name = "main"
-                               name_node = self
-                       else if n_kwinit != null then
+                       if n_kwinit != null then
                                name = "init"
                                name_node = n_kwinit
                        else if n_kwnew != null then
                                name = "new"
                                name_node = n_kwnew
                        else
-                               abort
+                               name = "main"
+                               name_node = self
                        end
                else if amethodid isa AIdMethid then
                        name = amethodid.n_id.text
@@ -822,23 +821,21 @@ redef class AMethPropdef
                end
                if mprop == null then
                        var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility)
-                       mprop = new MMethod(mclassdef, name, mvisibility)
+                       mprop = new MMethod(mclassdef, name, self.location, mvisibility)
                        if look_like_a_root_init and modelbuilder.the_root_init_mmethod == null then
                                modelbuilder.the_root_init_mmethod = mprop
                                mprop.is_root_init = true
                        end
                        mprop.is_init = is_init
-                       mprop.is_new = n_kwnew != null
-                       if mprop.is_new then mclassdef.mclass.has_new_factory = true
+                       mprop.is_new = is_new
+                       if is_new then mclassdef.mclass.has_new_factory = true
                        if name == "sys" then mprop.is_toplevel = true # special case for sys allowed in `new` factories
                        if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mprop) then
                                mprop.is_broken = true
                                return
                        end
                else
-                       if mprop.is_broken then
-                               return
-                       end
+                       if mprop.is_broken then return
                        if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, not self isa AMainMethPropdef, mprop) then return
                        check_redef_property_visibility(modelbuilder, self.n_visibility, mprop)
                end
@@ -875,11 +872,12 @@ redef class AMethPropdef
        do
                var mpropdef = self.mpropdef
                if mpropdef == null then return # Error thus skiped
+               var mproperty = mpropdef.mproperty
                var mclassdef = mpropdef.mclassdef
                var mmodule = mclassdef.mmodule
                var nsig = self.n_signature
 
-               if mpropdef.mproperty.is_root_init and not mclassdef.is_intro then
+               if mproperty.is_root_init and not mclassdef.is_intro then
                        var root_init = mclassdef.mclass.root_init
                        if root_init != null then
                                # Inherit the initializers by refinement
@@ -909,7 +907,7 @@ redef class AMethPropdef
                # FIXME: do not inherit from the intro, but from the most specific
                var msignature: nullable MSignature = null
                if not mpropdef.is_intro then
-                       msignature = mpropdef.mproperty.intro.msignature
+                       msignature = mproperty.intro.msignature
                        if msignature == null then return # Skip error
 
                        # The local signature is adapted to use the local formal types, if any.
@@ -919,14 +917,14 @@ redef class AMethPropdef
                        if param_names.length != msignature.arity then
                                var node: ANode
                                if nsig != null then node = nsig else node = self
-                               modelbuilder.error(node, "Redef Error: expected {msignature.arity} parameter(s) for `{mpropdef.mproperty.name}{msignature}`; got {param_names.length}. See introduction at `{mpropdef.mproperty.full_name}`.")
+                               modelbuilder.error(node, "Redef Error: expected {msignature.arity} parameter(s) for `{mproperty.name}{msignature}`; got {param_names.length}. See introduction at `{mproperty.full_name}`.")
                                return
                        end
-               else if mpropdef.mproperty.is_init and not mpropdef.mproperty.is_new then
+               else if mproperty.is_init and not mproperty.is_new then
                        # FIXME UGLY: inherit signature from a super-constructor
                        for msupertype in mclassdef.supertypes do
                                msupertype = msupertype.anchor_to(mmodule, mclassdef.bound_mtype)
-                               var candidate = modelbuilder.try_get_mproperty_by_name2(self, mmodule, msupertype, mpropdef.mproperty.name)
+                               var candidate = modelbuilder.try_get_mproperty_by_name2(self, mmodule, msupertype, mproperty.name)
                                if candidate != null then
                                        if msignature == null then
                                                msignature = candidate.intro.as(MMethodDef).msignature
@@ -963,14 +961,14 @@ redef class AMethPropdef
                end
 
                # In `new`-factories, the return type is by default the classtype.
-               if ret_type == null and mpropdef.mproperty.is_new then ret_type = mclassdef.mclass.mclass_type
+               if ret_type == null and mproperty.is_new then ret_type = mclassdef.mclass.mclass_type
 
                # Special checks for operator methods
                if not accept_special_last_parameter and mparameters.not_empty and mparameters.last.is_vararg then
-                       modelbuilder.error(self.n_signature.n_params.last, "Error: illegal variadic parameter `{mparameters.last}` for `{mpropdef.mproperty.name}`.")
+                       modelbuilder.error(self.n_signature.n_params.last, "Error: illegal variadic parameter `{mparameters.last}` for `{mproperty.name}`.")
                end
                if ret_type == null and return_is_mandatory then
-                       modelbuilder.error(self.n_methid, "Error: mandatory return type for `{mpropdef.mproperty.name}`.")
+                       modelbuilder.error(self.n_methid, "Error: mandatory return type for `{mproperty.name}`.")
                end
 
                msignature = new MSignature(mparameters, ret_type)
@@ -1159,8 +1157,8 @@ redef class AAttrPropdef
        # Is the node tagged optional?
        var is_optional = false
 
-       # Has the node a default value?
-       # Could be through `n_expr` or `n_block`
+       # Does the node have a default value?
+       # Could be through `n_expr`, `n_block` or `is_lazy`
        var has_value = false
 
        # The guard associated to a lazy attribute.
@@ -1186,7 +1184,7 @@ redef class AAttrPropdef
                                modelbuilder.error(self, "Error: attempt to define attribute `{name}` in the {mclass.kind} `{mclass}`.")
                        end
 
-                       var mprop = new MAttribute(mclassdef, "_" + name, private_visibility)
+                       var mprop = new MAttribute(mclassdef, "_" + name, self.location, private_visibility)
                        var mpropdef = new MAttributeDef(mclassdef, mprop, self.location)
                        self.mpropdef = mpropdef
                        modelbuilder.mpropdef2npropdef[mpropdef] = self
@@ -1196,14 +1194,24 @@ redef class AAttrPropdef
                var mreadprop = modelbuilder.try_get_mproperty_by_name(nid2, mclassdef, readname).as(nullable MMethod)
                if mreadprop == null then
                        var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility)
-                       mreadprop = new MMethod(mclassdef, readname, mvisibility)
-                       if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mreadprop) then return
+                       mreadprop = new MMethod(mclassdef, readname, self.location, mvisibility)
+                       if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mreadprop) then
+                               mreadprop.is_broken = true
+                               return
+                       end
                else
+                       if mreadprop.is_broken then return
                        if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, true, mreadprop) then return
                        check_redef_property_visibility(modelbuilder, self.n_visibility, mreadprop)
                end
                mclassdef.mprop2npropdef[mreadprop] = self
 
+               var attr_mpropdef = mpropdef
+               if attr_mpropdef != null then
+                       mreadprop.getter_for = attr_mpropdef.mproperty
+                       attr_mpropdef.mproperty.getter = mreadprop
+               end
+
                var mreadpropdef = new MMethodDef(mclassdef, mreadprop, self.location)
                self.mreadpropdef = mreadpropdef
                modelbuilder.mpropdef2npropdef[mreadpropdef] = self
@@ -1248,7 +1256,7 @@ redef class AAttrPropdef
                                return
                        end
                        is_lazy = true
-                       var mlazyprop = new MAttribute(mclassdef, "lazy _" + name, none_visibility)
+                       var mlazyprop = new MAttribute(mclassdef, "lazy _" + name, self.location, none_visibility)
                        mlazyprop.is_fictive = true
                        var mlazypropdef = new MAttributeDef(mclassdef, mlazyprop, self.location)
                        mlazypropdef.is_fictive = true
@@ -1295,10 +1303,14 @@ redef class AAttrPropdef
                                # By default, use protected visibility at most
                                if mvisibility > protected_visibility then mvisibility = protected_visibility
                        end
-                       mwriteprop = new MMethod(mclassdef, writename, mvisibility)
-                       if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef, false, mwriteprop) then return
+                       mwriteprop = new MMethod(mclassdef, writename, self.location, mvisibility)
+                       if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef, false, mwriteprop) then
+                               mwriteprop.is_broken = true
+                               return
+                       end
                        mwriteprop.deprecation = mreadprop.deprecation
                else
+                       if mwriteprop.is_broken then return
                        if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef or else n_kwredef, true, mwriteprop) then return
                        if atwritable != null then
                                check_redef_property_visibility(modelbuilder, atwritable.n_visibility, mwriteprop)
@@ -1306,6 +1318,11 @@ redef class AAttrPropdef
                end
                mclassdef.mprop2npropdef[mwriteprop] = self
 
+               if attr_mpropdef != null then
+                       mwriteprop.setter_for = attr_mpropdef.mproperty
+                       attr_mpropdef.mproperty.setter = mwriteprop
+               end
+
                var mwritepropdef = new MMethodDef(mclassdef, mwriteprop, self.location)
                self.mwritepropdef = mwritepropdef
                modelbuilder.mpropdef2npropdef[mwritepropdef] = self
@@ -1341,7 +1358,7 @@ redef class AAttrPropdef
 
                var ntype = self.n_type
                if ntype != null then
-                       mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, ntype, true)
+                       mtype = modelbuilder.resolve_mtype_unchecked(mclassdef, ntype, true)
                        if mtype == null then return
                end
 
@@ -1361,62 +1378,12 @@ redef class AAttrPropdef
                var nexpr = self.n_expr
                if mtype == null then
                        if nexpr != null then
-                               if nexpr isa ANewExpr then
-                                       mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, nexpr.n_type, true)
-                               else if nexpr isa AAsCastExpr then
-                                       mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, nexpr.n_type, true)
-                               else if nexpr isa AIntegerExpr then
-                                       var cla: nullable MClass = null
-                                       if nexpr.value isa Int then
-                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int")
-                                       else if nexpr.value isa Byte then
-                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Byte")
-                                       else if nexpr.value isa Int8 then
-                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int8")
-                                       else if nexpr.value isa Int16 then
-                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int16")
-                                       else if nexpr.value isa UInt16 then
-                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "UInt16")
-                                       else if nexpr.value isa Int32 then
-                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int32")
-                                       else if nexpr.value isa UInt32 then
-                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "UInt32")
-                                       else
-                                               # Should not happen, and should be updated as new types are added
-                                               abort
-                                       end
-                                       if cla != null then mtype = cla.mclass_type
-                               else if nexpr isa AFloatExpr then
-                                       var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Float")
-                                       if cla != null then mtype = cla.mclass_type
-                               else if nexpr isa ACharExpr then
-                                       var cla: nullable MClass
-                                       if nexpr.is_ascii then
-                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Byte")
-                                       else if nexpr.is_code_point then
-                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int")
-                                       else
-                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Char")
-                                       end
-                                       if cla != null then mtype = cla.mclass_type
-                               else if nexpr isa ABoolExpr then
-                                       var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Bool")
-                                       if cla != null then mtype = cla.mclass_type
-                               else if nexpr isa ASuperstringExpr then
-                                       var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "String")
-                                       if cla != null then mtype = cla.mclass_type
-                               else if nexpr isa AStringFormExpr then
-                                       var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "String")
-                                       if cla != null then mtype = cla.mclass_type
-                               else
-                                       modelbuilder.error(self, "Error: untyped attribute `{mreadpropdef}`. Implicit typing allowed only for literals and new.")
-                               end
-
+                               mtype = infer_static_type(modelbuilder, nexpr, mclassdef, mmodule, mreadpropdef)
                                if mtype == null then return
                        end
                else if ntype != null and inherited_type == mtype then
                        if nexpr isa ANewExpr then
-                               var xmtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, nexpr.n_type, true)
+                               var xmtype = modelbuilder.resolve_mtype_unchecked(mclassdef, nexpr.n_type, true)
                                if xmtype == mtype then
                                        modelbuilder.advice(ntype, "useless-type", "Warning: useless type definition")
                                end
@@ -1454,11 +1421,80 @@ redef class AAttrPropdef
 
                var mlazypropdef = self.mlazypropdef
                if mlazypropdef != null then
-                       mlazypropdef.static_mtype = modelbuilder.model.get_mclasses_by_name("Bool").first.mclass_type
+                       mlazypropdef.static_mtype = mmodule.bool_type
                end
                check_repeated_types(modelbuilder)
        end
 
+       # Detect the static type from the value assigned to the attribute `self`
+       #
+       # Return the static type if it can be safely inferred.
+       private fun infer_static_type(modelbuilder: ModelBuilder, nexpr: AExpr,
+               mclassdef: MClassDef, mmodule: MModule, mreadpropdef: MPropDef): nullable MType
+       do
+               var mtype = null
+               if nexpr isa ANewExpr then
+                       mtype = modelbuilder.resolve_mtype_unchecked(mclassdef, nexpr.n_type, true)
+               else if nexpr isa AAsCastExpr then
+                       mtype = modelbuilder.resolve_mtype_unchecked(mclassdef, nexpr.n_type, true)
+               else if nexpr isa AIntegerExpr then
+                       var cla: nullable MClass = null
+                       if nexpr.value isa Int then
+                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int")
+                       else if nexpr.value isa Byte then
+                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Byte")
+                       else if nexpr.value isa Int8 then
+                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int8")
+                       else if nexpr.value isa Int16 then
+                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int16")
+                       else if nexpr.value isa UInt16 then
+                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "UInt16")
+                       else if nexpr.value isa Int32 then
+                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int32")
+                       else if nexpr.value isa UInt32 then
+                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "UInt32")
+                       else
+                               # Should not happen, and should be updated as new types are added
+                               abort
+                       end
+                       if cla != null then mtype = cla.mclass_type
+               else if nexpr isa AFloatExpr then
+                       var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Float")
+                       if cla != null then mtype = cla.mclass_type
+               else if nexpr isa ACharExpr then
+                       var cla: nullable MClass
+                       if nexpr.is_ascii then
+                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Byte")
+                       else if nexpr.is_code_point then
+                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int")
+                       else
+                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Char")
+                       end
+                       if cla != null then mtype = cla.mclass_type
+               else if nexpr isa ABoolExpr then
+                       var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Bool")
+                       if cla != null then mtype = cla.mclass_type
+               else if nexpr isa ASuperstringExpr then
+                       var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "String")
+                       if cla != null then mtype = cla.mclass_type
+               else if nexpr isa AStringFormExpr then
+                       var cla: nullable MClass
+                       if nexpr.is_bytestring then
+                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Bytes")
+                       else if nexpr.is_re then
+                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Regex")
+                       else if nexpr.is_string then
+                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "String")
+                       else
+                               abort
+                       end
+                       if cla != null then mtype = cla.mclass_type
+               else
+                       modelbuilder.error(self, "Error: untyped attribute `{mreadpropdef}`. Implicit typing allowed only for literals and new.")
+               end
+               return mtype
+       end
+
        redef fun check_signature(modelbuilder)
        do
                var mpropdef = self.mpropdef
@@ -1472,11 +1508,11 @@ redef class AAttrPropdef
 
                # Check types
                if ntype != null then
-                       if modelbuilder.resolve_mtype(mmodule, mclassdef, ntype) == null then return
+                       if modelbuilder.resolve_mtype(mclassdef, ntype) == null then return
                end
                var nexpr = n_expr
                if nexpr isa ANewExpr then
-                       if modelbuilder.resolve_mtype(mmodule, mclassdef, nexpr.n_type) == null then return
+                       if modelbuilder.resolve_mtype(mclassdef, nexpr.n_type) == null then return
                end
 
                # Lookup for signature in the precursor
@@ -1593,12 +1629,13 @@ redef class ATypePropdef
                var mprop = modelbuilder.try_get_mproperty_by_name(self.n_qid, mclassdef, name)
                if mprop == null then
                        var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility)
-                       mprop = new MVirtualTypeProp(mclassdef, name, mvisibility)
+                       mprop = new MVirtualTypeProp(mclassdef, name, self.location, mvisibility)
                        for c in name.chars do if c >= 'a' and c<= 'z' then
                                modelbuilder.warning(n_qid, "bad-type-name", "Warning: lowercase in the virtual type `{name}`.")
                                break
                        end
                else
+                       if mprop.is_broken then return
                        assert mprop isa MVirtualTypeProp
                        check_redef_property_visibility(modelbuilder, self.n_visibility, mprop)
                end
@@ -1628,11 +1665,10 @@ redef class ATypePropdef
                var mpropdef = self.mpropdef
                if mpropdef == null then return # Error thus skipped
                var mclassdef = mpropdef.mclassdef
-               var mmodule = mclassdef.mmodule
                var mtype: nullable MType = null
 
                var ntype = self.n_type
-               mtype = modelbuilder.resolve_mtype_unchecked(mmodule, mclassdef, ntype, true)
+               mtype = modelbuilder.resolve_mtype_unchecked(mclassdef, ntype, true)
                if mtype == null then return
 
                mpropdef.bound = mtype
@@ -1654,7 +1690,7 @@ redef class ATypePropdef
                var anchor = mclassdef.bound_mtype
 
                var ntype = self.n_type
-               if modelbuilder.resolve_mtype(mmodule, mclassdef, ntype) == null then
+               if modelbuilder.resolve_mtype(mclassdef, ntype) == null then
                        mpropdef.bound = null
                        return
                end
@@ -1668,8 +1704,7 @@ redef class ATypePropdef
                                break
                        end
                        if p.mclassdef.mclass == mclassdef.mclass then
-                               # Still a warning to pass existing bad code
-                               modelbuilder.warning(n_type, "refine-type", "Redef Error: a virtual type cannot be refined.")
+                               modelbuilder.error(n_type, "Redef Error: a virtual type cannot be refined.")
                                break
                        end
                        if not modelbuilder.check_subtype(n_type, mmodule, anchor, bound, supbound) then