Prohibit using references to this from outer scope in contract declarations
This commit is contained in:
+5
@@ -1174,6 +1174,11 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
|
|||||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("accessToOuterThis.kt")
|
||||||
|
public void testAccessToOuterThis() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/accessToOuterThis.kt");
|
||||||
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInErrors() throws Exception {
|
public void testAllFilesPresentInErrors() throws Exception {
|
||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-3
@@ -133,9 +133,18 @@ internal class PsiContractParserDispatcher(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor is ReceiverParameterDescriptor && descriptor.type.constructor.declarationDescriptor?.isFromContractDsl() == true) {
|
if (descriptor is ReceiverParameterDescriptor) {
|
||||||
collector.badDescription("only references to parameters are allowed. Did you miss label on <this>?", expression)
|
if (descriptor.type.constructor.declarationDescriptor?.isFromContractDsl() == true) {
|
||||||
return null
|
collector.badDescription("only references to parameters are allowed. Did you miss label on <this>?", expression)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val directReceiver = callContext.functionDescriptor.let {
|
||||||
|
it.extensionReceiverParameter ?: it.dispatchReceiverParameter
|
||||||
|
}
|
||||||
|
if (descriptor != directReceiver) {
|
||||||
|
collector.badDescription("only references to direct <this> are allowed", expression)
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (KotlinBuiltIns.isBoolean(descriptor.type))
|
return if (KotlinBuiltIns.isBoolean(descriptor.type))
|
||||||
|
|||||||
Vendored
+41
@@ -0,0 +1,41 @@
|
|||||||
|
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect +AllowContractsForNonOverridableMembers
|
||||||
|
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||||
|
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER -SENSELESS_COMPARISON
|
||||||
|
|
||||||
|
import kotlin.contracts.*
|
||||||
|
|
||||||
|
interface A
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
inner class Bar {
|
||||||
|
fun good() {
|
||||||
|
contract {
|
||||||
|
returns() implies (this@Bar != null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun badOuter() {
|
||||||
|
contract {
|
||||||
|
returns() implies (this@Foo != null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun badInner() {
|
||||||
|
contract {
|
||||||
|
returns() implies (this != null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun A?.goodWithReceiver() {
|
||||||
|
contract {
|
||||||
|
returns() implies (this@goodWithReceiver != null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun A?.badWithReceiver() {
|
||||||
|
contract {
|
||||||
|
returns() implies (this@Bar != null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect +AllowContractsForNonOverridableMembers
|
||||||
|
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||||
|
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER -SENSELESS_COMPARISON
|
||||||
|
|
||||||
|
import kotlin.contracts.*
|
||||||
|
|
||||||
|
interface A
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
inner class Bar {
|
||||||
|
fun good() {
|
||||||
|
contract {
|
||||||
|
returns() implies (this@Bar != null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun badOuter() {
|
||||||
|
contract {
|
||||||
|
returns() implies (<!ERROR_IN_CONTRACT_DESCRIPTION("only references to direct <this> are allowed")!>this@Foo<!> != null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun badInner() {
|
||||||
|
contract {
|
||||||
|
returns() implies (<!ERROR_IN_CONTRACT_DESCRIPTION("only references to parameters are allowed. Did you miss label on <this>?")!>this<!> != null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun A?.goodWithReceiver() {
|
||||||
|
contract {
|
||||||
|
returns() implies (this@goodWithReceiver != null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun A?.badWithReceiver() {
|
||||||
|
contract {
|
||||||
|
returns() implies (<!ERROR_IN_CONTRACT_DESCRIPTION("only references to direct <this> are allowed")!>this@Bar<!> != null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public interface 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 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 final inner class Bar {
|
||||||
|
public constructor Bar()
|
||||||
|
public final fun badInner(): kotlin.Unit
|
||||||
|
public final fun badOuter(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final fun good(): kotlin.Unit
|
||||||
|
Returns(WILDCARD) -> <this> != null
|
||||||
|
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
public final fun A?.badWithReceiver(): kotlin.Unit
|
||||||
|
public final fun A?.goodWithReceiver(): kotlin.Unit
|
||||||
|
Returns(WILDCARD) -> <this> != null
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -1175,6 +1175,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
|
|||||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("accessToOuterThis.kt")
|
||||||
|
public void testAccessToOuterThis() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/accessToOuterThis.kt");
|
||||||
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInErrors() throws Exception {
|
public void testAllFilesPresentInErrors() throws Exception {
|
||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
}
|
}
|
||||||
|
|||||||
compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java
Generated
+5
@@ -1175,6 +1175,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
|
|||||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("accessToOuterThis.kt")
|
||||||
|
public void testAccessToOuterThis() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors/accessToOuterThis.kt");
|
||||||
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInErrors() throws Exception {
|
public void testAllFilesPresentInErrors() throws Exception {
|
||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/dsl/errors"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user