diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt index 25c6845d015..54500c0f7f7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt @@ -341,16 +341,16 @@ object Renderers { } val typeParameter = typeVariableWithCapturedConstraint.originalTypeParameter - - val explanation: String val upperBound = TypeIntersector.getUpperBoundsAsType(typeParameter) - if (!KotlinBuiltIns.isNullableAny(upperBound) && capturedTypeConstructor.typeProjection.projectionKind == Variance.IN_VARIANCE) { - explanation = "Type parameter has an upper bound '" + result.typeRenderer.render(upperBound, RenderingContext.of(upperBound)) + "'" + - " that cannot be satisfied capturing 'in' projection" - } - else { - explanation = "Only top-level type projections can be captured" + + assert(!KotlinBuiltIns.isNullableAny(upperBound) && capturedTypeConstructor.typeProjection.projectionKind == Variance.IN_VARIANCE) { + "There is the only reason to report TYPE_INFERENCE_CANNOT_CAPTURE_TYPES" } + + val explanation = + "Type parameter has an upper bound '" + result.typeRenderer.render(upperBound, RenderingContext.of(upperBound)) + "'" + + " that cannot be satisfied capturing 'in' projection" + result.text(newText().normal( "'" + typeParameter.name + "'" + " cannot capture " + @@ -454,4 +454,4 @@ object Renderers { }.asRenderer() } -fun DescriptorRenderer.asRenderer() = SmartDescriptorRenderer(this) \ No newline at end of file +fun DescriptorRenderer.asRenderer() = SmartDescriptorRenderer(this) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt index 27e9cdd04a9..92fec3c37fe 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/inference/ConstraintSystemBuilderImpl.kt @@ -152,13 +152,10 @@ open class ConstraintSystemBuilderImpl(private val mode: Mode = ConstraintSystem } override fun capture(type: KotlinType, typeProjection: TypeProjection): Boolean { - if (isMyTypeVariable(typeProjection.type)) return false + if (isMyTypeVariable(typeProjection.type) || depth > 0) return false val myTypeVariable = getMyTypeVariable(type) if (myTypeVariable != null && constraintPosition.isParameter()) { - if (depth > 0) { - errors.add(CannotCapture(constraintPosition, myTypeVariable)) - } generateTypeParameterCaptureConstraint(myTypeVariable, typeProjection, newConstraintContext, type.isMarkedNullable) return true } diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/captureTypeOnlyOnTopLevel.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/captureTypeOnlyOnTopLevel.kt index f3fd894ca32..dd8cc5160f8 100644 --- a/compiler/testData/diagnostics/tests/inference/capturedTypes/captureTypeOnlyOnTopLevel.kt +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/captureTypeOnlyOnTopLevel.kt @@ -3,7 +3,7 @@ fun foo(array: Array>): Array> = array fun test(array: Array>) { - foo(array) + foo(array) - val f: Array> = foo(array) -} \ No newline at end of file + val f: Array> = foo(array) +} diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/noCaptureTypeErrorForNonTopLevel.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/noCaptureTypeErrorForNonTopLevel.kt new file mode 100644 index 00000000000..be913887a32 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/noCaptureTypeErrorForNonTopLevel.kt @@ -0,0 +1,18 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +class A +class B + +fun foo(b: B>) {} +fun baz(b: B>) {} + +// See KT-13950 +fun bar(b: B>, bOut: B>, bOut2: B>) { + foo(b) + foo(b) + + baz(bOut) + baz(bOut) + + baz(bOut2) + baz(bOut2) +} diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/noCaptureTypeErrorForNonTopLevel.txt b/compiler/testData/diagnostics/tests/inference/capturedTypes/noCaptureTypeErrorForNonTopLevel.txt new file mode 100644 index 00000000000..2854e0e4c49 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/noCaptureTypeErrorForNonTopLevel.txt @@ -0,0 +1,19 @@ +package + +public fun bar(/*0*/ b: B>, /*1*/ bOut: B>, /*2*/ bOut2: B>): kotlin.Unit +public fun baz(/*0*/ b: B>): kotlin.Unit +public fun foo(/*0*/ b: B>): kotlin.Unit + +public final class A { + public constructor A() + 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 +} + +public final class B { + public constructor B() + 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 +} diff --git a/compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.kt b/compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.kt index 111b42f50bf..7ebe2dacaa1 100644 --- a/compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.kt +++ b/compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.kt @@ -4,6 +4,7 @@ class B fun B.foo(f: (T) -> Unit) {} fun B.bar(f: (T, T) -> Unit, g: (T, T) -> Unit) {} +fun B.baz(f: (B) -> Unit) {} fun number(x: Number) {} fun Number.foobar() {} @@ -34,4 +35,8 @@ fun test(b: B) { b.foo(::number) b.foo(Number::foobar) + + b.baz { + b -> b checkType { _>() } + } } diff --git a/compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.txt b/compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.txt index 583f8bb3905..221bb0770a4 100644 --- a/compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.txt +++ b/compiler/testData/diagnostics/tests/resolve/capturedTypesInLambdaParameter.txt @@ -3,6 +3,7 @@ package public fun number(/*0*/ x: kotlin.Number): kotlin.Unit public fun test(/*0*/ b: B): kotlin.Unit public fun B.bar(/*0*/ f: (T, T) -> kotlin.Unit, /*1*/ g: (T, T) -> kotlin.Unit): kotlin.Unit +public fun B.baz(/*0*/ f: (B) -> kotlin.Unit): kotlin.Unit public fun B.foo(/*0*/ f: (T) -> kotlin.Unit): kotlin.Unit public fun kotlin.Number.foobar(): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 72b9348803f..b57c117f776 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -9389,6 +9389,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("noCaptureTypeErrorForNonTopLevel.kt") + public void testNoCaptureTypeErrorForNonTopLevel() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/noCaptureTypeErrorForNonTopLevel.kt"); + doTest(fileName); + } + @TestMetadata("notApproximateWhenCopyDescriptors.kt") public void testNotApproximateWhenCopyDescriptors() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/notApproximateWhenCopyDescriptors.kt"); diff --git a/idea/testData/diagnosticMessage/typeInferenceCannotCaptureTypes.kt b/idea/testData/diagnosticMessage/typeInferenceCannotCaptureTypes.kt index acfd7aca9b9..ab300538f96 100644 --- a/idea/testData/diagnosticMessage/typeInferenceCannotCaptureTypes.kt +++ b/idea/testData/diagnosticMessage/typeInferenceCannotCaptureTypes.kt @@ -1,10 +1,8 @@ // !DIAGNOSTICS_NUMBER: 1 // !DIAGNOSTICS: TYPE_INFERENCE_CANNOT_CAPTURE_TYPES -class My +fun bar(a: Array): Array = null!! -fun foo(my: My, T>): My, T> = my - -fun test11(my: My, out Int>) { - foo(my) -} \ No newline at end of file +fun test1(a: Array) { + val r: Array = bar(a) +} diff --git a/idea/testData/diagnosticMessage/typeInferenceCannotCaptureTypes1.txt b/idea/testData/diagnosticMessage/typeInferenceCannotCaptureTypes1.txt index 2080a7f5710..13ad6f83762 100644 --- a/idea/testData/diagnosticMessage/typeInferenceCannotCaptureTypes1.txt +++ b/idea/testData/diagnosticMessage/typeInferenceCannotCaptureTypes1.txt @@ -1,2 +1,2 @@ -Type inference failed: 'R' cannot capture 'out Int'. Only top-level type projections can be captured \ No newline at end of file +Type inference failed: 'R' cannot capture 'in Int'. Type parameter has an upper bound 'Any' that cannot be satisfied capturing 'in' projection