KT-43525 forbid @JvmOverloads on mangled funs and hidden constructors

This commit is contained in:
Dmitry Petrov
2020-11-24 14:22:47 +03:00
parent ca78261d7f
commit 3a166f3592
18 changed files with 218 additions and 26 deletions
@@ -690,6 +690,11 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmOverloads/jvmOverloadsOnAnnotationClassConstructor_1_4.kt");
}
@TestMetadata("jvmOverloadsOnMangledFunctions.kt")
public void testJvmOverloadsOnMangledFunctions() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmOverloads/jvmOverloadsOnMangledFunctions.kt");
}
@TestMetadata("jvmOverloadsOnPrivate.kt")
public void testJvmOverloadsOnPrivate() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmOverloads/jvmOverloadsOnPrivate.kt");
@@ -13862,6 +13862,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inlineClasses/jvmFieldInInlineClassCompanion.kt");
}
@TestMetadata("jvmOverloadsOnTopLevelFunctionReturningInlineClassValue.kt")
public void testJvmOverloadsOnTopLevelFunctionReturningInlineClassValue() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/jvmOverloadsOnTopLevelFunctionReturningInlineClassValue.kt");
}
@TestMetadata("jvmStaticFunInInlineClassCompanion.kt")
public void testJvmStaticFunInInlineClassCompanion() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/jvmStaticFunInInlineClassCompanion.kt");
@@ -44,13 +44,15 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.resolve.jvm.isInlineClassThatRequiresMangling
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForParameterTypes
import org.jetbrains.kotlin.resolve.jvm.requiresFunctionNameManglingForReturnType
import org.jetbrains.kotlin.resolve.jvm.shouldHideConstructorDueToInlineClassTypeValueParameters
class LocalFunInlineChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (InlineUtil.isInline(descriptor) &&
declaration is KtNamedFunction &&
descriptor is FunctionDescriptor &&
descriptor.visibility == DescriptorVisibilities.LOCAL) {
descriptor.visibility == DescriptorVisibilities.LOCAL
) {
context.trace.report(Errors.NOT_YET_SUPPORTED_IN_INLINE.on(declaration, "Local inline functions"))
}
}
@@ -66,7 +68,8 @@ class JvmStaticChecker(jvmTarget: JvmTarget, languageVersionSettings: LanguageVe
if (declaration is KtNamedFunction ||
declaration is KtProperty ||
declaration is KtPropertyAccessor ||
declaration is KtParameter) {
declaration is KtParameter
) {
checkDeclaration(declaration, descriptor, context.trace)
}
}
@@ -85,7 +88,8 @@ class JvmStaticChecker(jvmTarget: JvmTarget, languageVersionSettings: LanguageVe
if (!insideObject || insideCompanionObjectInInterface) {
if (insideCompanionObjectInInterface &&
supportJvmStaticInInterface &&
descriptor is DeclarationDescriptorWithVisibility) {
descriptor is DeclarationDescriptorWithVisibility
) {
checkVisibility(descriptor, diagnosticHolder, declaration)
if (isLessJVM18) {
diagnosticHolder.report(ErrorsJvm.JVM_STATIC_IN_INTERFACE_1_6.on(declaration))
@@ -201,7 +205,7 @@ class SynchronizedAnnotationChecker : DeclarationChecker {
(descriptor.hasJvmStaticAnnotation() || descriptor.propertyIfAccessor.hasJvmStaticAnnotation()))
}
class OverloadsAnnotationChecker: DeclarationChecker {
class OverloadsAnnotationChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
descriptor.findJvmOverloadsAnnotation()?.let { annotation ->
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation)
@@ -218,26 +222,40 @@ class OverloadsAnnotationChecker: DeclarationChecker {
) {
val diagnosticHolder = context.trace
if (descriptor !is CallableDescriptor) {
return
} else if ((descriptor.containingDeclaration as? ClassDescriptor)?.kind == ClassKind.INTERFACE) {
diagnosticHolder.report(ErrorsJvm.OVERLOADS_INTERFACE.on(annotationEntry))
} else if (descriptor is FunctionDescriptor && descriptor.modality == Modality.ABSTRACT) {
diagnosticHolder.report(ErrorsJvm.OVERLOADS_ABSTRACT.on(annotationEntry))
} else if (DescriptorUtils.isLocal(descriptor)) {
diagnosticHolder.report(ErrorsJvm.OVERLOADS_LOCAL.on(annotationEntry))
} else if (descriptor.isAnnotationConstructor()) {
val diagnostic =
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses))
ErrorsJvm.OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR
else
ErrorsJvm.OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR_WARNING
if (descriptor !is CallableDescriptor) return
diagnosticHolder.report(diagnostic.on(annotationEntry))
} else if (!descriptor.visibility.isPublicAPI && descriptor.visibility != DescriptorVisibilities.INTERNAL) {
diagnosticHolder.report(ErrorsJvm.OVERLOADS_PRIVATE.on(annotationEntry))
} else if (descriptor.valueParameters.none { it.declaresDefaultValue() || it.isActualParameterWithCorrespondingExpectedDefault }) {
diagnosticHolder.report(ErrorsJvm.OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS.on(annotationEntry))
when {
(descriptor.containingDeclaration as? ClassDescriptor)?.kind == ClassKind.INTERFACE ->
diagnosticHolder.report(ErrorsJvm.OVERLOADS_INTERFACE.on(annotationEntry))
descriptor is FunctionDescriptor && descriptor.modality == Modality.ABSTRACT ->
diagnosticHolder.report(ErrorsJvm.OVERLOADS_ABSTRACT.on(annotationEntry))
DescriptorUtils.isLocal(descriptor) ->
diagnosticHolder.report(ErrorsJvm.OVERLOADS_LOCAL.on(annotationEntry))
descriptor.isAnnotationConstructor() -> {
val diagnostic =
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses))
ErrorsJvm.OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR
else
ErrorsJvm.OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR_WARNING
diagnosticHolder.report(diagnostic.on(annotationEntry))
}
!descriptor.visibility.isPublicAPI && descriptor.visibility != DescriptorVisibilities.INTERNAL ->
diagnosticHolder.report(ErrorsJvm.OVERLOADS_PRIVATE.on(annotationEntry))
descriptor.valueParameters.none { it.declaresDefaultValue() || it.isActualParameterWithCorrespondingExpectedDefault } ->
diagnosticHolder.report(ErrorsJvm.OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS.on(annotationEntry))
descriptor is SimpleFunctionDescriptor &&
(requiresFunctionNameManglingForParameterTypes(descriptor) || requiresFunctionNameManglingForReturnType(descriptor)) ->
diagnosticHolder.report(ErrorsJvm.OVERLOADS_ANNOTATION_MANGLED_FUNCTION.on(annotationEntry))
descriptor is ClassConstructorDescriptor && shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor) ->
diagnosticHolder.report(ErrorsJvm.OVERLOADS_ANNOTATION_HIDDEN_CONSTRUCTOR.on(annotationEntry))
}
}
}
@@ -245,8 +263,8 @@ class OverloadsAnnotationChecker: DeclarationChecker {
class TypeParameterBoundIsNotArrayChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val typeParameters = (descriptor as? CallableDescriptor)?.typeParameters
?: (descriptor as? ClassDescriptor)?.declaredTypeParameters
?: return
?: (descriptor as? ClassDescriptor)?.declaredTypeParameters
?: return
for (typeParameter in typeParameters) {
if (typeParameter.upperBounds.any { KotlinBuiltIns.isArray(it) || KotlinBuiltIns.isPrimitiveArray(it) }) {
@@ -52,8 +52,11 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
MAP.put(OVERLOADS_LOCAL, "'@JvmOverloads' annotation cannot be used on local declarations");
MAP.put(OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR_WARNING, "'@JvmOverloads' annotation on constructors of annotation classes is deprecated");
MAP.put(OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR, "'@JvmOverloads' annotation cannot be used on constructors of annotation classes");
MAP.put(OVERLOADS_ANNOTATION_HIDDEN_CONSTRUCTOR, "'@JvmOverloads' annotation cannot be used on constructors hidden by inline class rules");
MAP.put(OVERLOADS_ANNOTATION_MANGLED_FUNCTION, "'@JvmOverloads' annotation cannot be used on functions mangled by inline class rules");
MAP.put(INAPPLICABLE_JVM_NAME, "'@JvmName' annotation is not applicable to this declaration");
MAP.put(ILLEGAL_JVM_NAME, "Illegal JVM name");
MAP.put(VOLATILE_ON_VALUE, "'@Volatile' annotation cannot be used on immutable properties");
MAP.put(VOLATILE_ON_DELEGATE, "'@Volatile' annotation cannot be used on delegated properties");
MAP.put(SYNCHRONIZED_ON_ABSTRACT, "'@Synchronized' annotation cannot be used on abstract functions");
@@ -55,7 +55,8 @@ public interface ErrorsJvm {
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_LOCAL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR_WARNING = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_ANNOTATION_CLASS_CONSTRUCTOR = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_ANNOTATION_MANGLED_FUNCTION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_ANNOTATION_HIDDEN_CONSTRUCTOR = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtDeclaration> EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT = DiagnosticFactory0.create(ERROR, ABSTRACT_MODIFIER);
DiagnosticFactory0<KtDeclaration> EXTERNAL_DECLARATION_CANNOT_HAVE_BODY = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
@@ -0,0 +1,10 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
inline class Str(val s: String)
@JvmOverloads
fun test(so: String = "O", sk: String = "K") = Str(so + sk)
fun box(): String =
test().s
@@ -0,0 +1,6 @@
// WITH_RUNTIME
inline class Z(val x: Int)
@JvmOverloads
fun testTopLevelFunction(x: Int = 0): Z = Z(x)
@@ -0,0 +1,25 @@
@kotlin.Metadata
public final class JvmOverloadsOnTopLevelFunctionReturningInlineClassValueKt {
// source: 'jvmOverloadsOnTopLevelFunctionReturningInlineClassValue.kt'
public synthetic static method testTopLevelFunction$default(p0: int, p1: int, p2: java.lang.Object): int
public final static @kotlin.jvm.JvmOverloads method testTopLevelFunction(): int
public final static @kotlin.jvm.JvmOverloads method testTopLevelFunction(p0: int): int
}
@kotlin.Metadata
public final class Z {
// source: 'jvmOverloadsOnTopLevelFunctionReturningInlineClassValue.kt'
private final field x: int
private synthetic method <init>(p0: int): void
public synthetic final static method box-impl(p0: int): Z
public static method constructor-impl(p0: int): int
public method equals(p0: java.lang.Object): boolean
public static method equals-impl(p0: int, p1: java.lang.Object): boolean
public final static method equals-impl0(p0: int, p1: int): boolean
public final method getX(): int
public method hashCode(): int
public static method hashCode-impl(p0: int): int
public method toString(): java.lang.String
public static method toString-impl(p0: int): java.lang.String
public synthetic final method unbox-impl(): int
}
@@ -0,0 +1,30 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !LANGUAGE: +InlineClasses
inline class Z(val x: Int)
@JvmOverloads
fun testTopLevelFunction1(z: Z, x: Int = 0) {}
@JvmOverloads
fun testTopLevelFunction2(x: Int, z: Z = Z(0)) {}
@JvmOverloads
fun testTopLevelFunction3(x: Int = 0): Z = Z(x)
class C {
@JvmOverloads
constructor(i: Int, z: Z = Z(0))
@JvmOverloads
constructor(s: String, z: Z, i: Int = 0)
@JvmOverloads
fun testMemberFunction1(z: Z, x: Int = 0) {}
@JvmOverloads
fun testMemberFunction2(x: Int, z: Z = Z(0)) {}
@JvmOverloads
fun testMemberFunction3(x: Int = 0): Z = Z(x)
}
@@ -0,0 +1,30 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !LANGUAGE: +InlineClasses
inline class Z(val x: Int)
<!OVERLOADS_ANNOTATION_MANGLED_FUNCTION!>@JvmOverloads<!>
fun testTopLevelFunction1(z: Z, x: Int = 0) {}
<!OVERLOADS_ANNOTATION_MANGLED_FUNCTION!>@JvmOverloads<!>
fun testTopLevelFunction2(x: Int, z: Z = Z(0)) {}
@JvmOverloads
fun testTopLevelFunction3(x: Int = 0): Z = Z(x)
class C {
<!OVERLOADS_ANNOTATION_HIDDEN_CONSTRUCTOR!>@JvmOverloads<!>
constructor(i: Int, z: Z = Z(0))
<!OVERLOADS_ANNOTATION_HIDDEN_CONSTRUCTOR!>@JvmOverloads<!>
constructor(s: String, z: Z, i: Int = 0)
<!OVERLOADS_ANNOTATION_MANGLED_FUNCTION!>@JvmOverloads<!>
fun testMemberFunction1(z: Z, x: Int = 0) {}
<!OVERLOADS_ANNOTATION_MANGLED_FUNCTION!>@JvmOverloads<!>
fun testMemberFunction2(x: Int, z: Z = Z(0)) {}
<!OVERLOADS_ANNOTATION_MANGLED_FUNCTION!>@JvmOverloads<!>
fun testMemberFunction3(x: Int = 0): Z = Z(x)
}
@@ -0,0 +1,24 @@
package
@kotlin.jvm.JvmOverloads public fun testTopLevelFunction1(/*0*/ z: Z, /*1*/ x: kotlin.Int = ...): kotlin.Unit
@kotlin.jvm.JvmOverloads public fun testTopLevelFunction2(/*0*/ x: kotlin.Int, /*1*/ z: Z = ...): kotlin.Unit
@kotlin.jvm.JvmOverloads public fun testTopLevelFunction3(/*0*/ x: kotlin.Int = ...): Z
public final class C {
@kotlin.jvm.JvmOverloads public constructor C(/*0*/ i: kotlin.Int, /*1*/ z: Z = ...)
@kotlin.jvm.JvmOverloads public constructor C(/*0*/ s: kotlin.String, /*1*/ z: Z, /*2*/ i: kotlin.Int = ...)
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
@kotlin.jvm.JvmOverloads public final fun testMemberFunction1(/*0*/ z: Z, /*1*/ x: kotlin.Int = ...): kotlin.Unit
@kotlin.jvm.JvmOverloads public final fun testMemberFunction2(/*0*/ x: kotlin.Int, /*1*/ z: Z = ...): kotlin.Unit
@kotlin.jvm.JvmOverloads public final fun testMemberFunction3(/*0*/ x: kotlin.Int = ...): Z
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final inline class Z {
public constructor Z(/*0*/ x: kotlin.Int)
public final val x: kotlin.Int
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
@@ -690,6 +690,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmOverloads/jvmOverloadsOnAnnotationClassConstructor_1_4.kt");
}
@TestMetadata("jvmOverloadsOnMangledFunctions.kt")
public void testJvmOverloadsOnMangledFunctions() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmOverloads/jvmOverloadsOnMangledFunctions.kt");
}
@TestMetadata("jvmOverloadsOnPrivate.kt")
public void testJvmOverloadsOnPrivate() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmOverloads/jvmOverloadsOnPrivate.kt");
@@ -690,6 +690,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmOverloads/jvmOverloadsOnAnnotationClassConstructor_1_4.kt");
}
@TestMetadata("jvmOverloadsOnMangledFunctions.kt")
public void testJvmOverloadsOnMangledFunctions() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmOverloads/jvmOverloadsOnMangledFunctions.kt");
}
@TestMetadata("jvmOverloadsOnPrivate.kt")
public void testJvmOverloadsOnPrivate() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/annotations/jvmOverloads/jvmOverloadsOnPrivate.kt");
@@ -15262,6 +15262,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/jvmFieldInInlineClassCompanion.kt");
}
@TestMetadata("jvmOverloadsOnTopLevelFunctionReturningInlineClassValue.kt")
public void testJvmOverloadsOnTopLevelFunctionReturningInlineClassValue() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/jvmOverloadsOnTopLevelFunctionReturningInlineClassValue.kt");
}
@TestMetadata("jvmStaticFunInInlineClassCompanion.kt")
public void testJvmStaticFunInInlineClassCompanion() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/jvmStaticFunInInlineClassCompanion.kt");
@@ -982,6 +982,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/inlineClassWithManyKindsOfMembers.kt");
}
@TestMetadata("jvmOverloadsOnTopLevelFunctionReturningInlineClassValue.kt")
public void testJvmOverloadsOnTopLevelFunctionReturningInlineClassValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/jvmOverloadsOnTopLevelFunctionReturningInlineClassValue.kt");
}
@TestMetadata("memberExtensionProperty.kt")
public void testMemberExtensionProperty() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/memberExtensionProperty.kt");
@@ -15272,6 +15272,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/jvmFieldInInlineClassCompanion.kt");
}
@TestMetadata("jvmOverloadsOnTopLevelFunctionReturningInlineClassValue.kt")
public void testJvmOverloadsOnTopLevelFunctionReturningInlineClassValue() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/jvmOverloadsOnTopLevelFunctionReturningInlineClassValue.kt");
}
@TestMetadata("jvmStaticFunInInlineClassCompanion.kt")
public void testJvmStaticFunInInlineClassCompanion() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/jvmStaticFunInInlineClassCompanion.kt");
@@ -13862,6 +13862,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/jvmFieldInInlineClassCompanion.kt");
}
@TestMetadata("jvmOverloadsOnTopLevelFunctionReturningInlineClassValue.kt")
public void testJvmOverloadsOnTopLevelFunctionReturningInlineClassValue() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/jvmOverloadsOnTopLevelFunctionReturningInlineClassValue.kt");
}
@TestMetadata("jvmStaticFunInInlineClassCompanion.kt")
public void testJvmStaticFunInInlineClassCompanion() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/jvmStaticFunInInlineClassCompanion.kt");
@@ -952,6 +952,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/inlineClassWithManyKindsOfMembers.kt");
}
@TestMetadata("jvmOverloadsOnTopLevelFunctionReturningInlineClassValue.kt")
public void testJvmOverloadsOnTopLevelFunctionReturningInlineClassValue() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/jvmOverloadsOnTopLevelFunctionReturningInlineClassValue.kt");
}
@TestMetadata("memberExtensionProperty.kt")
public void testMemberExtensionProperty() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/inlineClasses/memberExtensionProperty.kt");