diff --git a/analysis/low-level-api-fir/testdata/lazyResolve/typeParameterBounds.kt b/analysis/low-level-api-fir/testdata/lazyResolve/typeParameterBounds.kt new file mode 100644 index 00000000000..019163b080f --- /dev/null +++ b/analysis/low-level-api-fir/testdata/lazyResolve/typeParameterBounds.kt @@ -0,0 +1,8 @@ +fun resolveMe(foo: Foo) { + foo.util() +} + +interface Foo +interface Bar + +fun > F.util(): B = null!! \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/lazyResolve/typeParameterBounds.txt b/analysis/low-level-api-fir/testdata/lazyResolve/typeParameterBounds.txt new file mode 100644 index 00000000000..a42e4d3e3dc --- /dev/null +++ b/analysis/low-level-api-fir/testdata/lazyResolve/typeParameterBounds.txt @@ -0,0 +1,141 @@ +RAW_FIR: +FILE: typeParameterBounds.kt + public? final? [RAW_FIR] fun resolveMe([RAW_FIR] foo: Foo): R|kotlin/Unit| { LAZY_BLOCK } + public? final? [RAW_FIR] interface Foo : R|kotlin/Any| { + } + public? final? [RAW_FIR] interface Bar<[RAW_FIR] T : Foo> : R|kotlin/Any| { + } + public? final? [RAW_FIR] fun <[RAW_FIR] F : Foo, [RAW_FIR] B : Bar> F.util(): B { LAZY_BLOCK } + +IMPORTS: +FILE: typeParameterBounds.kt + public? final? [RAW_FIR] fun resolveMe([RAW_FIR] foo: Foo): R|kotlin/Unit| { LAZY_BLOCK } + public? final? [RAW_FIR] interface Foo : R|kotlin/Any| { + } + public? final? [RAW_FIR] interface Bar<[RAW_FIR] T : Foo> : R|kotlin/Any| { + } + public? final? [RAW_FIR] fun <[RAW_FIR] F : Foo, [RAW_FIR] B : Bar> F.util(): B { LAZY_BLOCK } + +COMPILER_REQUIRED_ANNOTATIONS: +FILE: typeParameterBounds.kt + public? final? [COMPILER_REQUIRED_ANNOTATIONS] fun resolveMe([COMPILER_REQUIRED_ANNOTATIONS] foo: Foo): R|kotlin/Unit| { LAZY_BLOCK } + public? final? [RAW_FIR] interface Foo : R|kotlin/Any| { + } + public? final? [RAW_FIR] interface Bar<[RAW_FIR] T : Foo> : R|kotlin/Any| { + } + public? final? [RAW_FIR] fun <[RAW_FIR] F : Foo, [RAW_FIR] B : Bar> F.util(): B { LAZY_BLOCK } + +COMPANION_GENERATION: +FILE: typeParameterBounds.kt + public? final? [COMPANION_GENERATION] fun resolveMe([COMPANION_GENERATION] foo: Foo): R|kotlin/Unit| { LAZY_BLOCK } + public? final? [RAW_FIR] interface Foo : R|kotlin/Any| { + } + public? final? [RAW_FIR] interface Bar<[RAW_FIR] T : Foo> : R|kotlin/Any| { + } + public? final? [RAW_FIR] fun <[RAW_FIR] F : Foo, [RAW_FIR] B : Bar> F.util(): B { LAZY_BLOCK } + +SUPER_TYPES: +FILE: typeParameterBounds.kt + public? final? [SUPER_TYPES] fun resolveMe([SUPER_TYPES] foo: Foo): R|kotlin/Unit| { LAZY_BLOCK } + public? final? [RAW_FIR] interface Foo : R|kotlin/Any| { + } + public? final? [RAW_FIR] interface Bar<[RAW_FIR] T : Foo> : R|kotlin/Any| { + } + public? final? [RAW_FIR] fun <[RAW_FIR] F : Foo, [RAW_FIR] B : Bar> F.util(): B { LAZY_BLOCK } + +TYPES: +FILE: typeParameterBounds.kt + public? final? [TYPES] fun resolveMe([TYPES] foo: R|Foo|): R|kotlin/Unit| { LAZY_BLOCK } + public? final? [COMPILER_REQUIRED_ANNOTATIONS] interface Foo : R|kotlin/Any| { + } + public? final? [RAW_FIR] interface Bar<[RAW_FIR] T : Foo> : R|kotlin/Any| { + } + public? final? [RAW_FIR] fun <[RAW_FIR] F : Foo, [RAW_FIR] B : Bar> F.util(): B { LAZY_BLOCK } + +STATUS: +FILE: typeParameterBounds.kt + public final [STATUS] fun resolveMe([STATUS] foo: R|Foo|): R|kotlin/Unit| { LAZY_BLOCK } + public? final? [COMPILER_REQUIRED_ANNOTATIONS] interface Foo : R|kotlin/Any| { + } + public? final? [RAW_FIR] interface Bar<[RAW_FIR] T : Foo> : R|kotlin/Any| { + } + public? final? [RAW_FIR] fun <[RAW_FIR] F : Foo, [RAW_FIR] B : Bar> F.util(): B { LAZY_BLOCK } + +ARGUMENTS_OF_ANNOTATIONS: +FILE: typeParameterBounds.kt + public final [ARGUMENTS_OF_ANNOTATIONS] fun resolveMe([ARGUMENTS_OF_ANNOTATIONS] foo: R|Foo|): R|kotlin/Unit| { LAZY_BLOCK } + public? final? [COMPILER_REQUIRED_ANNOTATIONS] interface Foo : R|kotlin/Any| { + } + public? final? [RAW_FIR] interface Bar<[RAW_FIR] T : Foo> : R|kotlin/Any| { + } + public? final? [RAW_FIR] fun <[RAW_FIR] F : Foo, [RAW_FIR] B : Bar> F.util(): B { LAZY_BLOCK } + +CONTRACTS: +FILE: typeParameterBounds.kt + public final [CONTRACTS] fun resolveMe([CONTRACTS] foo: R|Foo|): R|kotlin/Unit| { + foo#.util#() + } + public? final? [COMPILER_REQUIRED_ANNOTATIONS] interface Foo : R|kotlin/Any| { + } + public? final? [RAW_FIR] interface Bar<[RAW_FIR] T : Foo> : R|kotlin/Any| { + } + public? final? [RAW_FIR] fun <[RAW_FIR] F : Foo, [RAW_FIR] B : Bar> F.util(): B { LAZY_BLOCK } + +IMPLICIT_TYPES_BODY_RESOLVE: +FILE: typeParameterBounds.kt + public final [IMPLICIT_TYPES_BODY_RESOLVE] fun resolveMe([IMPLICIT_TYPES_BODY_RESOLVE] foo: R|Foo|): R|kotlin/Unit| { + foo#.util#() + } + public? final? [COMPILER_REQUIRED_ANNOTATIONS] interface Foo : R|kotlin/Any| { + } + public? final? [RAW_FIR] interface Bar<[RAW_FIR] T : Foo> : R|kotlin/Any| { + } + public? final? [RAW_FIR] fun <[RAW_FIR] F : Foo, [RAW_FIR] B : Bar> F.util(): B { LAZY_BLOCK } + +ANNOTATIONS_ARGUMENTS_MAPPING: +FILE: typeParameterBounds.kt + public final [ANNOTATIONS_ARGUMENTS_MAPPING] fun resolveMe([ANNOTATIONS_ARGUMENTS_MAPPING] foo: R|Foo|): R|kotlin/Unit| { + foo#.util#() + } + public? final? [COMPILER_REQUIRED_ANNOTATIONS] interface Foo : R|kotlin/Any| { + } + public? final? [RAW_FIR] interface Bar<[RAW_FIR] T : Foo> : R|kotlin/Any| { + } + public? final? [RAW_FIR] fun <[RAW_FIR] F : Foo, [RAW_FIR] B : Bar> F.util(): B { LAZY_BLOCK } + +EXPECT_ACTUAL_MATCHING: +FILE: typeParameterBounds.kt + public final [EXPECT_ACTUAL_MATCHING] fun resolveMe([EXPECT_ACTUAL_MATCHING] foo: R|Foo|): R|kotlin/Unit| { + foo#.util#() + } + public? final? [COMPILER_REQUIRED_ANNOTATIONS] interface Foo : R|kotlin/Any| { + } + public? final? [RAW_FIR] interface Bar<[RAW_FIR] T : Foo> : R|kotlin/Any| { + } + public? final? [RAW_FIR] fun <[RAW_FIR] F : Foo, [RAW_FIR] B : Bar> F.util(): B { LAZY_BLOCK } + +BODY_RESOLVE: +FILE: typeParameterBounds.kt + public final [BODY_RESOLVE] fun resolveMe([BODY_RESOLVE] foo: R|Foo|): R|kotlin/Unit| { + R|/foo|.R|/util||>() + } + public abstract [STATUS] interface Foo : R|kotlin/Any| { + } + public? final? [TYPES] interface Bar<[TYPES] T : R|Foo|> : R|kotlin/Any| { + } + public final [CONTRACTS] fun <[CONTRACTS] F : R|Foo|, [CONTRACTS] B : R|Bar|> R|F|.util(): R|B| { + ^util Null(null)!! + } + +FILE RAW TO BODY: +FILE: typeParameterBounds.kt + public final [BODY_RESOLVE] fun resolveMe([BODY_RESOLVE] foo: R|Foo|): R|kotlin/Unit| { + R|/foo|.R|/util||>() + } + public abstract [BODY_RESOLVE] interface Foo : R|kotlin/Any| { + } + public abstract [BODY_RESOLVE] interface Bar<[BODY_RESOLVE] T : R|Foo|> : R|kotlin/Any| { + } + public final [BODY_RESOLVE] fun <[BODY_RESOLVE] F : R|Foo|, [BODY_RESOLVE] B : R|Bar|> R|F|.util(): R|B| { + ^util Null(null)!! + } diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirOutOfContentRootLazyDeclarationResolveTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirOutOfContentRootLazyDeclarationResolveTestGenerated.java index eee711b130a..b1bacb03e04 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirOutOfContentRootLazyDeclarationResolveTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirOutOfContentRootLazyDeclarationResolveTestGenerated.java @@ -126,6 +126,12 @@ public class FirOutOfContentRootLazyDeclarationResolveTestGenerated extends Abst runTest("analysis/low-level-api-fir/testdata/lazyResolve/topLevelFunctionsWithImplicitType.kt"); } + @Test + @TestMetadata("typeParameterBounds.kt") + public void testTypeParameterBounds() throws Exception { + runTest("analysis/low-level-api-fir/testdata/lazyResolve/typeParameterBounds.kt"); + } + @Test @TestMetadata("typeParameterOfNonLocalFunction.kt") public void testTypeParameterOfNonLocalFunction() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirSourceLazyDeclarationResolveTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirSourceLazyDeclarationResolveTestGenerated.java index 5858af2a823..cd299f50029 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirSourceLazyDeclarationResolveTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirSourceLazyDeclarationResolveTestGenerated.java @@ -126,6 +126,12 @@ public class FirSourceLazyDeclarationResolveTestGenerated extends AbstractFirSou runTest("analysis/low-level-api-fir/testdata/lazyResolve/topLevelFunctionsWithImplicitType.kt"); } + @Test + @TestMetadata("typeParameterBounds.kt") + public void testTypeParameterBounds() throws Exception { + runTest("analysis/low-level-api-fir/testdata/lazyResolve/typeParameterBounds.kt"); + } + @Test @TestMetadata("typeParameterOfNonLocalFunction.kt") public void testTypeParameterOfNonLocalFunction() throws Exception { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt index 16a50af3e5c..b6ffdd456a2 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt @@ -338,6 +338,7 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty override fun TypeParameterMarker.hasRecursiveBounds(selfConstructor: TypeConstructorMarker?): Boolean { require(this is ConeTypeParameterLookupTag) + this.typeParameterSymbol.lazyResolveToPhase(FirResolvePhase.TYPES) return this.bounds().any { typeRef -> typeRef.coneType.contains { it.typeConstructor() == this.getTypeConstructor() } && (selfConstructor == null || typeRef.coneType.typeConstructor() == selfConstructor)