Propagate all annotations during creating simple functional types

^KT-44563 Fixed
This commit is contained in:
Victor Petukhov
2021-01-27 16:27:20 +03:00
parent 5d7dc5fa39
commit 9efac8f68b
13 changed files with 109 additions and 15 deletions
@@ -1457,6 +1457,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
public void testParenthesizedAnnotations() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/parenthesizedAnnotations.kt");
}
@Test
@TestMetadata("propagteAnyAnnotations.kt")
public void testPropagteAnyAnnotations() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/propagteAnyAnnotations.kt");
}
}
@Nested
@@ -58,7 +58,8 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
constructor: TypeConstructorMarker,
arguments: List<TypeArgumentMarker>,
nullable: Boolean,
isExtensionFunction: Boolean
isExtensionFunction: Boolean,
annotations: List<AnnotationMarker>? // TODO: process annotations
): SimpleTypeMarker {
val attributes = if (isExtensionFunction) // TODO: assert correct type constructor
ConeAttributes.WithExtensionFunctionType
@@ -402,6 +402,11 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
return false
}
override fun KotlinTypeMarker.getAnnotations(): List<AnnotationMarker> {
require(this is ConeKotlinType)
return emptyList() // TODO
}
override fun SimpleTypeMarker.isStubType(): Boolean {
return this is StubTypeMarker
}
@@ -10,9 +10,12 @@ import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.FqNameEqualityChecker
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
@@ -237,13 +240,22 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
return IrDynamicTypeImpl(null, emptyList(), Variance.INVARIANT)
}
// TODO: implement taking into account `isExtensionFunction`
override fun createSimpleType(
constructor: TypeConstructorMarker,
arguments: List<TypeArgumentMarker>,
nullable: Boolean,
isExtensionFunction: Boolean
): SimpleTypeMarker = IrSimpleTypeImpl(constructor as IrClassifierSymbol, nullable, arguments.map { it as IrTypeArgument }, emptyList())
isExtensionFunction: Boolean,
annotations: List<AnnotationMarker>?
): SimpleTypeMarker {
val ourAnnotations = annotations?.filterIsInstance<IrConstructorCall>()
require(ourAnnotations?.size == annotations?.size)
return IrSimpleTypeImpl(
constructor as IrClassifierSymbol,
nullable,
arguments.map { it as IrTypeArgument },
ourAnnotations ?: emptyList()
)
}
private fun TypeVariance.convertVariance(): Variance {
return when (this) {
@@ -298,6 +310,11 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
override fun SimpleTypeMarker.isPrimitiveType(): Boolean =
this is IrSimpleType && irTypePredicates_isPrimitiveType()
override fun KotlinTypeMarker.getAnnotations(): List<AnnotationMarker> {
require(this is IrType)
return this.annotations.map { object : AnnotationMarker, IrElement by it {} }
}
override fun createErrorType(debugName: String): SimpleTypeMarker {
TODO("IrTypeSystemContext doesn't support constraint system resolution")
}
@@ -24,6 +24,7 @@ class PostponedArgumentInputTypesResolver(
val parametersFromDeclaration: List<KotlinTypeMarker?>?,
val parametersFromDeclarationOfRelatedLambdas: Set<List<KotlinTypeMarker?>>?,
val parametersFromConstraints: Set<List<TypeWithKind>>?,
val annotations: List<AnnotationMarker>?,
val isExtensionFunction: Boolean,
val isSuspend: Boolean,
val isNullable: Boolean
@@ -57,7 +58,7 @@ class PostponedArgumentInputTypesResolver(
argument: PostponedAtomWithRevisableExpectedType,
postponedArguments: List<PostponedAtomWithRevisableExpectedType>,
variableDependencyProvider: TypeVariableDependencyInformationProvider
): ParameterTypesInfo? = with(resolutionTypeSystemContext) {
): ParameterTypesInfo? {
val expectedType = argument.expectedType ?: return null
val variableWithConstraints = notFixedTypeVariables[expectedType.typeConstructor()] ?: return null
val functionalTypesFromConstraints = findFunctionalTypesInConstraints(variableWithConstraints, variableDependencyProvider)
@@ -76,6 +77,8 @@ class PostponedArgumentInputTypesResolver(
}
}
val annotations = functionalTypesFromConstraints?.map { it.type.getAnnotations() }?.flatten()?.distinct()
// An extension function flag can only come from a declaration of anonymous function: `select({ this + it }, fun Int.(x: Int) = 10)`
val (parameterTypesFromDeclarationOfRelatedLambdas, isThereExtensionFunctionAmongRelatedLambdas) =
getDeclaredParametersFromRelatedLambdas(argument, postponedArguments, variableDependencyProvider)
@@ -96,6 +99,7 @@ class PostponedArgumentInputTypesResolver(
parameterTypesFromDeclaration,
parameterTypesFromDeclarationOfRelatedLambdas,
parameterTypesFromConstraints,
annotations = annotations,
isExtensionFunction = isThereExtensionFunctionAmongRelatedLambdas || extensionFunctionTypePresentInConstraints,
isSuspend = isSuspend,
isNullable = isNullable
@@ -344,7 +348,8 @@ class PostponedArgumentInputTypesResolver(
shouldDiscriminateExtensionFunctionAnnotation -> false
argument.isFunctionExpressionWithReceiver() -> true
else -> parameterTypesInfo.isExtensionFunction
}
},
annotations = parameterTypesInfo.annotations
)
getBuilder().addSubtypeConstraint(
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE)
annotation class Composable
fun bar(p: @Composable ()->Unit) {}
@Composable fun foo() {}
fun main() {
bar(if(true) { { foo() } } else { { } })
}
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE)
annotation class Composable
fun bar(p: @Composable ()->Unit) {}
@Composable fun foo() {}
fun main() {
bar(<!DEBUG_INFO_EXPRESSION_TYPE("@Composable () -> kotlin.Unit")!>if(true) { { foo() } } else { { } }<!>)
}
@@ -0,0 +1,12 @@
package
public fun bar(/*0*/ p: @Composable () -> kotlin.Unit): kotlin.Unit
@Composable public fun foo(): kotlin.Unit
public fun main(): kotlin.Unit
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FUNCTION, AnnotationTarget.TYPE}) public final annotation class Composable : kotlin.Annotation {
public constructor Composable()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -1463,6 +1463,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
public void testParenthesizedAnnotations() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/parenthesizedAnnotations.kt");
}
@Test
@TestMetadata("propagteAnyAnnotations.kt")
public void testPropagteAnyAnnotations() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/propagteAnyAnnotations.kt");
}
}
@Nested