mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Kotlin: Revert type erasure within $default functions
This imprecise implementation turned out to cause linkage errors, e.g. when type variables in the signatures of member methods were inappropriately erased. For the time being we accept that $default methods despite having erased signatures in keeping with their JVM representation can contain expressions whose types make reference to their surrounding function or class' type variables, even though they should be out of scope since $default methods are static and don't have type parameters, and need to cope with the inconsistency in QL.
This commit is contained in:
@@ -1194,8 +1194,6 @@ open class KotlinFileExtractor(
|
||||
// n + o'th parameter, where `o` is the parameter offset caused by adding any dispatch receiver to the parameter list.
|
||||
// Note we don't need to add the extension receiver here because `useValueParameter` always assumes an extension receiver
|
||||
// will be prepended if one exists.
|
||||
// Note we have to get the real function ID here before entering this block, because otherwise we'll misrepresent the signature of a generic
|
||||
// function without its type variables -- for example, trying to address `f(T, List<T>)` as `f(Object, List)`.
|
||||
val realFunctionId = useFunction<DbCallable>(f)
|
||||
DeclarationStackAdjuster(f, OverriddenFunctionAttributes(id, id, locId, nonSyntheticParams, typeParameters = listOf(), isStatic = true)).use {
|
||||
val realParamsVarId = getValueParameterLabel(id, parameterTypes.size - 2)
|
||||
|
||||
@@ -643,26 +643,6 @@ open class KotlinUsesExtractor(
|
||||
RETURN, GENERIC_ARGUMENT, OTHER
|
||||
}
|
||||
|
||||
private fun isOnDeclarationStackWithoutTypeParameters(f: IrFunction) =
|
||||
this is KotlinFileExtractor && this.declarationStack.findOverriddenAttributes(f)?.typeParameters?.isEmpty() == true
|
||||
|
||||
private fun isStaticFunctionOnStackBeforeClass(c: IrClass) =
|
||||
this is KotlinFileExtractor && (this.declarationStack.findFirst { it.first == c || it.second?.isStatic == true })?.second?.isStatic == true
|
||||
|
||||
private fun isUnavailableTypeParameter(t: IrType) =
|
||||
t is IrSimpleType && t.classifier.owner.let { owner ->
|
||||
owner is IrTypeParameter && owner.parent.let { parent ->
|
||||
when (parent) {
|
||||
is IrFunction -> isOnDeclarationStackWithoutTypeParameters(parent)
|
||||
is IrClass -> isStaticFunctionOnStackBeforeClass(parent)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun argIsUnavailableTypeParameter(t: IrTypeArgument) =
|
||||
t is IrTypeProjection && isUnavailableTypeParameter(t.type)
|
||||
|
||||
private fun useSimpleType(s: IrSimpleType, context: TypeContext): TypeResults {
|
||||
if (s.abbreviation != null) {
|
||||
// TODO: Extract this information
|
||||
@@ -735,13 +715,11 @@ open class KotlinUsesExtractor(
|
||||
}
|
||||
|
||||
owner is IrClass -> {
|
||||
val args = if (s.isRawType() || s.arguments.any { argIsUnavailableTypeParameter(it) }) null else s.arguments
|
||||
val args = if (s.isRawType()) null else s.arguments
|
||||
|
||||
return useSimpleTypeClass(owner, args, s.isNullable())
|
||||
}
|
||||
owner is IrTypeParameter -> {
|
||||
if (isUnavailableTypeParameter(s))
|
||||
return useType(erase(s), context)
|
||||
val javaResult = useTypeParameter(owner)
|
||||
val aClassId = makeClass("kotlin", "TypeParam") // TODO: Wrong
|
||||
val kotlinResult = if (true) TypeResult(fakeKotlinType(), "TODO", "TODO") else
|
||||
@@ -1474,7 +1452,13 @@ open class KotlinUsesExtractor(
|
||||
param.parent.let {
|
||||
(it as? IrFunction)?.let { fn ->
|
||||
if (this is KotlinFileExtractor)
|
||||
this.declarationStack.findOverriddenAttributes(fn)?.id
|
||||
this.declarationStack.findOverriddenAttributes(fn)?.takeUnless {
|
||||
// When extracting the `static fun f$default(...)` that accompanies `fun <T> f(val x: T? = defaultExpr, ...)`,
|
||||
// `f$default` has no type parameters, and so there is no `f$default::T` to refer to.
|
||||
// We have no good way to extract references to `T` in `defaultExpr`, so we just fall back on describing it
|
||||
// in terms of `f::T`, even though that type variable ought to be out of scope here.
|
||||
attribs -> attribs.typeParameters?.isEmpty() == true
|
||||
}?.id
|
||||
else
|
||||
null
|
||||
} ?:
|
||||
|
||||
Reference in New Issue
Block a user