# Detect circularity errors for virtual types.
fun check_virtual_types_circularity(node: ANode, mproperty: MVirtualTypeProp, recv: MType, mmodule: MModule): Bool
do
# Check circularity
# Slow case: progress on each resolution until we visit all without getting a loop
# The graph used to detect loops
var mtype = mproperty.mvirtualtype
var poset = new POSet[MType]
# The work-list of types to resolve
var todo = new List[MType]
todo.add mtype
while not todo.is_empty do
# The visited type
var t = todo.pop
if not t.need_anchor then continue
# Get the types derived of `t` (subtypes and bounds)
var nexts
if t isa MNullableType then
nexts = [t.mtype]
else if t isa MGenericType then
nexts = t.arguments
else if t isa MVirtualType then
var vt = t.mproperty
# Because `vt` is possibly unchecked, we have to do the bound-lookup manually
var defs = vt.lookup_definitions(mmodule, recv)
if defs.is_empty then return false
nexts = new Array[MType]
for d in defs do
var next = defs.first.bound
if next == null then return false
nexts.add next
end
else if t isa MClassType then
# Basic type, nothing to to
continue
else if t isa MParameterType then
# Parameter types cannot depend on virtual types, so nothing to do
continue
else
abort
end
# For each one
for next in nexts do
if poset.has_edge(next, t) then
if mtype == next then
error(node, "Error: circularity of virtual type definition: {next} <-> {t}.")
else
error(node, "Error: circularity of virtual type definition: {mtype} -> {next} <-> {t}.")
end
return false
else
poset.add_edge(t, next)
todo.add next
end
end
end
return true
end
src/modelize/modelize_property.nit:445,2--508,4