JS: prohibit to implement functional interfaces. See KT-15136
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
//KT-3190 Compiler crash if function called 'invoke' calls a closure
|
//KT-3190 Compiler crash if function called 'invoke' calls a closure
|
||||||
|
// IGNORE_BACKEND: JS
|
||||||
|
// JS backend does not allow to implement Function{N} interfaces
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val test = Cached<Int,Int>({ it + 2 })
|
val test = Cached<Int,Int>({ it + 2 })
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
//KT-3822 Compiler crashes when use invoke convention with `this` in class which extends Function0<T>
|
//KT-3822 Compiler crashes when use invoke convention with `this` in class which extends Function0<T>
|
||||||
|
// IGNORE_BACKEND: JS
|
||||||
|
// JS backend does not allow to implement Function{N} interfaces
|
||||||
|
|
||||||
class B() : Function0<Boolean> {
|
class B() : Function0<Boolean> {
|
||||||
override fun invoke() = true
|
override fun invoke() = true
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
abstract class <!IMPLEMENTING_FUNCTION_INTERFACE!>A<!> : () -> Unit
|
||||||
|
|
||||||
|
<!IMPLEMENTING_FUNCTION_INTERFACE!>object B<!> : (String, Int) -> Long {
|
||||||
|
override fun invoke(a: String, B: Int) = 23L
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class <!IMPLEMENTING_FUNCTION_INTERFACE!>C<!> : kotlin.Function1<Any, Int>
|
||||||
|
|
||||||
|
abstract class <!IMPLEMENTING_FUNCTION_INTERFACE!>D<!> : C()
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public abstract class A : () -> kotlin.Unit {
|
||||||
|
public constructor 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 abstract override /*1*/ /*fake_override*/ fun invoke(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public object B : (kotlin.String, kotlin.Int) -> kotlin.Long {
|
||||||
|
private constructor B()
|
||||||
|
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*/ fun invoke(/*0*/ a: kotlin.String, /*1*/ B: kotlin.Int): kotlin.Long
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class C : (kotlin.Any) -> kotlin.Int {
|
||||||
|
public constructor C()
|
||||||
|
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 abstract override /*1*/ /*fake_override*/ fun invoke(/*0*/ p1: kotlin.Any): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class D : C {
|
||||||
|
public constructor D()
|
||||||
|
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 abstract override /*1*/ /*fake_override*/ fun invoke(/*0*/ p1: kotlin.Any): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -36,6 +36,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithJsStdLib"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithJsStdLib"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("implementingFunction.kt")
|
||||||
|
public void testImplementingFunction() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/implementingFunction.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("localClassMetadata.kt")
|
@TestMetadata("localClassMetadata.kt")
|
||||||
public void testLocalClassMetadata() throws Exception {
|
public void testLocalClassMetadata() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/localClassMetadata.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/localClassMetadata.kt");
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("IMPLEMENTING_FUNCTION_INTERFACE")
|
||||||
package kotlin.reflect
|
package kotlin.reflect
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
@@ -71,6 +71,7 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
|
|||||||
put(ErrorsJs.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS, "Overriding `external` function with optional parameters")
|
put(ErrorsJs.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS, "Overriding `external` function with optional parameters")
|
||||||
put(ErrorsJs.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE,
|
put(ErrorsJs.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE,
|
||||||
"Overriding `external` function with optional parameters by declaration from superclass: {0}", Renderers.COMPACT)
|
"Overriding `external` function with optional parameters by declaration from superclass: {0}", Renderers.COMPACT)
|
||||||
|
put(ErrorsJs.IMPLEMENTING_FUNCTION_INTERFACE, "Implementing function interface is prohibited in JavaScript")
|
||||||
|
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement;
|
|||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.kotlin.diagnostics.*;
|
import org.jetbrains.kotlin.diagnostics.*;
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration;
|
import org.jetbrains.kotlin.psi.KtDeclaration;
|
||||||
import org.jetbrains.kotlin.psi.KtElement;
|
import org.jetbrains.kotlin.psi.KtElement;
|
||||||
import org.jetbrains.kotlin.psi.KtExpression;
|
import org.jetbrains.kotlin.psi.KtExpression;
|
||||||
@@ -73,6 +74,8 @@ public interface ErrorsJs {
|
|||||||
DiagnosticFactory0.create(ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
|
DiagnosticFactory0.create(ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||||
DiagnosticFactory1<KtElement, FunctionDescriptor> OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE =
|
DiagnosticFactory1<KtElement, FunctionDescriptor> OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE =
|
||||||
DiagnosticFactory1.create(ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
|
DiagnosticFactory1.create(ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||||
|
DiagnosticFactory0<KtClassOrObject> IMPLEMENTING_FUNCTION_INTERFACE = DiagnosticFactory0.create(
|
||||||
|
ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||||
|
|
||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
Object _initializer = new Object() {
|
Object _initializer = new Object() {
|
||||||
|
|||||||
+13
-1
@@ -16,14 +16,20 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.resolve.diagnostics
|
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
|
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||||
|
|
||||||
object JsInheritanceChecker : SimpleDeclarationChecker {
|
object JsInheritanceChecker : SimpleDeclarationChecker {
|
||||||
override fun check(
|
override fun check(
|
||||||
@@ -44,6 +50,12 @@ object JsInheritanceChecker : SimpleDeclarationChecker {
|
|||||||
declaration, fakeOverriddenMethod))
|
declaration, fakeOverriddenMethod))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (descriptor is ClassDescriptor &&
|
||||||
|
descriptor.defaultType.immediateSupertypes().any { it.isBuiltinFunctionalTypeOrSubtype }
|
||||||
|
) {
|
||||||
|
diagnosticHolder.report(ErrorsJs.IMPLEMENTING_FUNCTION_INTERFACE.on(declaration as KtClassOrObject))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isOverridingExternalWithOptionalParams(function: FunctionDescriptor): Boolean {
|
private fun isOverridingExternalWithOptionalParams(function: FunctionDescriptor): Boolean {
|
||||||
|
|||||||
+14
-2
@@ -8870,7 +8870,13 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
@TestMetadata("kt3190.kt")
|
@TestMetadata("kt3190.kt")
|
||||||
public void testKt3190() throws Exception {
|
public void testKt3190() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/invoke/kt3190.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/invoke/kt3190.kt");
|
||||||
doTest(fileName);
|
try {
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
catch (Throwable ignore) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("kt3297.kt")
|
@TestMetadata("kt3297.kt")
|
||||||
@@ -8906,7 +8912,13 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
@TestMetadata("kt3822invokeOnThis.kt")
|
@TestMetadata("kt3822invokeOnThis.kt")
|
||||||
public void testKt3822invokeOnThis() throws Exception {
|
public void testKt3822invokeOnThis() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/invoke/kt3822invokeOnThis.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/invoke/kt3822invokeOnThis.kt");
|
||||||
doTest(fileName);
|
try {
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
catch (Throwable ignore) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user