nitc :: TypeVisitor :: check_subtype
sub
is a subtype of sup
.If sub
is not a valid suptype, then display an error on node
and return null
.
If sub
is a safe subtype of sup
, then return sub
.
If sub
is an unsafe subtype (i.e., an implicit cast is required), then return sup
.
The point of the return type is to determinate the usable type on an expression when autocast
is true:
If the suptype is safe, then the return type is the one on the expression typed by sub
.
Is the subtype is unsafe, then the return type is the one of an implicit cast on sup
.
# Check that `sub` is a subtype of `sup`.
# If `sub` is not a valid suptype, then display an error on `node` and return `null`.
# If `sub` is a safe subtype of `sup`, then return `sub`.
# If `sub` is an unsafe subtype (i.e., an implicit cast is required), then return `sup`.
#
# The point of the return type is to determinate the usable type on an expression when `autocast` is true:
# If the suptype is safe, then the return type is the one on the expression typed by `sub`.
# Is the subtype is unsafe, then the return type is the one of an implicit cast on `sup`.
fun check_subtype(node: ANode, sub, sup: MType, autocast: Bool): nullable MType
do
if self.is_subtype(sub, sup) then return sub
if autocast and self.is_subtype(sub, self.anchor_to(sup)) then
# FIXME workaround to the current unsafe typing policy. To remove once fixed virtual types exists.
#node.debug("Unsafe typing: expected {sup}, got {sub}")
return sup
end
if sup isa MErrorType then return null # Skip error
if sub.need_anchor then
var u = anchor_to(sub)
self.modelbuilder.error(node, "Type Error: expected `{sup}`, got `{sub}: {u}`.")
else
self.modelbuilder.error(node, "Type Error: expected `{sup}`, got `{sub}`.")
end
return null
end
src/semantize/typing.nit:102,2--126,4
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
var supx = sup
var subx = sub
var p = node.parent.as(not null)
if p isa AExprs then p = p.parent.as(not null)
# Case of autocast
if not self.is_subtype(sub, sup) then
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.count_cast(node, supx, sub, mmodule, anchor)
else
sup = supx.resolve_for(anchor, null, mmodule, false)
if self.is_subtype(sub, sup) then
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}`")
return null
end
end
dcp.count_types(p, node, supx, subx, mmodule, anchor)
return res
end
# Count case
if not dcp.count_types(p, node, sub, sup, mmodule, anchor) then return sub
# Unknown explanation of covariance, go further
dcp.cpt_explanations["other covariance"] -= 1
var n = node
if n isa AOnceExpr then n = n.n_expr
dcp.cpt_expression.inc(n.class_name)
if node isa AArrayExpr then
dcp.cpt_explanations.inc("lit-array")
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
return res
end
src/metrics/detect_covariance.nit:346,2--409,4