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.

Property definitions

nitc $ TypeVisitor :: check_subtype
	# 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

nitc :: detect_covariance $ TypeVisitor :: check_subtype
	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