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
|
||||
// IGNORE_BACKEND: JS
|
||||
// JS backend does not allow to implement Function{N} interfaces
|
||||
|
||||
fun box(): String {
|
||||
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>
|
||||
// IGNORE_BACKEND: JS
|
||||
// JS backend does not allow to implement Function{N} interfaces
|
||||
|
||||
class B() : Function0<Boolean> {
|
||||
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);
|
||||
}
|
||||
|
||||
@TestMetadata("implementingFunction.kt")
|
||||
public void testImplementingFunction() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/implementingFunction.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("localClassMetadata.kt")
|
||||
public void testLocalClassMetadata() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/localClassMetadata.kt");
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:Suppress("IMPLEMENTING_FUNCTION_INTERFACE")
|
||||
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_WITH_FAKE,
|
||||
"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
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.*;
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration;
|
||||
import org.jetbrains.kotlin.psi.KtElement;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
@@ -73,6 +74,8 @@ public interface ErrorsJs {
|
||||
DiagnosticFactory0.create(ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
DiagnosticFactory1<KtElement, FunctionDescriptor> OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE =
|
||||
DiagnosticFactory1.create(ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
DiagnosticFactory0<KtClassOrObject> IMPLEMENTING_FUNCTION_INTERFACE = DiagnosticFactory0.create(
|
||||
ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
Object _initializer = new Object() {
|
||||
|
||||
+13
-1
@@ -16,14 +16,20 @@
|
||||
|
||||
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.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||
|
||||
object JsInheritanceChecker : SimpleDeclarationChecker {
|
||||
override fun check(
|
||||
@@ -44,6 +50,12 @@ object JsInheritanceChecker : SimpleDeclarationChecker {
|
||||
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 {
|
||||
|
||||
+14
-2
@@ -8870,7 +8870,13 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
@TestMetadata("kt3190.kt")
|
||||
public void testKt3190() throws Exception {
|
||||
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")
|
||||
@@ -8906,7 +8912,13 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
@TestMetadata("kt3822invokeOnThis.kt")
|
||||
public void testKt3822invokeOnThis() throws Exception {
|
||||
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