From 154e53c701ed1481315af04d822ab0587e2ec3e8 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 26 Aug 2022 16:23:01 +0200 Subject: [PATCH] K1: add diagnostic BUILDER_INFERENCE_STUB_RECEIVER It's reported on receivers in extension function calls with stub type, as such calls can shadow members of finalized stub types causing change of resolve when corresponding type argument specified explicitly It works by checking extension receiver during call resolution parts run That way we can easily detect if we found an extension applicable to stub receiver and report call diagnostic for it KT-53739 --- ...CompilerTestFE10TestdataTestGenerated.java | 12 +++ ...irOldFrontendDiagnosticsTestGenerated.java | 12 +++ ...DiagnosticsWithLightTreeTestGenerated.java | 12 +++ .../jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../DiagnosticReporterByTrackingStrategy.kt | 16 ++++ .../calls/components/ResolutionParts.kt | 20 ++++- .../calls/model/KotlinCallDiagnostics.kt | 7 ++ .../inference/builderInference/memberScope.kt | 24 +++--- .../builderInference/errorOnStubReceiver.kt | 2 +- .../inference/builderInference/kt53422.fir.kt | 1 + .../inference/builderInference/kt53422.kt | 2 +- .../builderInference/stubTypes/memberScope.kt | 60 +++++++-------- .../stubTypeReceiverRestriction.fir.kt | 72 ++++++++++++++++++ .../stubTypes/stubTypeReceiverRestriction.kt | 72 ++++++++++++++++++ ...stubTypeReceiverRestrictionDisabled.fir.kt | 73 +++++++++++++++++++ .../stubTypeReceiverRestrictionDisabled.kt | 73 +++++++++++++++++++ .../test/runners/DiagnosticTestGenerated.java | 12 +++ 18 files changed, 428 insertions(+), 44 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestriction.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestriction.kt create mode 100644 compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestrictionDisabled.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestrictionDisabled.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 970c5c67d5f..e85e9d33053 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -14625,6 +14625,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag public void testRenderingStubTypes() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/renderingStubTypes.kt"); } + + @Test + @TestMetadata("stubTypeReceiverRestriction.kt") + public void testStubTypeReceiverRestriction() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestriction.kt"); + } + + @Test + @TestMetadata("stubTypeReceiverRestrictionDisabled.kt") + public void testStubTypeReceiverRestrictionDisabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestrictionDisabled.kt"); + } } } diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 0004dacaa56..b509f0e061a 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -14625,6 +14625,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti public void testRenderingStubTypes() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/renderingStubTypes.kt"); } + + @Test + @TestMetadata("stubTypeReceiverRestriction.kt") + public void testStubTypeReceiverRestriction() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestriction.kt"); + } + + @Test + @TestMetadata("stubTypeReceiverRestrictionDisabled.kt") + public void testStubTypeReceiverRestrictionDisabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestrictionDisabled.kt"); + } } } diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index 0a20c57bccd..22ae96e9131 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -14625,6 +14625,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac public void testRenderingStubTypes() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/renderingStubTypes.kt"); } + + @Test + @TestMetadata("stubTypeReceiverRestriction.kt") + public void testStubTypeReceiverRestriction() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestriction.kt"); + } + + @Test + @TestMetadata("stubTypeReceiverRestrictionDisabled.kt") + public void testStubTypeReceiverRestrictionDisabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestrictionDisabled.kt"); + } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 7664f6014ca..36e3ddf9b1c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -862,6 +862,7 @@ public interface Errors { DiagnosticFactory3 STUB_TYPE_IN_ARGUMENT_CAUSES_AMBIGUITY = DiagnosticFactory3.create(ERROR); DiagnosticFactory4 STUB_TYPE_IN_RECEIVER_CAUSES_AMBIGUITY = DiagnosticFactory4.create(ERROR); DiagnosticFactory2 BUILDER_INFERENCE_MULTI_LAMBDA_RESTRICTION = DiagnosticFactory2.create(ERROR); + DiagnosticFactory2 BUILDER_INFERENCE_STUB_RECEIVER = DiagnosticFactory2.create(ERROR); DiagnosticFactory1>> NONE_APPLICABLE = DiagnosticFactory1.create(ERROR); DiagnosticFactory1>> CANNOT_COMPLETE_RESOLVE = DiagnosticFactory1.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 1c9decc2988..329347d605c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -945,6 +945,7 @@ public class DefaultErrorMessages { MAP.put(STUB_TYPE_IN_ARGUMENT_CAUSES_AMBIGUITY, "The type of an argument hasn''t been inferred yet. To disambiguate this call, explicitly cast it to `{0}` if you want the builder''s type parameter(s) `{1}` to be inferred to `{2}`.", RENDER_TYPE, STRING, STRING); MAP.put(STUB_TYPE_IN_RECEIVER_CAUSES_AMBIGUITY, "The type of a receiver hasn''t been inferred yet. To disambiguate this call, explicitly cast it to `{0}` if you want the builder''s type parameter(s) `{1}` to be inferred to `{2}`.", RENDER_TYPE, STRING, STRING, null); MAP.put(BUILDER_INFERENCE_MULTI_LAMBDA_RESTRICTION, "Unstable inference behaviour with multiple lambdas. Please either specify type argument for generic parameter `{0}` of `{1}` explicitly or add @BuilderInference to corresponding parameter declaration", TO_STRING, TO_STRING); + MAP.put(BUILDER_INFERENCE_STUB_RECEIVER, "The type of a receiver hasn''t been inferred yet. Please specify type argument for generic parameter `{0}` of `{1}` explicitly", TO_STRING, TO_STRING); MAP.put(NONE_APPLICABLE, "None of the following functions can be called with the arguments supplied: {0}", AMBIGUOUS_CALLS); MAP.put(CANNOT_COMPLETE_RESOLVE, "Cannot choose among the following candidates without completing type inference: {0}", AMBIGUOUS_CALLS); MAP.put(UNRESOLVED_REFERENCE_WRONG_RECEIVER, "Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: {0}", AMBIGUOUS_CALLS); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt index cd7edadfabf..9b57556c738 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -39,6 +39,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.StubTypeForBuilderInference import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.checker.intersectWrappedTypes import org.jetbrains.kotlin.types.error.ErrorUtils @@ -199,6 +200,21 @@ class DiagnosticReporterByTrackingStrategy( trace.report(SUPER_CANT_BE_EXTENSION_RECEIVER.on(psiExpression, psiExpression.text)) } } + + StubBuilderInferenceReceiver::class.java -> { + diagnostic as StubBuilderInferenceReceiver + + val stubType = callReceiver.receiver.receiverValue.type as? StubTypeForBuilderInference + val originalTypeParameter = stubType?.originalTypeVariable?.originalTypeParameter + + trace.report( + BUILDER_INFERENCE_STUB_RECEIVER.on( + callReceiver.psiExpression ?: call.callElement, + originalTypeParameter?.name ?: SpecialNames.NO_NAME_PROVIDED, + originalTypeParameter?.containingDeclaration?.name ?: SpecialNames.NO_NAME_PROVIDED + ) + ) + } } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt index 2d172f6b8cf..d45efcd58f6 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt @@ -661,9 +661,25 @@ internal object CheckReceivers : ResolutionPart() { candidateDescriptor.dispatchReceiverParameter, shouldCheckImplicitInvoke = true, ) + 1 -> { - if (resolvedCall.extensionReceiverArgument == null) { - resolvedCall.extensionReceiverArgument = chooseExtensionReceiverCandidate() ?: return + val checkBuilderInferenceRestriction = + !callComponents.languageVersionSettings + .supportsFeature(LanguageFeature.NoBuilderInferenceWithoutAnnotationRestriction) + if (checkBuilderInferenceRestriction) { + var extensionReceiverArgument = resolvedCall.extensionReceiverArgument + if (extensionReceiverArgument == null) { + extensionReceiverArgument = chooseExtensionReceiverCandidate() ?: return + resolvedCall.extensionReceiverArgument = extensionReceiverArgument + } + if (extensionReceiverArgument.receiver.receiverValue.type is StubTypeForBuilderInference) { + addDiagnostic( + StubBuilderInferenceReceiver( + extensionReceiverArgument, + candidateDescriptor.extensionReceiverParameter!! + ) + ) + } } checkReceiver( resolvedCall.extensionReceiverArgument, diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallDiagnostics.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallDiagnostics.kt index 284620868db..11878bb6242 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallDiagnostics.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallDiagnostics.kt @@ -73,6 +73,13 @@ class MultiLambdaBuilderInferenceRestriction( override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this) } +class StubBuilderInferenceReceiver( + val receiver: SimpleKotlinCallArgument, + val extensionReceiverParameter: ReceiverParameterDescriptor, +) : KotlinCallDiagnostic(RESOLVED) { + override fun report(reporter: DiagnosticReporter) = reporter.onCallReceiver(receiver, this) +} + class MixingNamedAndPositionArguments(override val argument: KotlinCallArgument) : InapplicableArgumentDiagnostic() class NamedArgumentNotAllowed(val argument: KotlinCallArgument, val descriptor: CallableDescriptor) : KotlinCallDiagnostic(INAPPLICABLE) { diff --git a/compiler/testData/codegen/box/inference/builderInference/memberScope.kt b/compiler/testData/codegen/box/inference/builderInference/memberScope.kt index 42d2b17b909..1c33204c932 100644 --- a/compiler/testData/codegen/box/inference/builderInference/memberScope.kt +++ b/compiler/testData/codegen/box/inference/builderInference/memberScope.kt @@ -20,9 +20,10 @@ fun box(): String { val ret = build { emit(1) emit(null) - get()?.test() - get()?.test2() - get().test2() + // Error, resolved to extension on stub receiver +// get()?.test() +// get()?.test2() +// get().test2() get()?.hashCode() get()?.equals(1) val x = get() @@ -38,9 +39,10 @@ fun box(): String { x.equals("") x.hashCode() x.toString() - x.test() - x?.test2() - x.test2() + // Error, resolved to extension on stub receiver +// x.test() +// x?.test2() +// x.test2() } if (x == null) { @@ -50,8 +52,9 @@ fun box(): String { // x.hashCode() // x.toString() // x.test() - x?.test2() - x.test2() + // Error, resolved to extension on stub receiver +// x?.test2() +// x.test2() } if (x === null) { @@ -61,8 +64,9 @@ fun box(): String { // x.hashCode() // x.toString() // x.test() - x?.test2() - x.test2() + // Error, resolved to extension on stub receiver +// x?.test2() +// x.test2() } "" diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/errorOnStubReceiver.kt b/compiler/testData/diagnostics/tests/inference/builderInference/errorOnStubReceiver.kt index 655a98ec345..38e5002a960 100644 --- a/compiler/testData/diagnostics/tests/inference/builderInference/errorOnStubReceiver.kt +++ b/compiler/testData/diagnostics/tests/inference/builderInference/errorOnStubReceiver.kt @@ -12,7 +12,7 @@ fun main() { buildList { add(Bar()) - this.get(0).test() // resolved to Any?.test + this.get(0).test() // resolved to Any?.test } buildList { add(Bar()) diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/kt53422.fir.kt b/compiler/testData/diagnostics/tests/inference/builderInference/kt53422.fir.kt index 5ec0bf50632..8a84de782e4 100644 --- a/compiler/testData/diagnostics/tests/inference/builderInference/kt53422.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/builderInference/kt53422.fir.kt @@ -1,4 +1,5 @@ // WITH_STDLIB +// SKIP_TXT fun test() { foo( flow { emit(0) } diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/kt53422.kt b/compiler/testData/diagnostics/tests/inference/builderInference/kt53422.kt index e2c112f8304..24f6b4e7dcf 100644 --- a/compiler/testData/diagnostics/tests/inference/builderInference/kt53422.kt +++ b/compiler/testData/diagnostics/tests/inference/builderInference/kt53422.kt @@ -3,7 +3,7 @@ fun test() { foo( flow { emit(0) } - ) { it.collect {} } + ) { it.collect {} } // 0. Initial // W <: Any / declared upper bound diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/memberScope.kt b/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/memberScope.kt index 821f280ae66..c13790a7560 100644 --- a/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/memberScope.kt +++ b/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/memberScope.kt @@ -20,9 +20,9 @@ fun test() { val ret1 = build { emit(1) emit(null) - get()?.test() - get()?.test2() - get().test2() + get()?.test() + get()?.test2() + get().test2() get()?.hashCode() get()?.equals(1) // there is `String?.equals` extension @@ -31,9 +31,9 @@ fun test() { val ret2 = build { emit(1) emit(null) - get()?.test() - get()?.test2() - get().test2() + get()?.test() + get()?.test2() + get().test2() get()?.hashCode() get()?.equals(1) val x = get() @@ -44,9 +44,9 @@ fun test() { val ret3 = build { emit(1) emit(null) - get()?.test() - get()?.test2() - get().test2() + get()?.test() + get()?.test2() + get().test2() get()?.hashCode() get()?.equals(1) val x = get() @@ -62,9 +62,9 @@ fun test() { x.equals("") x.hashCode() x.toString() - x.test() - x?.test2() - x.test2() + x.test() + x?.test2() + x.test2() } "" @@ -104,7 +104,7 @@ fun test() { emit(null) val x = get() if (x == null) { - x.test() + x.test() } "" @@ -144,7 +144,7 @@ fun test() { emit(null) val x = get() if (x === null) { - x.test() + x.test() } "" @@ -153,16 +153,16 @@ fun test() { emit(1) emit(null) val x = get() - x.test() + x.test() "" } val ret41 = build { emit(1) emit(null) - get()?.test() - get()?.test2() - get().test2() + get()?.test() + get()?.test2() + get().test2() get()?.hashCode() get()?.equals(1) val x = get() @@ -181,11 +181,11 @@ fun test() { } if (x == null) { - x?.test2() + x?.test2() } if (x == null) { - x.test2() + x.test2() } if (x === null) { @@ -197,11 +197,11 @@ fun test() { } if (x === null) { - x?.test2() + x?.test2() } if (x === null) { - x.test2() + x.test2() } "" @@ -239,7 +239,7 @@ fun test() { emit(null) val x = get() if (x == null) { - x.test() + x.test() } "" } @@ -276,7 +276,7 @@ fun test() { emit(null) val x = get() if (x === null) { - x.test() + x.test() } "" } @@ -284,15 +284,15 @@ fun test() { emit(1) emit(null) val x = get() - x.test() + x.test() "" } val ret51 = build { emit(1) emit(null) - get()?.test() - get()?.test2() - get().test2() + get()?.test() + get()?.test2() + get().test2() get()?.hashCode() get()?.equals(1) val x = get() @@ -305,8 +305,8 @@ fun test() { if (x == null) { x?.hashCode() x?.equals(1) - x?.test2() - x.test2() + x?.test2() + x.test2() } "" diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestriction.fir.kt b/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestriction.fir.kt new file mode 100644 index 00000000000..0294509b82d --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestriction.fir.kt @@ -0,0 +1,72 @@ +// WITH_STDLIB +// SKIP_TXT + +fun a(lambda: List.(R) -> Unit) {} + +fun T.extension() {} + +fun use(p: Any?) {} + +fun test1() { + a { + this.get(0).extension() + use(this.get(0)::extension) + use(it::extension) + } +} + + +fun test2() { + a { + val v = this.get(0) + v.extension() + use(v::extension) + use(it::extension) + } +} + +fun test3() { + operator fun T.getValue(thisRef: Any?, prop: Any?): T = this + a { + val v by this.get(0) + v.extension() + use(v::extension) + use(it::extension) + } +} + +class Box(val t: TIn) + +fun test4() { + operator fun T.provideDelegate(thisRef: Any?, prop: Any?): Box = Box(this) + operator fun Box.getValue(thisRef: Any?, prop: Any?): T = this.t + a { + val v by this.get(0) + v.extension() + use(v::extension) + use(it::extension) + } +} + +fun b(lambda: R.(List) -> Unit) {} + +fun test5() { + + operator fun T.invoke(): T = this + b { + extension() + this().extension() + use(::extension) + } +} + +val T.genericLambda: T.((T) -> Unit) -> Unit get() = {} + +fun test6() { + b { + extension() + genericLambda { } + genericLambda { it.extension() } + use(::extension) + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestriction.kt b/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestriction.kt new file mode 100644 index 00000000000..9444a280bde --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestriction.kt @@ -0,0 +1,72 @@ +// WITH_STDLIB +// SKIP_TXT + +fun a(lambda: List.(R) -> Unit) {} + +fun T.extension() {} + +fun use(p: Any?) {} + +fun test1() { + a { + this.get(0).extension() + use(this.get(0)::extension) + use(it::extension) + } +} + + +fun test2() { + a { + val v = this.get(0) + v.extension() + use(v::extension) + use(it::extension) + } +} + +fun test3() { + operator fun T.getValue(thisRef: Any?, prop: Any?): T = this + a { + val v by this.get(0) + v.extension() + use(v::extension) + use(it::extension) + } +} + +class Box(val t: TIn) + +fun test4() { + operator fun T.provideDelegate(thisRef: Any?, prop: Any?): Box = Box(this) + operator fun Box.getValue(thisRef: Any?, prop: Any?): T = this.t + a { + val v by this.get(0) + v.extension() + use(v::extension) + use(it::extension) + } +} + +fun b(lambda: R.(List) -> Unit) {} + +fun test5() { + + operator fun T.invoke(): T = this + b { + extension() + this().extension() + use(::extension) + } +} + +val T.genericLambda: T.((T) -> Unit) -> Unit get() = {} + +fun test6() { + b { + extension() + genericLambda { } + genericLambda { it.extension() } + use(::extension) + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestrictionDisabled.fir.kt b/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestrictionDisabled.fir.kt new file mode 100644 index 00000000000..bd649fb47b2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestrictionDisabled.fir.kt @@ -0,0 +1,73 @@ +// WITH_STDLIB +// LANGUAGE: +NoBuilderInferenceWithoutAnnotationRestriction +// SKIP_TXT + +fun a(lambda: List.(R) -> Unit) {} + +fun T.extension() {} + +fun use(p: Any?) {} + +fun test1() { + a { + this.get(0).extension() + use(this.get(0)::extension) + use(it::extension) + } +} + + +fun test2() { + a { + val v = this.get(0) + v.extension() + use(v::extension) + use(it::extension) + } +} + +fun test3() { + operator fun T.getValue(thisRef: Any?, prop: Any?): T = this + a { + val v by this.get(0) + v.extension() + use(v::extension) + use(it::extension) + } +} + +class Box(val t: TIn) + +fun test4() { + operator fun T.provideDelegate(thisRef: Any?, prop: Any?): Box = Box(this) + operator fun Box.getValue(thisRef: Any?, prop: Any?): T = this.t + a { + val v by this.get(0) + v.extension() + use(v::extension) + use(it::extension) + } +} + +fun b(lambda: R.(List) -> Unit) {} + +fun test5() { + + operator fun T.invoke(): T = this + b { + extension() + this().extension() + use(::extension) + } +} + +val T.genericLambda: T.((T) -> Unit) -> Unit get() = {} + +fun test6() { + b { + extension() + genericLambda { } + genericLambda { it.extension() } + use(::extension) + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestrictionDisabled.kt b/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestrictionDisabled.kt new file mode 100644 index 00000000000..38f5c9cbc8d --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestrictionDisabled.kt @@ -0,0 +1,73 @@ +// WITH_STDLIB +// LANGUAGE: +NoBuilderInferenceWithoutAnnotationRestriction +// SKIP_TXT + +fun a(lambda: List.(R) -> Unit) {} + +fun T.extension() {} + +fun use(p: Any?) {} + +fun test1() { + a { + this.get(0).extension() + use(this.get(0)::extension) + use(it::extension) + } +} + + +fun test2() { + a { + val v = this.get(0) + v.extension() + use(v::extension) + use(it::extension) + } +} + +fun test3() { + operator fun T.getValue(thisRef: Any?, prop: Any?): T = this + a { + val v by this.get(0) + v.extension() + use(v::extension) + use(it::extension) + } +} + +class Box(val t: TIn) + +fun test4() { + operator fun T.provideDelegate(thisRef: Any?, prop: Any?): Box = Box(this) + operator fun Box.getValue(thisRef: Any?, prop: Any?): T = this.t + a { + val v by this.get(0) + v.extension() + use(v::extension) + use(it::extension) + } +} + +fun b(lambda: R.(List) -> Unit) {} + +fun test5() { + + operator fun T.invoke(): T = this + b { + extension() + this().extension() + use(::extension) + } +} + +val T.genericLambda: T.((T) -> Unit) -> Unit get() = {} + +fun test6() { + b { + extension() + genericLambda { } + genericLambda { it.extension() } + use(::extension) + } +} \ 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 77441d80500..2b47bf1aff4 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 @@ -14631,6 +14631,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { public void testRenderingStubTypes() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/renderingStubTypes.kt"); } + + @Test + @TestMetadata("stubTypeReceiverRestriction.kt") + public void testStubTypeReceiverRestriction() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestriction.kt"); + } + + @Test + @TestMetadata("stubTypeReceiverRestrictionDisabled.kt") + public void testStubTypeReceiverRestrictionDisabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/stubTypeReceiverRestrictionDisabled.kt"); + } } }