covar_classes
, covar_pt
, contravar_classes
and contravar_pt
The algorithm uses a fixed-point approach on the covariance/contravariance rules.
# Propagate the variance constraints on `covar_classes`, `covar_pt`, `contravar_classes` and `contravar_pt`
#
# The algorithm uses a fixed-point approach on the covariance/contravariance rules.
fun propagate
do
# Classes to add to the `covar_classes` set at the end of an iteration
var new_covar = new Array[MClassType]
# Classes to add to the `contravar_classes` set at the end of an iteration
var new_contravar = new Array[MClassType]
# Does a modification occurred, so that another iteration is needed?
var dirty = true
# Total number of iterations
var cpt = 0
while dirty do
cpt += 1
dirty = false
new_covar.clear
new_contravar.clear
# Process the generic types in a covariant position
for c in covar_classes do for i in [0..c.mclass.arity[ do
# The type used in the argument
var ta = c.arguments[i].undecorate
# The associated formal parameter
var tp = c.mclass.mparameters[i]
if not ta.need_anchor then
# Nothing to do
else if ta isa MParameterType then
# COVAR * COVAR = COVAR
if covar_pt.has(tp) and not covar_pt.has(ta) then
covar_pt.add(ta)
dirty = true
end
# COVAR * CONTRAVAR = CONTRAVAR
if contravar_pt.has(tp) and not contravar_pt.has(ta) then
contravar_pt.add(ta)
dirty = true
end
else if ta isa MVirtualType then
# TODO?
else if ta isa MClassType then
# COVAR * COVAR = COVAR
if covar_pt.has(tp) and not covar_classes.has(ta) then
new_covar.add ta
dirty = true
end
# COVAR * CONTRAVAR = CONTRAVAR
if contravar_pt.has(tp) and not contravar_classes.has(ta) then
new_contravar.add ta
dirty = true
end
end
end
# Process the generic types in a contravariant position
for c in contravar_classes do for i in [0..c.mclass.arity[ do
# The type used in the argument
var ta = c.arguments[i].undecorate
# The associated formal parameter
var tp = c.mclass.mparameters[i]
if not ta.need_anchor then
# Nothing to do
else if ta isa MParameterType then
# CONTRAVAR * CONTRAVAR = COVAR
if contravar_pt.has(tp) and not covar_pt.has(ta) then
covar_pt.add(ta)
dirty = true
end
# CONTRAVAR * COVAR = CONTRAVAR
if covar_pt.has(tp) and not contravar_pt.has(ta) then
contravar_pt.add(ta)
dirty = true
end
else if ta isa MVirtualType then
# TODO?
else if ta isa MClassType then
# CONTRAVAR * CONTRAVAR = COVAR
if contravar_pt.has(tp) and not covar_classes.has(ta) then
new_covar.add ta
dirty = true
end
# CONTRAVAR * COVAR = CONTRAVAR
if covar_pt.has(tp) and not contravar_classes.has(ta) then
new_contravar.add ta
dirty = true
end
end
end
covar_classes.add_all(new_covar)
contravar_classes.add_all(new_contravar)
end
end
src/metrics/detect_variance_constraints.nit:203,2--298,4