~ cst fix
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java
index 68ed2be..58051be 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java
@@ -16420,6 +16420,12 @@
                 }
 
                 @Test
+                @TestMetadata("innerTvFixationFromLowerConstraints.kt")
+                public void testInnerTvFixationFromLowerConstraints() throws Exception {
+                    runTest("compiler/testData/diagnostics/tests/inference/builderInference/innerTvFixationFromLowerConstraints.kt");
+                }
+
+                @Test
                 @TestMetadata("invalidateKeys.kt")
                 public void testInvalidateKeys() throws Exception {
                     runTest("compiler/testData/diagnostics/tests/inference/builderInference/invalidateKeys.kt");
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java
index 1fd63e8..3fdd2f4 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java
@@ -16420,6 +16420,12 @@
                 }
 
                 @Test
+                @TestMetadata("innerTvFixationFromLowerConstraints.kt")
+                public void testInnerTvFixationFromLowerConstraints() throws Exception {
+                    runTest("compiler/testData/diagnostics/tests/inference/builderInference/innerTvFixationFromLowerConstraints.kt");
+                }
+
+                @Test
                 @TestMetadata("invalidateKeys.kt")
                 public void testInvalidateKeys() throws Exception {
                     runTest("compiler/testData/diagnostics/tests/inference/builderInference/invalidateKeys.kt");
diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java
index 3050112..350f863 100644
--- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java
+++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java
@@ -16414,6 +16414,12 @@
                 }
 
                 @Test
+                @TestMetadata("innerTvFixationFromLowerConstraints.kt")
+                public void testInnerTvFixationFromLowerConstraints() throws Exception {
+                    runTest("compiler/testData/diagnostics/tests/inference/builderInference/innerTvFixationFromLowerConstraints.kt");
+                }
+
+                @Test
                 @TestMetadata("invalidateKeys.kt")
                 public void testInvalidateKeys() throws Exception {
                     runTest("compiler/testData/diagnostics/tests/inference/builderInference/invalidateKeys.kt");
diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java
index 0295745..37cb735 100644
--- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java
+++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java
@@ -16420,6 +16420,12 @@
                 }
 
                 @Test
+                @TestMetadata("innerTvFixationFromLowerConstraints.kt")
+                public void testInnerTvFixationFromLowerConstraints() throws Exception {
+                    runTest("compiler/testData/diagnostics/tests/inference/builderInference/innerTvFixationFromLowerConstraints.kt");
+                }
+
+                @Test
                 @TestMetadata("invalidateKeys.kt")
                 public void testInvalidateKeys() throws Exception {
                     runTest("compiler/testData/diagnostics/tests/inference/builderInference/invalidateKeys.kt");
diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt
index c75d763..90b2fdd 100644
--- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt
+++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt
@@ -14,10 +14,7 @@
 import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
 import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
 import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
-import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
-import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
-import org.jetbrains.kotlin.fir.resolve.substitution.NoSubstitutor
-import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor
+import org.jetbrains.kotlin.fir.resolve.substitution.*
 import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
 import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
 import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousObjectSymbol
@@ -351,6 +348,15 @@
         return ConeSubstitutor.Empty
     }
 
+    override fun createSubstitutionFromSubtypingStubTypesToTypeVariables(): TypeSubstitutorMarker {
+        return object : AbstractConeSubstitutor(this) {
+            override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
+                return ((type as? ConeStubTypeForTypeVariableInSubtyping)
+                    ?.constructor?.variable?.defaultType)?.withNullability(type.nullability, this@ConeInferenceContext)
+            }
+        }
+    }
+
     override fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker {
         if (this === NoSubstitutor) return type
         require(this is ConeSubstitutor)
diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt
index a29b0f8..df4f7c34 100644
--- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt
+++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt
@@ -603,6 +603,10 @@
         return IrTypeSubstitutor(emptyMap())
     }
 
+    override fun createSubstitutionFromSubtypingStubTypesToTypeVariables(): TypeSubstitutorMarker {
+        error("Only for inference")
+    }
+
     override fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker {
         require(this is AbstractIrTypeSubstitutor)
         require(type is IrType)
diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt
index de12ac5..5517947 100644
--- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt
+++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt
@@ -22,6 +22,7 @@
     private val languageVersionSettings: LanguageVersionSettings
 ) {
     interface Context : TypeSystemInferenceExtensionContext {
+        val outerSystemVariablesPrefixSize: Int
         fun isProperType(type: KotlinTypeMarker): Boolean
         fun buildNotFixedVariablesToStubTypesSubstitutor(): TypeSubstitutorMarker
         fun isReified(variable: TypeVariableMarker): Boolean
@@ -220,6 +221,8 @@
 
                 if (typesWithoutStubs.isNotEmpty()) {
                     commonSuperType = computeCommonSuperType(typesWithoutStubs)
+                } else if (outerSystemVariablesPrefixSize > 0) {
+                    commonSuperType = createSubstitutionFromSubtypingStubTypesToTypeVariables().safeSubstitute(commonSuperType)
                 }
             }
 
@@ -273,11 +276,23 @@
         }
 
         if (!atLeastOneProper) return emptyList()
-        if (!atLeastOneNonProper) return lowerConstraintTypes
+
+        val noOuterTypeVariables = outerSystemVariablesPrefixSize == 0
+        if (!atLeastOneNonProper && noOuterTypeVariables) return lowerConstraintTypes
+
+        // Might be an optimization
+//        if (!noOuterTypeVariables && lowerConstraintTypes.size == 1 && isProperTypeForFixation(lowerConstraintTypes.single())) {
+//            return lowerConstraintTypes
+//        }
 
         val notFixedToStubTypesSubstitutor = buildNotFixedVariablesToStubTypesSubstitutor()
 
-        return lowerConstraintTypes.map { if (isProperTypeForFixation(it)) it else notFixedToStubTypesSubstitutor.safeSubstitute(it) }
+        return lowerConstraintTypes.map {
+            if (noOuterTypeVariables && isProperTypeForFixation(it))
+                it
+            else
+                notFixedToStubTypesSubstitutor.safeSubstitute(it)
+        }
     }
 
     private fun Context.sinkIntegerLiteralTypes(types: List<KotlinTypeMarker>): List<KotlinTypeMarker> {
diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/innerTvFixationFromLowerConstraints.fir.kt b/compiler/testData/diagnostics/tests/inference/builderInference/innerTvFixationFromLowerConstraints.fir.kt
new file mode 100644
index 0000000..616a438
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/inference/builderInference/innerTvFixationFromLowerConstraints.fir.kt
@@ -0,0 +1,32 @@
+class Controller<T> {
+    fun yield(t: T): Boolean = true
+}
+
+fun <S> generate(g: suspend Controller<S>.() -> Unit): S = TODO()
+
+fun <E4> select(x: E4, y: E4) {}
+fun <E5> selectL(x: E5, y: E5, l: (E5) -> Unit) {}
+
+fun main(x: Controller<String>) {
+    generate {
+        // Just adding the constraints
+        // Controller<String> <: E4
+        // Controller<S> <: E4
+        // No fixation is required
+        select(x, this)
+    }.length
+
+    generate {
+        // Adding the constraints
+        // Controller<String> <: E5
+        // Controller<S> <: E5
+        // But to analyze lambda we fix E5 to CST(Controller<String>, Controller<S>) = Controller<CST(String, S)>
+        // The question is what is CST(String, S)
+        // And current answer in K2 is that it's String just the same way as when while fixating some TV, it has improper lower constraits
+        // See org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver.prepareLowerConstraints
+        selectL(x, this) { x ->
+            x.yield(<!ARGUMENT_TYPE_MISMATCH!>1<!>)
+            x.yield("")
+        }
+    }.length
+}
\ No newline at end of file
diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/innerTvFixationFromLowerConstraints.kt b/compiler/testData/diagnostics/tests/inference/builderInference/innerTvFixationFromLowerConstraints.kt
new file mode 100644
index 0000000..aaad0a0
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/inference/builderInference/innerTvFixationFromLowerConstraints.kt
@@ -0,0 +1,32 @@
+class Controller<T> {
+    fun yield(t: T): Boolean = true
+}
+
+fun <S> generate(g: suspend Controller<S>.() -> Unit): S = TODO()
+
+fun <E4> select(x: E4, y: E4) {}
+fun <E5> selectL(x: E5, y: E5, l: (E5) -> Unit) {}
+
+fun main(x: Controller<String>) {
+    generate {
+        // Just adding the constraints
+        // Controller<String> <: E4
+        // Controller<S> <: E4
+        // No fixation is required
+        select(x, this)
+    }.length
+
+    generate {
+        // Adding the constraints
+        // Controller<String> <: E5
+        // Controller<S> <: E5
+        // But to analyze lambda we fix E5 to CST(Controller<String>, Controller<S>) = Controller<CST(String, S)>
+        // The question is what is CST(String, S)
+        // And current answer in K2 is that it's String just the same way as when while fixating some TV, it has improper lower constraits
+        // See org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver.prepareLowerConstraints
+        selectL(x, this) { x ->
+            x.yield(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
+            x.yield(<!TYPE_MISMATCH!>""<!>)
+        }
+    }.length
+}
\ No newline at end of file
diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
index 3b69ed7..af3a206 100644
--- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
+++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
@@ -16420,6 +16420,12 @@
                 }
 
                 @Test
+                @TestMetadata("innerTvFixationFromLowerConstraints.kt")
+                public void testInnerTvFixationFromLowerConstraints() throws Exception {
+                    runTest("compiler/testData/diagnostics/tests/inference/builderInference/innerTvFixationFromLowerConstraints.kt");
+                }
+
+                @Test
                 @TestMetadata("invalidateKeys.kt")
                 public void testInvalidateKeys() throws Exception {
                     runTest("compiler/testData/diagnostics/tests/inference/builderInference/invalidateKeys.kt");
diff --git a/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt b/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt
index 1f26eb4..6a46d3c 100644
--- a/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt
+++ b/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt
@@ -559,6 +559,8 @@
     fun typeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, KotlinTypeMarker>): TypeSubstitutorMarker
     fun createEmptySubstitutor(): TypeSubstitutorMarker
 
+    fun createSubstitutionFromSubtypingStubTypesToTypeVariables(): TypeSubstitutorMarker
+
     /**
      * @returns substituted type or [type] if there were no substitution
      */
diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt
index 6518f37..d617635 100644
--- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt
+++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt
@@ -618,6 +618,10 @@
         errorSupportedOnlyInTypeInference()
     }
 
+    override fun createSubstitutionFromSubtypingStubTypesToTypeVariables(): TypeSubstitutorMarker {
+        error("Only for K2")
+    }
+
     override fun TypeSubstitutorMarker.safeSubstitute(type: KotlinTypeMarker): KotlinTypeMarker {
         require(type is UnwrappedType, type::errorMessage)
         require(this is TypeSubstitutor, this::errorMessage)