[FE] Add missing 'lazyResolveToPhase()' before recursive bound check

^KTIJ-24087 Fixed
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 0000000..019163b
--- /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<T : Foo>
+
+fun <F : Foo, B : Bar<F>> 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 0000000..a42e4d3
--- /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>> 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>> 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>> 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>> 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>> 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>> 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>> 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>> 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>> 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>> 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>> 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>> 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|<local>/foo|.R|/util|<R|Foo|, R|Bar<Foo>|>()
+    }
+    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<F>|> 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|<local>/foo|.R|/util|<R|Foo|, R|Bar<Foo>|>()
+    }
+    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<F>|> 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/FirLazyDeclarationResolveTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirLazyDeclarationResolveTestGenerated.java
index 994b4a9..dedec26 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirLazyDeclarationResolveTestGenerated.java
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirLazyDeclarationResolveTestGenerated.java
@@ -127,6 +127,12 @@
     }
 
     @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 {
         runTest("analysis/low-level-api-fir/testdata/lazyResolve/typeParameterOfNonLocalFunction.kt");
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 04f5d1b..16cb98c 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
@@ -335,6 +335,7 @@
 
     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)