## ONLY covariance remains here
- cpt_modules.inc(mmodule.mgroup.mproject.name)
+ cpt_modules.inc(mmodule.mgroup.mpackage.name)
cpt_classes.inc(sub.mclass)
# Track if `cpt_explanations` is already decided (used to fallback on unknown)
fun dcp: DetectCovariancePhase do return modelbuilder.toolcontext.detect_covariance_phase
- redef fun visit_expr_cast(node, nexpr, ntype)
+ redef fun check_expr_cast(node, nexpr, ntype)
do
var sub = super
return sub
end
- redef fun check_subtype(node: ANode, sub, sup: MType): nullable MType
+ redef fun check_subtype(node: ANode, sub, sup: MType, autocast: Bool): nullable MType
do
var res = super
if dcp.is_disabled then return res
var anchor = self.anchor
- assert anchor != null
var supx = sup
var subx = sub
var p = node.parent.as(not null)
if node isa AAsCastExpr then
return res
end
+ if not autocast then
+ return res
+ end
sup = supx.resolve_for(anchor.mclass.mclass_type, anchor, mmodule, true)
if self.is_subtype(sub, sup) then
dcp.cpt_autocast.inc("vt")
dcp.cpt_autocast.inc("vt+pt")
dcp.count_cast(node, supx, sub, mmodule, anchor)
else
- self.modelbuilder.error(node, "Type error: expected {sup}, got {sub}")
+ self.modelbuilder.error(node, "Type Error: expected `{sup}`, got `{sub}`")
return null
end
end
if node isa AArrayExpr then
dcp.cpt_explanations.inc("lit-array")
- else if p isa ACallExpr and (p.n_id.text == "sort" or p.n_id.text == "linearize_mpropdefs") then
- dcp.cpt_explanations.inc("generic methods (sort-method)")
- else if p isa ACallExpr and p.n_id.text == "visit_list" then
- dcp.cpt_explanations.inc("use-site covariance (visit_list-method)")
+ else if p isa ACallExpr then
+ var name = p.n_qid.n_id.text
+ if name == "sort" or name == "linearize_mpropdefs" then
+ dcp.cpt_explanations.inc("generic methods (sort-method)")
+ else if name == "visit_list" then
+ dcp.cpt_explanations.inc("use-site covariance (visit_list-method)")
+ else
+ dcp.cpt_explanations.inc("other covariance")
+ end
else
dcp.cpt_explanations.inc("other covariance")
end
end
#print "4.is {sub} a {sup}? <- no more resolution"
- assert sub isa MClassType # 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 or sub isa MErrorType then
+ return true
end
- if sup isa MNullType then
- # `sup` accepts only null
+ assert sub isa MClassType else print_error "{sub} <? {sup}" # 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 or sup isa MErrorType 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_error "got {sup} {sub.inspect}" # It is the only remaining type
# Now both are MClassType, we need to dig
if anchor == null then anchor = sub # UGLY: any anchor will work
var resolved_sub = sub.anchor_to(mmodule, anchor)
var res = resolved_sub.collect_mclasses(mmodule).has(sup.mclass)
- if res == false then return false
+ if not res then return false
if not sup isa MGenericType then return true
var sub2 = sub.supertype_to(mmodule, anchor, sup.mclass)
assert sub2.mclass == sup.mclass
var sub_arg = sub2.arguments[i]
var sup_arg = sup.arguments[i]
res = sub_arg.is_subtype(mmodule, anchor, sup_arg)
- if res == false then return false
+ if not res then return false
# The two new lines
res = sup_arg.is_subtype(mmodule, anchor, sub_arg)
- if res == false then return false
+ if not res then return false
# End of the two new lines
end
return true