|
|
|
|
@@ -54,11 +54,28 @@ private predicate implicitConversionNonNull(Type fromType, Type toType) {
|
|
|
|
|
fromType instanceof DynamicType // 6.1.8
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Type getTypeArgument(UnboundGenericType ugt, ConstructedType ct, int i, TypeParameter tp) {
|
|
|
|
|
ct.getUnboundGeneric() = ugt and
|
|
|
|
|
/**
|
|
|
|
|
* A generic type. This includes both constructed generic types and unbound
|
|
|
|
|
* generic types (which correspond to constructed generic types where the
|
|
|
|
|
* type arguments equal the type parameters).
|
|
|
|
|
*/
|
|
|
|
|
private class GenericType extends Generic, Type {
|
|
|
|
|
/** Gets the `i`th type argument. */
|
|
|
|
|
Type getTypeArgument(int i) { result = this.getChild(i) }
|
|
|
|
|
|
|
|
|
|
/** Gets the unbound generic type. */
|
|
|
|
|
UnboundGenericType getUnboundGeneric() {
|
|
|
|
|
result = this.(ConstructedType).getUnboundGeneric()
|
|
|
|
|
or
|
|
|
|
|
result = this
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Type getTypeArgument(UnboundGenericType ugt, GenericType gt, int i, TypeParameter tp) {
|
|
|
|
|
gt.getUnboundGeneric() = ugt and
|
|
|
|
|
not ugt instanceof AnonymousClass and
|
|
|
|
|
tp = ugt.getTypeParameter(i) and
|
|
|
|
|
result = ct.getTypeArgument(i)
|
|
|
|
|
result = gt.getTypeArgument(i)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** A type that is an element type of an array type. */
|
|
|
|
|
@@ -68,7 +85,7 @@ private class ArrayElementType extends Type {
|
|
|
|
|
|
|
|
|
|
/** A type that is an argument in a constructed type. */
|
|
|
|
|
private class TypeArgument extends Type {
|
|
|
|
|
TypeArgument() { this = any(ConstructedType ct).getATypeArgument() }
|
|
|
|
|
TypeArgument() { this = any(GenericType gt).getTypeArgument(_) }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -95,8 +112,7 @@ private module Identity {
|
|
|
|
|
|
|
|
|
|
private class IdentityConvertibleArrayType extends IdentityConvertibleType, ArrayType { }
|
|
|
|
|
|
|
|
|
|
private class IdentityConvertibleConstructedType extends IdentityConvertibleType, ConstructedType {
|
|
|
|
|
}
|
|
|
|
|
private class IdentityConvertibleGenericType extends IdentityConvertibleType, GenericType { }
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A type is (strictly) identity convertible if it contains at least one `object`
|
|
|
|
|
@@ -109,7 +125,7 @@ private module Identity {
|
|
|
|
|
or
|
|
|
|
|
isIdentityConvertible(t.(ArrayType).getElementType())
|
|
|
|
|
or
|
|
|
|
|
isIdentityConvertible(t.(ConstructedType).getATypeArgument())
|
|
|
|
|
isIdentityConvertible(t.(GenericType).getTypeArgument(_))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
predicate convIdentityStrict(IdentityConvertibleType fromType, IdentityConvertibleType toType) {
|
|
|
|
|
@@ -119,7 +135,7 @@ private module Identity {
|
|
|
|
|
or
|
|
|
|
|
convIdentityStrictArrayType(fromType, toType)
|
|
|
|
|
or
|
|
|
|
|
convIdentityStrictConstructedType(fromType, toType)
|
|
|
|
|
convIdentityStrictGenericType(fromType, toType)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private predicate convIdentityObjectDynamic(ObjectType fromType, DynamicType toType) { any() }
|
|
|
|
|
@@ -151,7 +167,7 @@ private module Identity {
|
|
|
|
|
*/
|
|
|
|
|
private int getTypeArgumentCount(UnboundGenericType ugt, int i) {
|
|
|
|
|
result = strictcount(Type arg |
|
|
|
|
|
exists(IdentityConvertibleConstructedType ct | ct.getUnboundGeneric() = ugt |
|
|
|
|
|
exists(IdentityConvertibleGenericType ct | ct.getUnboundGeneric() = ugt |
|
|
|
|
|
arg = ct.getTypeArgument(i)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
@@ -162,9 +178,7 @@ private module Identity {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Gets the 'i'th type argument, ranked by size, of constructed type `t`. */
|
|
|
|
|
private Type getTypeArgumentRanked(
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleConstructedType t, int i
|
|
|
|
|
) {
|
|
|
|
|
private Type getTypeArgumentRanked(UnboundGenericType ugt, IdentityConvertibleGenericType t, int i) {
|
|
|
|
|
result = getTypeArgument(ugt, t, rnk(ugt, i), _)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -207,8 +221,8 @@ private module Identity {
|
|
|
|
|
|
|
|
|
|
pragma[nomagic]
|
|
|
|
|
private predicate convIdentitySingle0(
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleConstructedType toType,
|
|
|
|
|
TypeArgument fromTypeArgument, TypeArgument toTypeArgument
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleGenericType toType, TypeArgument fromTypeArgument,
|
|
|
|
|
TypeArgument toTypeArgument
|
|
|
|
|
) {
|
|
|
|
|
convTypeArgumentsSameUnbound(ugt, fromTypeArgument, toTypeArgument, 0) and
|
|
|
|
|
toTypeArgument = getTypeArgumentRanked(ugt, toType, 0) and
|
|
|
|
|
@@ -220,8 +234,8 @@ private module Identity {
|
|
|
|
|
* convertible, and the number of type arguments is 1.
|
|
|
|
|
*/
|
|
|
|
|
predicate convIdentitySingle(
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleConstructedType fromType,
|
|
|
|
|
IdentityConvertibleConstructedType toType
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleGenericType fromType,
|
|
|
|
|
IdentityConvertibleGenericType toType
|
|
|
|
|
) {
|
|
|
|
|
exists(TypeArgument fromTypeArgument, TypeArgument toTypeArgument |
|
|
|
|
|
convIdentitySingle0(ugt, toType, fromTypeArgument, toTypeArgument)
|
|
|
|
|
@@ -232,8 +246,8 @@ private module Identity {
|
|
|
|
|
|
|
|
|
|
pragma[nomagic]
|
|
|
|
|
private predicate convIdentityMultiple01Aux0(
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleConstructedType toType,
|
|
|
|
|
TypeArgument fromTypeArgument0, TypeArgument toTypeArgument0, TypeArgument toTypeArgument1
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleGenericType toType, TypeArgument fromTypeArgument0,
|
|
|
|
|
TypeArgument toTypeArgument0, TypeArgument toTypeArgument1
|
|
|
|
|
) {
|
|
|
|
|
convTypeArgumentsSameUnbound(ugt, fromTypeArgument0, toTypeArgument0, 0) and
|
|
|
|
|
toTypeArgument0 = getTypeArgumentRanked(ugt, toType, 0) and
|
|
|
|
|
@@ -242,8 +256,8 @@ private module Identity {
|
|
|
|
|
|
|
|
|
|
pragma[nomagic]
|
|
|
|
|
private predicate convIdentityMultiple01Aux1(
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleConstructedType fromType,
|
|
|
|
|
TypeArgument fromTypeArgument0, TypeArgument fromTypeArgument1, TypeArgument toTypeArgument1
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleGenericType fromType, TypeArgument fromTypeArgument0,
|
|
|
|
|
TypeArgument fromTypeArgument1, TypeArgument toTypeArgument1
|
|
|
|
|
) {
|
|
|
|
|
convTypeArgumentsSameUnbound(ugt, fromTypeArgument1, toTypeArgument1, 1) and
|
|
|
|
|
fromTypeArgument0 = getTypeArgumentRanked(ugt, fromType, 0) and
|
|
|
|
|
@@ -255,8 +269,8 @@ private module Identity {
|
|
|
|
|
* are identity convertible.
|
|
|
|
|
*/
|
|
|
|
|
private predicate convIdentityMultiple01(
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleConstructedType fromType,
|
|
|
|
|
IdentityConvertibleConstructedType toType
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleGenericType fromType,
|
|
|
|
|
IdentityConvertibleGenericType toType
|
|
|
|
|
) {
|
|
|
|
|
exists(
|
|
|
|
|
Type fromTypeArgument0, Type toTypeArgument0, Type fromTypeArgument1, Type toTypeArgument1
|
|
|
|
|
@@ -270,7 +284,7 @@ private module Identity {
|
|
|
|
|
|
|
|
|
|
pragma[nomagic]
|
|
|
|
|
private predicate convIdentityMultiple2Aux(
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleConstructedType toType, int i,
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleGenericType toType, int i,
|
|
|
|
|
TypeArgument fromTypeArgument, TypeArgument toTypeArgument
|
|
|
|
|
) {
|
|
|
|
|
convTypeArgumentsSameUnbound(ugt, fromTypeArgument, toTypeArgument, i) and
|
|
|
|
|
@@ -279,8 +293,8 @@ private module Identity {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private predicate convIdentityMultiple2(
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleConstructedType fromType,
|
|
|
|
|
IdentityConvertibleConstructedType toType, int i
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleGenericType fromType,
|
|
|
|
|
IdentityConvertibleGenericType toType, int i
|
|
|
|
|
) {
|
|
|
|
|
exists(TypeArgument fromTypeArgument, TypeArgument toTypeArgument |
|
|
|
|
|
convIdentityMultiple2Aux(ugt, toType, i, fromTypeArgument, toTypeArgument)
|
|
|
|
|
@@ -295,8 +309,8 @@ private module Identity {
|
|
|
|
|
*/
|
|
|
|
|
pragma[nomagic]
|
|
|
|
|
predicate convIdentityMultiple(
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleConstructedType fromType,
|
|
|
|
|
IdentityConvertibleConstructedType toType, int i
|
|
|
|
|
UnboundGenericType ugt, IdentityConvertibleGenericType fromType,
|
|
|
|
|
IdentityConvertibleGenericType toType, int i
|
|
|
|
|
) {
|
|
|
|
|
convIdentityMultiple01(ugt, fromType, toType) and i = 1
|
|
|
|
|
or
|
|
|
|
|
@@ -304,8 +318,8 @@ private module Identity {
|
|
|
|
|
convIdentityMultiple2(ugt, fromType, toType, i)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private predicate convIdentityStrictConstructedType(
|
|
|
|
|
IdentityConvertibleConstructedType fromType, IdentityConvertibleConstructedType toType
|
|
|
|
|
private predicate convIdentityStrictGenericType(
|
|
|
|
|
IdentityConvertibleGenericType fromType, IdentityConvertibleGenericType toType
|
|
|
|
|
) {
|
|
|
|
|
// Semantically equivalent with
|
|
|
|
|
// ```
|
|
|
|
|
@@ -730,7 +744,7 @@ predicate convConversionOperator(Type fromType, Type toType) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 13.1.3.2: Variance conversion. */
|
|
|
|
|
private predicate convVariance(ConstructedType fromType, ConstructedType toType) {
|
|
|
|
|
private predicate convVariance(GenericType fromType, GenericType toType) {
|
|
|
|
|
// Semantically equivalent with
|
|
|
|
|
// ```
|
|
|
|
|
// ugt = fromType.getUnboundGeneric()
|
|
|
|
|
@@ -758,34 +772,14 @@ private predicate convVariance(ConstructedType fromType, ConstructedType toType)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private module Variance {
|
|
|
|
|
/**
|
|
|
|
|
* Holds if constructed type `ct` is potentially variance convertible to
|
|
|
|
|
* or from another constructed type, as a result of the `i`th type
|
|
|
|
|
* argument being potentially convertible.
|
|
|
|
|
*/
|
|
|
|
|
private predicate isVarianceConvertible(ConstructedType ct, int i) {
|
|
|
|
|
exists(TypeParameter tp, Type t |
|
|
|
|
|
tp = ct.getUnboundGeneric().getTypeParameter(i) and
|
|
|
|
|
t = ct.getTypeArgument(i)
|
|
|
|
|
|
|
|
|
|
|
// Anything that is not a type parameter is potentially convertible
|
|
|
|
|
// to/from another type; if the `i`th type parameter is invariant,
|
|
|
|
|
// `t` must be strictly identity convertible
|
|
|
|
|
not t instanceof TypeParameter and
|
|
|
|
|
(tp.isIn() or tp.isOut() or Identity::convIdentityStrict(t, _))
|
|
|
|
|
or
|
|
|
|
|
exists(TypeParameter s | s = t |
|
|
|
|
|
// A type parameter with implicit reference conversion
|
|
|
|
|
exists(convTypeParameterBase(s)) and s.isRefType() and tp.isOut()
|
|
|
|
|
private class VarianceConvertibleGenericType extends GenericType {
|
|
|
|
|
VarianceConvertibleGenericType() {
|
|
|
|
|
exists(TypeParameter tp | tp = this.getUnboundGeneric().getATypeParameter() |
|
|
|
|
|
tp.isIn()
|
|
|
|
|
or
|
|
|
|
|
// A type parameter convertible from another type parameter
|
|
|
|
|
exists(TypeParameter u | s = convTypeParameterBase(u) and u.isRefType() and tp.isIn())
|
|
|
|
|
tp.isOut()
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class VarianceConvertibleConstructedType extends ConstructedType {
|
|
|
|
|
VarianceConvertibleConstructedType() { isVarianceConvertible(this, _) }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -794,8 +788,8 @@ private module Variance {
|
|
|
|
|
*/
|
|
|
|
|
private int getTypeArgumentCount(UnboundGenericType ugt, int i) {
|
|
|
|
|
result = strictcount(Type arg |
|
|
|
|
|
exists(VarianceConvertibleConstructedType ct | ct.getUnboundGeneric() = ugt |
|
|
|
|
|
arg = ct.getTypeArgument(i)
|
|
|
|
|
exists(VarianceConvertibleGenericType gt | gt.getUnboundGeneric() = ugt |
|
|
|
|
|
arg = gt.getTypeArgument(i)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
@@ -806,7 +800,7 @@ private module Variance {
|
|
|
|
|
|
|
|
|
|
/** Gets the 'i'th type argument, ranked by size, of constructed type `t`. */
|
|
|
|
|
private Type getTypeArgumentRanked(
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleConstructedType t, int i, TypeParameter tp
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleGenericType t, int i, TypeParameter tp
|
|
|
|
|
) {
|
|
|
|
|
result = getTypeArgument(ugt, t, rnk(ugt, i), tp)
|
|
|
|
|
}
|
|
|
|
|
@@ -889,8 +883,8 @@ private module Variance {
|
|
|
|
|
|
|
|
|
|
pragma[nomagic]
|
|
|
|
|
private predicate convVarianceSingle0(
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleConstructedType toType,
|
|
|
|
|
TypeArgument fromTypeArgument, TypeArgument toTypeArgument
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleGenericType toType, TypeArgument fromTypeArgument,
|
|
|
|
|
TypeArgument toTypeArgument
|
|
|
|
|
) {
|
|
|
|
|
convTypeArgumentsSameUnbound(ugt, fromTypeArgument, toTypeArgument, 0) and
|
|
|
|
|
toTypeArgument = getTypeArgumentRanked(ugt, toType, 0, _) and
|
|
|
|
|
@@ -902,8 +896,8 @@ private module Variance {
|
|
|
|
|
* convertible, and the number of type arguments is 1.
|
|
|
|
|
*/
|
|
|
|
|
predicate convVarianceSingle(
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleConstructedType fromType,
|
|
|
|
|
VarianceConvertibleConstructedType toType
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleGenericType fromType,
|
|
|
|
|
VarianceConvertibleGenericType toType
|
|
|
|
|
) {
|
|
|
|
|
exists(TypeArgument fromTypeArgument, TypeArgument toTypeArgument |
|
|
|
|
|
convVarianceSingle0(ugt, toType, fromTypeArgument, toTypeArgument)
|
|
|
|
|
@@ -914,8 +908,8 @@ private module Variance {
|
|
|
|
|
|
|
|
|
|
pragma[nomagic]
|
|
|
|
|
private predicate convVarianceMultiple01Aux0(
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleConstructedType toType,
|
|
|
|
|
TypeArgument fromTypeArgument0, TypeArgument toTypeArgument0, TypeArgument toTypeArgument1
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleGenericType toType, TypeArgument fromTypeArgument0,
|
|
|
|
|
TypeArgument toTypeArgument0, TypeArgument toTypeArgument1
|
|
|
|
|
) {
|
|
|
|
|
convTypeArgumentsSameUnbound(ugt, fromTypeArgument0, toTypeArgument0, 0) and
|
|
|
|
|
toTypeArgument0 = getTypeArgumentRanked(ugt, toType, 0, _) and
|
|
|
|
|
@@ -924,8 +918,8 @@ private module Variance {
|
|
|
|
|
|
|
|
|
|
pragma[nomagic]
|
|
|
|
|
private predicate convVarianceMultiple01Aux1(
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleConstructedType fromType,
|
|
|
|
|
TypeArgument fromTypeArgument0, TypeArgument fromTypeArgument1, TypeArgument toTypeArgument1
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleGenericType fromType, TypeArgument fromTypeArgument0,
|
|
|
|
|
TypeArgument fromTypeArgument1, TypeArgument toTypeArgument1
|
|
|
|
|
) {
|
|
|
|
|
convTypeArgumentsSameUnbound(ugt, fromTypeArgument1, toTypeArgument1, 1) and
|
|
|
|
|
fromTypeArgument0 = getTypeArgumentRanked(ugt, fromType, 0, _) and
|
|
|
|
|
@@ -937,8 +931,8 @@ private module Variance {
|
|
|
|
|
* are variance convertible.
|
|
|
|
|
*/
|
|
|
|
|
private predicate convVarianceMultiple01(
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleConstructedType fromType,
|
|
|
|
|
VarianceConvertibleConstructedType toType
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleGenericType fromType,
|
|
|
|
|
VarianceConvertibleGenericType toType
|
|
|
|
|
) {
|
|
|
|
|
exists(
|
|
|
|
|
TypeArgument fromTypeArgument0, TypeArgument toTypeArgument0, TypeArgument fromTypeArgument1,
|
|
|
|
|
@@ -953,7 +947,7 @@ private module Variance {
|
|
|
|
|
|
|
|
|
|
pragma[nomagic]
|
|
|
|
|
private predicate convVarianceMultiple2Aux(
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleConstructedType toType, int i,
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleGenericType toType, int i,
|
|
|
|
|
TypeArgument fromTypeArgument, TypeArgument toTypeArgument
|
|
|
|
|
) {
|
|
|
|
|
convTypeArgumentsSameUnbound(ugt, fromTypeArgument, toTypeArgument, i) and
|
|
|
|
|
@@ -962,8 +956,8 @@ private module Variance {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private predicate convVarianceMultiple2(
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleConstructedType fromType,
|
|
|
|
|
VarianceConvertibleConstructedType toType, int i
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleGenericType fromType,
|
|
|
|
|
VarianceConvertibleGenericType toType, int i
|
|
|
|
|
) {
|
|
|
|
|
exists(TypeArgument fromTypeArgument, TypeArgument toTypeArgument |
|
|
|
|
|
convVarianceMultiple2Aux(ugt, toType, i, fromTypeArgument, toTypeArgument)
|
|
|
|
|
@@ -978,8 +972,8 @@ private module Variance {
|
|
|
|
|
*/
|
|
|
|
|
pragma[nomagic]
|
|
|
|
|
predicate convVarianceMultiple(
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleConstructedType fromType,
|
|
|
|
|
VarianceConvertibleConstructedType toType, int i
|
|
|
|
|
UnboundGenericType ugt, VarianceConvertibleGenericType fromType,
|
|
|
|
|
VarianceConvertibleGenericType toType, int i
|
|
|
|
|
) {
|
|
|
|
|
convVarianceMultiple01(ugt, fromType, toType) and i = 1
|
|
|
|
|
or
|
|
|
|
|
|