From 04846ca47a32d08444840fa80847a2d013034b32 Mon Sep 17 00:00:00 2001 From: Victor Petukhov Date: Thu, 19 Nov 2020 12:42:04 +0300 Subject: [PATCH] Rework checking constraints by presented `OnlyInputTypes` annotation in accordance with changed incorporation mechanism --- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 ++ .../model/NewConstraintSystemImpl.kt | 65 +++++++++++++------ .../checkingNotincorporatedInputTypes.kt | 6 ++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 ++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 ++ .../IrJsCodegenBoxES6TestGenerated.java | 5 ++ .../IrJsCodegenBoxTestGenerated.java | 5 ++ .../semantics/JsCodegenBoxTestGenerated.java | 5 ++ .../IrCodegenBoxWasmTestGenerated.java | 5 ++ 9 files changed, 86 insertions(+), 20 deletions(-) create mode 100644 compiler/testData/codegen/box/annotations/typeAnnotations/checkingNotincorporatedInputTypes.kt diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 80baaeb9c96..12fe003c7d0 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -271,6 +271,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/typeAnnotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @TestMetadata("checkingNotincorporatedInputTypes.kt") + public void testCheckingNotincorporatedInputTypes() throws Exception { + runTest("compiler/testData/codegen/box/annotations/typeAnnotations/checkingNotincorporatedInputTypes.kt"); + } + @TestMetadata("implicitReturn.kt") public void testImplicitReturn() throws Exception { runTest("compiler/testData/codegen/box/annotations/typeAnnotations/implicitReturn.kt"); diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt index fd4527e34ad..76f82239400 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt @@ -28,6 +28,8 @@ class NewConstraintSystemImpl( { private val utilContext = constraintInjector.constraintIncorporator.utilContext + private val postponedComputationsAfterAllVariablesAreFixed = mutableListOf<() -> Unit>() + private val storage = MutableConstraintStorage() private var state = State.BUILDING private val typeVariablesTransaction: MutableList = SmartList() @@ -321,42 +323,65 @@ class NewConstraintSystemImpl( } // KotlinConstraintSystemCompleter.Context - // TODO: simplify this: do only substitution a fixing type variable rather than running of subtyping and full incorporation - override fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker, position: FixVariableConstraintPosition<*>) { + override fun fixVariable( + variable: TypeVariableMarker, + resultType: KotlinTypeMarker, + position: FixVariableConstraintPosition<*> + ) = with(utilContext) { checkState(State.BUILDING, State.COMPLETION) - constraintInjector.addInitialEqualityConstraint( - this, variable.defaultType(), resultType, position - ) + constraintInjector.addInitialEqualityConstraint(this@NewConstraintSystemImpl, variable.defaultType(), resultType, position) val freshTypeConstructor = variable.freshTypeConstructor() - val variableWithConstraints = notFixedTypeVariables.remove(freshTypeConstructor) - checkOnlyInputTypesAnnotation(variableWithConstraints, resultType) - for (variableWithConstraint in notFixedTypeVariables.values) { - variableWithConstraint.removeConstrains { - it.type.contains { it.typeConstructor() == freshTypeConstructor } + for (otherVariableWithConstraints in notFixedTypeVariables.values) { + otherVariableWithConstraints.removeConstrains { otherConstraint -> + otherConstraint.type.contains { it.typeConstructor() == freshTypeConstructor } } } storage.fixedTypeVariables[freshTypeConstructor] = resultType + + postponeOnlyInputTypesCheck(variableWithConstraints, resultType) + + doPostponedComputationsIfAllVariablesAreFixed() } - private fun checkOnlyInputTypesAnnotation( + private fun ConstraintSystemUtilContext.postponeOnlyInputTypesCheck( variableWithConstraints: MutableVariableWithConstraints?, resultType: KotlinTypeMarker ) { - if (variableWithConstraints == null) return - val variableHasOnlyInputTypes = with(utilContext) { variableWithConstraints.typeVariable.hasOnlyInputTypesAttribute() } - if (!variableHasOnlyInputTypes) return - - val resultTypeIsInputType = variableWithConstraints.getProjectedInputCallTypes(utilContext).any { inputType -> - if (AbstractTypeChecker.equalTypes(this, resultType, inputType)) return@any true - val constructor = inputType.typeConstructor() - constructor.isIntersection() && constructor.supertypes().any { AbstractTypeChecker.equalTypes(this, resultType, it) } + if (variableWithConstraints != null && variableWithConstraints.typeVariable.hasOnlyInputTypesAttribute()) { + postponedComputationsAfterAllVariablesAreFixed.add { checkOnlyInputTypesAnnotation(variableWithConstraints, resultType) } } - if (!resultTypeIsInputType) { + } + + private fun doPostponedComputationsIfAllVariablesAreFixed() { + if (notFixedTypeVariables.isEmpty()) { + postponedComputationsAfterAllVariablesAreFixed.forEach { it() } + } + } + + private fun KotlinTypeMarker.substituteIfNecessary(substitutor: TypeSubstitutorMarker): KotlinTypeMarker { + val doesInputTypeContainsOtherVariables = this.contains { it.typeConstructor() is TypeVariableTypeConstructorMarker } + return if (doesInputTypeContainsOtherVariables) substitutor.safeSubstitute(this) else this + } + + private fun checkOnlyInputTypesAnnotation(variableWithConstraints: MutableVariableWithConstraints, resultType: KotlinTypeMarker) { + val substitutor = buildCurrentSubstitutor() + val isResultTypeEqualSomeInputType = variableWithConstraints.getProjectedInputCallTypes(utilContext).any { inputType -> + val inputTypeConstructor = inputType.typeConstructor() + + if (inputTypeConstructor.isIntersection()) { + inputTypeConstructor.supertypes().any { + AbstractTypeChecker.equalTypes(this, resultType, it.substituteIfNecessary(substitutor)) + } + } else { + AbstractTypeChecker.equalTypes(this, resultType, inputType.substituteIfNecessary(substitutor)) + } + } + if (!isResultTypeEqualSomeInputType) { addError(OnlyInputTypesDiagnostic(variableWithConstraints.typeVariable)) } } diff --git a/compiler/testData/codegen/box/annotations/typeAnnotations/checkingNotincorporatedInputTypes.kt b/compiler/testData/codegen/box/annotations/typeAnnotations/checkingNotincorporatedInputTypes.kt new file mode 100644 index 00000000000..0ecff0fc251 --- /dev/null +++ b/compiler/testData/codegen/box/annotations/typeAnnotations/checkingNotincorporatedInputTypes.kt @@ -0,0 +1,6 @@ +// IGNORE_BACKEND: JS_IR +// WITH_RUNTIME + +fun isImportedByDefault(c: String?, x: Set) = c?.let { it.toInt() } in x + +fun box(): String = "OK" diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index d1b41493916..6fbd66a341d 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -271,6 +271,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/typeAnnotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @TestMetadata("checkingNotincorporatedInputTypes.kt") + public void testCheckingNotincorporatedInputTypes() throws Exception { + runTest("compiler/testData/codegen/box/annotations/typeAnnotations/checkingNotincorporatedInputTypes.kt"); + } + @TestMetadata("implicitReturn.kt") public void testImplicitReturn() throws Exception { runTest("compiler/testData/codegen/box/annotations/typeAnnotations/implicitReturn.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 3f5e335323b..43df8c8d995 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -271,6 +271,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/typeAnnotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @TestMetadata("checkingNotincorporatedInputTypes.kt") + public void testCheckingNotincorporatedInputTypes() throws Exception { + runTest("compiler/testData/codegen/box/annotations/typeAnnotations/checkingNotincorporatedInputTypes.kt"); + } + @TestMetadata("implicitReturn.kt") public void testImplicitReturn() throws Exception { runTest("compiler/testData/codegen/box/annotations/typeAnnotations/implicitReturn.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index ded22676945..fe9e7de73fb 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -85,6 +85,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes public void testAllFilesPresentInTypeAnnotations() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/typeAnnotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true); } + + @TestMetadata("checkingNotincorporatedInputTypes.kt") + public void testCheckingNotincorporatedInputTypes() throws Exception { + runTest("compiler/testData/codegen/box/annotations/typeAnnotations/checkingNotincorporatedInputTypes.kt"); + } } } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index f4943aebaf4..20fbfa79448 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -85,6 +85,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { public void testAllFilesPresentInTypeAnnotations() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/typeAnnotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); } + + @TestMetadata("checkingNotincorporatedInputTypes.kt") + public void testCheckingNotincorporatedInputTypes() throws Exception { + runTest("compiler/testData/codegen/box/annotations/typeAnnotations/checkingNotincorporatedInputTypes.kt"); + } } } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 18ef3e5b394..8729285c012 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -85,6 +85,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { public void testAllFilesPresentInTypeAnnotations() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/typeAnnotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); } + + @TestMetadata("checkingNotincorporatedInputTypes.kt") + public void testCheckingNotincorporatedInputTypes() throws Exception { + runTest("compiler/testData/codegen/box/annotations/typeAnnotations/checkingNotincorporatedInputTypes.kt"); + } } } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 5d69afc5888..7e513f3ed55 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -80,6 +80,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest public void testAllFilesPresentInTypeAnnotations() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/typeAnnotations"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true); } + + @TestMetadata("checkingNotincorporatedInputTypes.kt") + public void testCheckingNotincorporatedInputTypes() throws Exception { + runTest("compiler/testData/codegen/box/annotations/typeAnnotations/checkingNotincorporatedInputTypes.kt"); + } } }