[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");
|
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
|
@Test
|
||||||
@TestMetadata("intersectingInfo.kt")
|
@TestMetadata("intersectingInfo.kt")
|
||||||
public void testIntersectingInfo() throws Exception {
|
public void testIntersectingInfo() throws Exception {
|
||||||
|
|||||||
+6
@@ -35747,6 +35747,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.kt");
|
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
|
@Test
|
||||||
@TestMetadata("intersectingInfo.kt")
|
@TestMetadata("intersectingInfo.kt")
|
||||||
public void testIntersectingInfo() throws Exception {
|
public void testIntersectingInfo() throws Exception {
|
||||||
|
|||||||
+6
@@ -35747,6 +35747,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.kt");
|
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
|
@Test
|
||||||
@TestMetadata("intersectingInfo.kt")
|
@TestMetadata("intersectingInfo.kt")
|
||||||
public void testIntersectingInfo() throws Exception {
|
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.structure.*
|
||||||
import org.jetbrains.kotlin.contracts.model.visitors.Reducer
|
import org.jetbrains.kotlin.contracts.model.visitors.Reducer
|
||||||
import org.jetbrains.kotlin.contracts.model.visitors.Substitutor
|
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.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueDescriptor
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
class SubstitutingFunctor(
|
class SubstitutingFunctor(
|
||||||
@@ -31,13 +34,7 @@ class SubstitutingFunctor(
|
|||||||
override fun doInvocation(arguments: List<Computation>, typeSubstitution: ESTypeSubstitution, reducer: Reducer): List<ESEffect> {
|
override fun doInvocation(arguments: List<Computation>, typeSubstitution: ESTypeSubstitution, reducer: Reducer): List<ESEffect> {
|
||||||
if (basicEffects.isEmpty()) return emptyList()
|
if (basicEffects.isEmpty()) return emptyList()
|
||||||
|
|
||||||
val receiver =
|
val parameters = computeParameters(arguments)
|
||||||
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 substitutions = parameters.zip(arguments).toMap()
|
val substitutions = parameters.zip(arguments).toMap()
|
||||||
val substitutor = Substitutor(substitutions, typeSubstitution, reducer)
|
val substitutor = Substitutor(substitutions, typeSubstitution, reducer)
|
||||||
@@ -61,6 +58,38 @@ class SubstitutingFunctor(
|
|||||||
return substitutedClauses
|
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? {
|
private fun combine(effect: SimpleEffect, substitutedCondition: ESEffect): ESEffect? {
|
||||||
if (substitutedCondition !is ConditionalEffect) return null
|
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");
|
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
|
@Test
|
||||||
@TestMetadata("intersectingInfo.kt")
|
@TestMetadata("intersectingInfo.kt")
|
||||||
public void testIntersectingInfo() throws Exception {
|
public void testIntersectingInfo() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user