[FE 1.0] Don't fail on calls of functions with contracts from object
^KT-51704 Fixed
This commit is contained in:
committed by
teamcity
parent
993021a71d
commit
4d5a4ccd6b
+6
@@ -35747,6 +35747,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionInCompanion.kt")
|
||||
public void testFunctionInCompanion() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/functionInCompanion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intersectingInfo.kt")
|
||||
public void testIntersectingInfo() throws Exception {
|
||||
|
||||
+6
@@ -35747,6 +35747,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionInCompanion.kt")
|
||||
public void testFunctionInCompanion() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/functionInCompanion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intersectingInfo.kt")
|
||||
public void testIntersectingInfo() throws Exception {
|
||||
|
||||
+6
@@ -35747,6 +35747,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionInCompanion.kt")
|
||||
public void testFunctionInCompanion() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/functionInCompanion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intersectingInfo.kt")
|
||||
public void testIntersectingInfo() throws Exception {
|
||||
|
||||
+36
-7
@@ -20,8 +20,11 @@ import org.jetbrains.kotlin.contracts.model.*
|
||||
import org.jetbrains.kotlin.contracts.model.structure.*
|
||||
import org.jetbrains.kotlin.contracts.model.visitors.Reducer
|
||||
import org.jetbrains.kotlin.contracts.model.visitors.Substitutor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueDescriptor
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
class SubstitutingFunctor(
|
||||
@@ -31,13 +34,7 @@ class SubstitutingFunctor(
|
||||
override fun doInvocation(arguments: List<Computation>, typeSubstitution: ESTypeSubstitution, reducer: Reducer): List<ESEffect> {
|
||||
if (basicEffects.isEmpty()) return emptyList()
|
||||
|
||||
val receiver =
|
||||
listOfNotNull(ownerFunction.dispatchReceiverParameter?.toESVariable(), ownerFunction.extensionReceiverParameter?.toESVariable())
|
||||
val parameters = receiver + ownerFunction.valueParameters.map { it.toESVariable() }
|
||||
|
||||
assert(parameters.size == arguments.size) {
|
||||
"Arguments and parameters size mismatch: arguments.size = ${arguments.size}, parameters.size = ${parameters.size}"
|
||||
}
|
||||
val parameters = computeParameters(arguments)
|
||||
|
||||
val substitutions = parameters.zip(arguments).toMap()
|
||||
val substitutor = Substitutor(substitutions, typeSubstitution, reducer)
|
||||
@@ -61,6 +58,38 @@ class SubstitutingFunctor(
|
||||
return substitutedClauses
|
||||
}
|
||||
|
||||
private fun computeParameters(arguments: List<Computation>): List<ESVariable> {
|
||||
val dispatchReceiver = ownerFunction.dispatchReceiverParameter?.toESVariable()
|
||||
val extensionReceiver = ownerFunction.extensionReceiverParameter?.toESVariable()
|
||||
val receivers = listOfNotNull(dispatchReceiver, extensionReceiver)
|
||||
val valueParameters = ownerFunction.valueParameters.map { it.toESVariable() }
|
||||
val parameters = receivers + valueParameters
|
||||
|
||||
if (parameters.size == arguments.size) {
|
||||
return parameters
|
||||
}
|
||||
|
||||
fun fail(): Nothing {
|
||||
error("Arguments and parameters size mismatch: arguments.size = ${arguments.size}, parameters.size = ${parameters.size}")
|
||||
}
|
||||
|
||||
val dispatchParameterDescriptor = dispatchReceiver?.descriptor ?: fail()
|
||||
if (dispatchParameterDescriptor is ReceiverParameterDescriptor) {
|
||||
val classDescriptor = (dispatchParameterDescriptor.value as? ImplicitClassReceiver)?.classDescriptor ?: fail()
|
||||
if (classDescriptor.kind == ClassKind.OBJECT) {
|
||||
val parametersWithoutDispatch = buildList {
|
||||
extensionReceiver?.let { add(it) }
|
||||
addAll(valueParameters)
|
||||
}
|
||||
if (parametersWithoutDispatch.size != arguments.size) {
|
||||
fail()
|
||||
}
|
||||
return parametersWithoutDispatch
|
||||
}
|
||||
}
|
||||
fail()
|
||||
}
|
||||
|
||||
private fun combine(effect: SimpleEffect, substitutedCondition: ESEffect): ESEffect? {
|
||||
if (substitutedCondition !is ConditionalEffect) return null
|
||||
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// FIR_IDENTICAL
|
||||
// ISSUE: KT-51704
|
||||
|
||||
import Foo.Companion.checkSomethingCompanion
|
||||
import Bar.checkSomethingObject
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
||||
class Foo {
|
||||
companion object {
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun checkSomethingCompanion(condition: Boolean, message: String) {
|
||||
contract {
|
||||
returns() implies (condition)
|
||||
}
|
||||
if (!condition)
|
||||
throw Exception(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object Bar {
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun checkSomethingObject(condition: Boolean, message: String) {
|
||||
contract {
|
||||
returns() implies (condition)
|
||||
}
|
||||
if (!condition)
|
||||
throw Exception(message)
|
||||
}
|
||||
}
|
||||
|
||||
fun usage() {
|
||||
Foo.checkSomethingCompanion(1 == 2, "wat") // ok
|
||||
checkSomethingCompanion(1 == 2, "wat") // compiler crash
|
||||
Bar.checkSomethingObject(1 == 2, "wat") // ok
|
||||
checkSomethingObject(1 == 2, "wat") // compiler crash
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package
|
||||
|
||||
public fun usage(): kotlin.Unit
|
||||
|
||||
public object Bar {
|
||||
private constructor Bar()
|
||||
@kotlin.OptIn(markerClass = {kotlin.contracts.ExperimentalContracts::class}) public final fun checkSomethingObject(/*0*/ condition: kotlin.Boolean, /*1*/ message: kotlin.String): kotlin.Unit
|
||||
Returns(WILDCARD) -> condition
|
||||
|
||||
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 Foo {
|
||||
public constructor Foo()
|
||||
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 companion object Companion {
|
||||
private constructor Companion()
|
||||
@kotlin.OptIn(markerClass = {kotlin.contracts.ExperimentalContracts::class}) public final fun checkSomethingCompanion(/*0*/ condition: kotlin.Boolean, /*1*/ message: kotlin.String): kotlin.Unit
|
||||
Returns(WILDCARD) -> condition
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+6
@@ -35837,6 +35837,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionInCompanion.kt")
|
||||
public void testFunctionInCompanion() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/functionInCompanion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intersectingInfo.kt")
|
||||
public void testIntersectingInfo() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user