Propagate all annotations during creating simple functional types
^KT-44563 Fixed
This commit is contained in:
+6
@@ -1457,6 +1457,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
public void testParenthesizedAnnotations() throws Exception {
|
public void testParenthesizedAnnotations() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/parenthesizedAnnotations.kt");
|
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
|
@Nested
|
||||||
|
|||||||
@@ -58,7 +58,8 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
|||||||
constructor: TypeConstructorMarker,
|
constructor: TypeConstructorMarker,
|
||||||
arguments: List<TypeArgumentMarker>,
|
arguments: List<TypeArgumentMarker>,
|
||||||
nullable: Boolean,
|
nullable: Boolean,
|
||||||
isExtensionFunction: Boolean
|
isExtensionFunction: Boolean,
|
||||||
|
annotations: List<AnnotationMarker>? // TODO: process annotations
|
||||||
): SimpleTypeMarker {
|
): SimpleTypeMarker {
|
||||||
val attributes = if (isExtensionFunction) // TODO: assert correct type constructor
|
val attributes = if (isExtensionFunction) // TODO: assert correct type constructor
|
||||||
ConeAttributes.WithExtensionFunctionType
|
ConeAttributes.WithExtensionFunctionType
|
||||||
|
|||||||
@@ -402,6 +402,11 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.getAnnotations(): List<AnnotationMarker> {
|
||||||
|
require(this is ConeKotlinType)
|
||||||
|
return emptyList() // TODO
|
||||||
|
}
|
||||||
|
|
||||||
override fun SimpleTypeMarker.isStubType(): Boolean {
|
override fun SimpleTypeMarker.isStubType(): Boolean {
|
||||||
return this is StubTypeMarker
|
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.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
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.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
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.FqNameEqualityChecker
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||||
@@ -237,13 +240,22 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
|
|||||||
return IrDynamicTypeImpl(null, emptyList(), Variance.INVARIANT)
|
return IrDynamicTypeImpl(null, emptyList(), Variance.INVARIANT)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement taking into account `isExtensionFunction`
|
|
||||||
override fun createSimpleType(
|
override fun createSimpleType(
|
||||||
constructor: TypeConstructorMarker,
|
constructor: TypeConstructorMarker,
|
||||||
arguments: List<TypeArgumentMarker>,
|
arguments: List<TypeArgumentMarker>,
|
||||||
nullable: Boolean,
|
nullable: Boolean,
|
||||||
isExtensionFunction: Boolean
|
isExtensionFunction: Boolean,
|
||||||
): SimpleTypeMarker = IrSimpleTypeImpl(constructor as IrClassifierSymbol, nullable, arguments.map { it as IrTypeArgument }, emptyList())
|
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 {
|
private fun TypeVariance.convertVariance(): Variance {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
@@ -298,6 +310,11 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
|
|||||||
override fun SimpleTypeMarker.isPrimitiveType(): Boolean =
|
override fun SimpleTypeMarker.isPrimitiveType(): Boolean =
|
||||||
this is IrSimpleType && irTypePredicates_isPrimitiveType()
|
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 {
|
override fun createErrorType(debugName: String): SimpleTypeMarker {
|
||||||
TODO("IrTypeSystemContext doesn't support constraint system resolution")
|
TODO("IrTypeSystemContext doesn't support constraint system resolution")
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-2
@@ -24,6 +24,7 @@ class PostponedArgumentInputTypesResolver(
|
|||||||
val parametersFromDeclaration: List<KotlinTypeMarker?>?,
|
val parametersFromDeclaration: List<KotlinTypeMarker?>?,
|
||||||
val parametersFromDeclarationOfRelatedLambdas: Set<List<KotlinTypeMarker?>>?,
|
val parametersFromDeclarationOfRelatedLambdas: Set<List<KotlinTypeMarker?>>?,
|
||||||
val parametersFromConstraints: Set<List<TypeWithKind>>?,
|
val parametersFromConstraints: Set<List<TypeWithKind>>?,
|
||||||
|
val annotations: List<AnnotationMarker>?,
|
||||||
val isExtensionFunction: Boolean,
|
val isExtensionFunction: Boolean,
|
||||||
val isSuspend: Boolean,
|
val isSuspend: Boolean,
|
||||||
val isNullable: Boolean
|
val isNullable: Boolean
|
||||||
@@ -57,7 +58,7 @@ class PostponedArgumentInputTypesResolver(
|
|||||||
argument: PostponedAtomWithRevisableExpectedType,
|
argument: PostponedAtomWithRevisableExpectedType,
|
||||||
postponedArguments: List<PostponedAtomWithRevisableExpectedType>,
|
postponedArguments: List<PostponedAtomWithRevisableExpectedType>,
|
||||||
variableDependencyProvider: TypeVariableDependencyInformationProvider
|
variableDependencyProvider: TypeVariableDependencyInformationProvider
|
||||||
): ParameterTypesInfo? = with(resolutionTypeSystemContext) {
|
): ParameterTypesInfo? {
|
||||||
val expectedType = argument.expectedType ?: return null
|
val expectedType = argument.expectedType ?: return null
|
||||||
val variableWithConstraints = notFixedTypeVariables[expectedType.typeConstructor()] ?: return null
|
val variableWithConstraints = notFixedTypeVariables[expectedType.typeConstructor()] ?: return null
|
||||||
val functionalTypesFromConstraints = findFunctionalTypesInConstraints(variableWithConstraints, variableDependencyProvider)
|
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)`
|
// An extension function flag can only come from a declaration of anonymous function: `select({ this + it }, fun Int.(x: Int) = 10)`
|
||||||
val (parameterTypesFromDeclarationOfRelatedLambdas, isThereExtensionFunctionAmongRelatedLambdas) =
|
val (parameterTypesFromDeclarationOfRelatedLambdas, isThereExtensionFunctionAmongRelatedLambdas) =
|
||||||
getDeclaredParametersFromRelatedLambdas(argument, postponedArguments, variableDependencyProvider)
|
getDeclaredParametersFromRelatedLambdas(argument, postponedArguments, variableDependencyProvider)
|
||||||
@@ -96,6 +99,7 @@ class PostponedArgumentInputTypesResolver(
|
|||||||
parameterTypesFromDeclaration,
|
parameterTypesFromDeclaration,
|
||||||
parameterTypesFromDeclarationOfRelatedLambdas,
|
parameterTypesFromDeclarationOfRelatedLambdas,
|
||||||
parameterTypesFromConstraints,
|
parameterTypesFromConstraints,
|
||||||
|
annotations = annotations,
|
||||||
isExtensionFunction = isThereExtensionFunctionAmongRelatedLambdas || extensionFunctionTypePresentInConstraints,
|
isExtensionFunction = isThereExtensionFunctionAmongRelatedLambdas || extensionFunctionTypePresentInConstraints,
|
||||||
isSuspend = isSuspend,
|
isSuspend = isSuspend,
|
||||||
isNullable = isNullable
|
isNullable = isNullable
|
||||||
@@ -344,7 +348,8 @@ class PostponedArgumentInputTypesResolver(
|
|||||||
shouldDiscriminateExtensionFunctionAnnotation -> false
|
shouldDiscriminateExtensionFunctionAnnotation -> false
|
||||||
argument.isFunctionExpressionWithReceiver() -> true
|
argument.isFunctionExpressionWithReceiver() -> true
|
||||||
else -> parameterTypesInfo.isExtensionFunction
|
else -> parameterTypesInfo.isExtensionFunction
|
||||||
}
|
},
|
||||||
|
annotations = parameterTypesInfo.annotations
|
||||||
)
|
)
|
||||||
|
|
||||||
getBuilder().addSubtypeConstraint(
|
getBuilder().addSubtypeConstraint(
|
||||||
|
|||||||
Vendored
+12
@@ -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 { { } })
|
||||||
|
}
|
||||||
+12
@@ -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 { { } }<!>)
|
||||||
|
}
|
||||||
+12
@@ -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
|
||||||
|
}
|
||||||
Generated
+6
@@ -1463,6 +1463,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
public void testParenthesizedAnnotations() throws Exception {
|
public void testParenthesizedAnnotations() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/annotations/functionalTypes/parenthesizedAnnotations.kt");
|
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
|
@Nested
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ interface IntersectionTypeConstructorMarker : TypeConstructorMarker
|
|||||||
|
|
||||||
interface TypeSubstitutorMarker
|
interface TypeSubstitutorMarker
|
||||||
|
|
||||||
|
interface AnnotationMarker
|
||||||
|
|
||||||
enum class TypeVariance(val presentation: String) {
|
enum class TypeVariance(val presentation: String) {
|
||||||
IN("in"),
|
IN("in"),
|
||||||
@@ -73,7 +74,8 @@ interface TypeSystemTypeFactoryContext {
|
|||||||
constructor: TypeConstructorMarker,
|
constructor: TypeConstructorMarker,
|
||||||
arguments: List<TypeArgumentMarker>,
|
arguments: List<TypeArgumentMarker>,
|
||||||
nullable: Boolean,
|
nullable: Boolean,
|
||||||
isExtensionFunction: Boolean = false
|
isExtensionFunction: Boolean = false,
|
||||||
|
annotations: List<AnnotationMarker>? = null
|
||||||
): SimpleTypeMarker
|
): SimpleTypeMarker
|
||||||
|
|
||||||
fun createTypeArgument(type: KotlinTypeMarker, variance: TypeVariance): TypeArgumentMarker
|
fun createTypeArgument(type: KotlinTypeMarker, variance: TypeVariance): TypeArgumentMarker
|
||||||
@@ -391,6 +393,8 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
|
|||||||
fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker
|
fun prepareType(type: KotlinTypeMarker): KotlinTypeMarker
|
||||||
|
|
||||||
fun SimpleTypeMarker.isPrimitiveType(): Boolean
|
fun SimpleTypeMarker.isPrimitiveType(): Boolean
|
||||||
|
|
||||||
|
fun KotlinTypeMarker.getAnnotations(): List<AnnotationMarker>
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class CaptureStatus {
|
enum class CaptureStatus {
|
||||||
|
|||||||
+2
-1
@@ -25,8 +25,9 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
|||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.getAbbreviation
|
import org.jetbrains.kotlin.types.getAbbreviation
|
||||||
|
import org.jetbrains.kotlin.types.model.AnnotationMarker
|
||||||
|
|
||||||
interface AnnotationDescriptor {
|
interface AnnotationDescriptor : AnnotationMarker {
|
||||||
val type: KotlinType
|
val type: KotlinType
|
||||||
|
|
||||||
val fqName: FqName?
|
val fqName: FqName?
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.descriptors.annotations
|
package org.jetbrains.kotlin.descriptors.annotations
|
||||||
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.types.model.AnnotationMarker
|
||||||
|
|
||||||
interface Annotated {
|
interface Annotated {
|
||||||
val annotations: Annotations
|
val annotations: Annotations
|
||||||
|
|||||||
+19
-7
@@ -29,8 +29,6 @@ import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||||
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.contracts.contract
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isSignedOrUnsignedNumberType as classicIsSignedOrUnsignedNumberType
|
import org.jetbrains.kotlin.types.typeUtil.isSignedOrUnsignedNumberType as classicIsSignedOrUnsignedNumberType
|
||||||
|
|
||||||
interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSystemCommonBackendContext {
|
interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSystemCommonBackendContext {
|
||||||
@@ -437,16 +435,25 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
|||||||
constructor: TypeConstructorMarker,
|
constructor: TypeConstructorMarker,
|
||||||
arguments: List<TypeArgumentMarker>,
|
arguments: List<TypeArgumentMarker>,
|
||||||
nullable: Boolean,
|
nullable: Boolean,
|
||||||
isExtensionFunction: Boolean
|
isExtensionFunction: Boolean,
|
||||||
|
annotations: List<AnnotationMarker>?
|
||||||
): SimpleTypeMarker {
|
): SimpleTypeMarker {
|
||||||
require(constructor is TypeConstructor, constructor::errorMessage)
|
require(constructor is TypeConstructor, constructor::errorMessage)
|
||||||
|
|
||||||
val annotations = if (isExtensionFunction) {
|
val ourAnnotations = annotations?.filterIsInstance<AnnotationDescriptor>()
|
||||||
Annotations.create(listOf(BuiltInAnnotationDescriptor(builtIns, FqNames.extensionFunctionType, emptyMap())))
|
require(ourAnnotations?.size == annotations?.size)
|
||||||
} else Annotations.EMPTY
|
|
||||||
|
fun createExtensionFunctionAnnotation() = BuiltInAnnotationDescriptor(builtIns, FqNames.extensionFunctionType, emptyMap())
|
||||||
|
|
||||||
|
val resultingAnnotations = when {
|
||||||
|
ourAnnotations.isNullOrEmpty() && isExtensionFunction -> Annotations.create(listOf(createExtensionFunctionAnnotation()))
|
||||||
|
!ourAnnotations.isNullOrEmpty() && !isExtensionFunction -> Annotations.create(ourAnnotations.filter { it.fqName != FqNames.extensionFunctionType })
|
||||||
|
!ourAnnotations.isNullOrEmpty() && isExtensionFunction -> Annotations.create(ourAnnotations + createExtensionFunctionAnnotation())
|
||||||
|
else -> Annotations.EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return KotlinTypeFactory.simpleType(annotations, constructor, arguments as List<TypeProjection>, nullable)
|
return KotlinTypeFactory.simpleType(resultingAnnotations, constructor, arguments as List<TypeProjection>, nullable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createTypeArgument(type: KotlinTypeMarker, variance: TypeVariance): TypeArgumentMarker {
|
override fun createTypeArgument(type: KotlinTypeMarker, variance: TypeVariance): TypeArgumentMarker {
|
||||||
@@ -557,6 +564,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
|||||||
return KotlinBuiltIns.isPrimitiveType(this)
|
return KotlinBuiltIns.isPrimitiveType(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun KotlinTypeMarker.getAnnotations(): List<AnnotationMarker> {
|
||||||
|
require(this is KotlinType, this::errorMessage)
|
||||||
|
return this.annotations.toList()
|
||||||
|
}
|
||||||
|
|
||||||
override fun captureFromExpression(type: KotlinTypeMarker): KotlinTypeMarker? {
|
override fun captureFromExpression(type: KotlinTypeMarker): KotlinTypeMarker? {
|
||||||
return captureFromExpressionInternal(type as UnwrappedType)
|
return captureFromExpressionInternal(type as UnwrappedType)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user