in scala/scala-impl/src/org/jetbrains/plugins/scala/lang/psi/types/ScalaConformance.scala [977:1191]
override def visitParameterizedType(p: ParameterizedType): Unit = {
var rightVisitor: ScalaTypeVisitor =
new ValDesignatorSimplification with UndefinedSubstVisitor with AbstractVisitor {}
r.visitType(rightVisitor)
if (result != null) return
p.designator match {
case DesignatorOwner(ta: ScTypeAlias) if p.typeArguments.size == 1 =>
val containingClassName = Option(ta.containingClass).map(_.qualifiedName).orNull
if (containingClassName == "scala.compiletime.ops.int" && ta.name == "S") {
r match {
case ScLiteralType(ScIntegerLiteralImpl.Value(int), _) if int > 0 =>
val tvar = p.typeArguments.head
val decremented = ScIntegerLiteralImpl.Value(int - 1)
result = equivInner(tvar, ScLiteralType(decremented)(projectContext), constraints, falseUndef = false)
return
case _ => ()
}
}
case a: ScAbstractType =>
val subst = ScSubstitutor.bind(a.typeParameter.typeParameters, p.typeArguments)
val upper: ScType =
subst(a.upper) match {
case up if up.equiv(Any) => Any
case ParameterizedType(up, _) => ScParameterizedType(up, p.typeArguments)
case up => ScParameterizedType(up, p.typeArguments)
}
if (!upper.equiv(Any)) {
result = conformsInner(upper, r, visited, constraints, checkWeak)
} else {
result = constraints
}
if (result.isRight) {
val lower: ScType =
subst(a.lower) match {
case low if low.equiv(Nothing) => Nothing
case ParameterizedType(low, _) => ScParameterizedType(low, p.typeArguments)
case low => ScParameterizedType(low, p.typeArguments)
}
if (!lower.equiv(Nothing)) {
val t = conformsInner(r, lower, visited, result.constraints, checkWeak)
if (t.isRight) result = t
}
}
return
case _ =>
}
rightVisitor = new ParameterizedAbstractVisitor {}
r.visitType(rightVisitor)
if (result != null) return
checkEquiv()
if (result ne null) return
rightVisitor = new ExistentialSimplification with ExistentialArgumentVisitor {}
r.visitType(rightVisitor)
if (result != null) return
p.designator match {
case s: ScExistentialArgument =>
s.lower match {
case ParameterizedType(lower, _) =>
result = conformsInner(lower, r, visited, constraints, checkWeak)
return
case lower =>
result = conformsInner(lower, r, visited, constraints, checkWeak)
return
}
case _ =>
}
rightVisitor = new ParameterizedExistentialArgumentVisitor with OtherNonvalueTypesVisitor with NothingNullVisitor
with ThisVisitor {}
r.visitType(rightVisitor)
if (result != null) return
r match {
case ScalaArrayType(rightArg) =>
p match {
case ScalaArrayType(leftArg) => result = checkArrayArgs(leftArg, rightArg)
case _ =>
}
case p2: ScParameterizedType =>
val des1 = p.designator
val des2 = p2.designator
val args1 = p.typeArguments
val args2 = p2.typeArguments
(des1, des2) match {
case (lhs: TypeParameterType, _: TypeParameterType) =>
if (des1.equiv(des2)) {
if (args1.length != args2.length) {
result = ConstraintsResult.Left
} else {
result = checkParameterizedType(lhs.typeParameters, args1, args2,
constraints, visited, checkWeak)
}
} else result = retryTypeParamsConformance(lhs, l, r, constraints)
case (UndefinedType(_, _), UndefinedType(typeParameter, _)) =>
if (TypeVariableUnification.unifiableKinds(p, p2)) {
constraints = constraints.withUpper(typeParameter.typeParamId, des1)
result = checkParameterizedType(
typeParameter.typeParameters,
args1, args2, constraints,
visited, checkWeak
)
} else result = ConstraintsResult.Left
case (UndefinedType(_, _), _) => result = unifyHK(p, p2, constraints, Bound.Lower, visited, checkWeak)
case (_, UndefinedType(_, _)) => result = unifyHK(p2, p, constraints, Bound.Upper, visited, checkWeak)
case _ if des1 equiv des2 =>
result =
if (args1.length != args2.length) ConstraintsResult.Left
else {
val tparams = extractTypeParameters(des1)
if (tparams.isEmpty) ConstraintsResult.Left
else checkParameterizedType(tparams, args1, args2, constraints, visited, checkWeak)
}
case (_, t: TypeParameterType) if t.typeParameters.length == p2.typeArguments.length =>
val upper = {
val upper = t.upperType
upper.typeConstructor.getOrElse(upper)
}
val subst = upper match {
case ScTypePolymorphicType(_, tparams) => ScSubstitutor.bind(tparams, p2.typeArguments)
case _ => ScSubstitutor.bind(t.typeParameters, p2.typeArguments)
}
result = conformsInner(ScTypePolymorphicType(p, t.typeParameters), subst(upper), visited, constraints, checkWeak)
case (proj1: ScProjectionType, proj2: ScProjectionType)
if smartEquivalence(proj1.actualElement, proj2.actualElement) =>
val t = conformsInner(proj1, proj2, visited, constraints)
if (t.isLeft) {
result = ConstraintsResult.Left
} else {
constraints = t.constraints
if (args1.length != args2.length) {
result = ConstraintsResult.Left
} else {
proj1.actualElement match {
case td: ScTypeParametersOwner =>
val tps = td.typeParameters.map(TypeParameter(_))
result = checkParameterizedType(tps, args1, args2, constraints, visited, checkWeak)
case td: PsiTypeParameterListOwner =>
val tps = td.getTypeParameters.map(TypeParameter(_))
result = checkParameterizedType(tps, args1, args2, constraints, visited, checkWeak)
case _ =>
result = ConstraintsResult.Left
}
}
}
case _ =>
}
case _ =>
}
if (result != null) {
//sometimes when the above part has failed, we still have to check for alias
if (!result.isRight && r.isAliasType) {
rightVisitor = new ParameterizedAliasVisitor with TypeParameterTypeVisitor {}
r.visitType(rightVisitor)
}
if (result.isRight) return
else l match {
case AliasType(_, Right(lower), _, _) =>
result = conformsInner(lower, r, visited, constraints)
case _ => return
}
return
}
rightVisitor = new ParameterizedAliasVisitor {}
r.visitType(rightVisitor)
if (result != null) return
r match {
case JavaArrayType(rightArg) =>
p match {
case ScalaArrayType(leftArg) =>
result = checkArrayArgs(leftArg, rightArg)
case _ =>
}
case _ =>
}
if (result != null) return
rightVisitor = new AliasDesignatorVisitor with MatchTypeVisitor with CompoundTypeVisitor with ExistentialVisitor
with ProjectionVisitor with OrTypeVisitor {}
r.visitType(rightVisitor)
if (result != null) return
p match {
case AliasType(_, lower, _, _) =>
lower match {
case Right(value) if !value.isNothing =>
result = conformsInner(value, r, visited, constraints)
if (result != null) return
case _ => ()
}
case _ =>
}
rightVisitor = new DesignatorVisitor {}
r.visitType(rightVisitor)
if (result != null) return
rightVisitor = new TypeParameterTypeVisitor {}
r.visitType(rightVisitor)
}