Provide fallback flag for KT-19174
-Xno-exception-on-explicit-equals-for-boxed-null Also unify corresponding names.
This commit is contained in:
@@ -37,7 +37,7 @@ class Equals : IntrinsicMethod() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConsistentEquals(private val lhsType: Type) : IntrinsicMethod() {
|
class EqualsThrowingNpeForNullReceiver(private val lhsType: Type) : IntrinsicMethod() {
|
||||||
override fun toCallable(method: CallableMethod): Callable =
|
override fun toCallable(method: CallableMethod): Callable =
|
||||||
createBinaryIntrinsicCallable(
|
createBinaryIntrinsicCallable(
|
||||||
method.returnType,
|
method.returnType,
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class IntrinsicMethods {
|
|||||||
this(jvmTarget, true);
|
this(jvmTarget, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntrinsicMethods(JvmTarget jvmTarget, boolean useConsistentEqualsForPrimitiveWrappers) {
|
public IntrinsicMethods(JvmTarget jvmTarget, boolean shouldThrowNpeOnExplicitEqualsForBoxedNull) {
|
||||||
intrinsicsMap.registerIntrinsic(KOTLIN_JVM, RECEIVER_PARAMETER_FQ_NAME, "javaClass", -1, JavaClassProperty.INSTANCE);
|
intrinsicsMap.registerIntrinsic(KOTLIN_JVM, RECEIVER_PARAMETER_FQ_NAME, "javaClass", -1, JavaClassProperty.INSTANCE);
|
||||||
intrinsicsMap.registerIntrinsic(KOTLIN_JVM, KotlinBuiltIns.FQ_NAMES.kClass, "java", -1, new KClassJavaProperty());
|
intrinsicsMap.registerIntrinsic(KOTLIN_JVM, KotlinBuiltIns.FQ_NAMES.kClass, "java", -1, new KClassJavaProperty());
|
||||||
intrinsicsMap.registerIntrinsic(KotlinBuiltIns.FQ_NAMES.kCallable.toSafe(), null, "name", -1, new KCallableNameProperty());
|
intrinsicsMap.registerIntrinsic(KotlinBuiltIns.FQ_NAMES.kCallable.toSafe(), null, "name", -1, new KCallableNameProperty());
|
||||||
@@ -102,9 +102,9 @@ public class IntrinsicMethods {
|
|||||||
for (PrimitiveType type : PrimitiveType.values()) {
|
for (PrimitiveType type : PrimitiveType.values()) {
|
||||||
FqName typeFqName = type.getTypeFqName();
|
FqName typeFqName = type.getTypeFqName();
|
||||||
IntrinsicMethod equalsMethod;
|
IntrinsicMethod equalsMethod;
|
||||||
if (useConsistentEqualsForPrimitiveWrappers) {
|
if (shouldThrowNpeOnExplicitEqualsForBoxedNull) {
|
||||||
Type wrapperType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(JvmPrimitiveType.get(type).getWrapperFqName());
|
Type wrapperType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(JvmPrimitiveType.get(type).getWrapperFqName());
|
||||||
equalsMethod = new ConsistentEquals(wrapperType);
|
equalsMethod = new EqualsThrowingNpeForNullReceiver(wrapperType);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
equalsMethod = EQUALS;
|
equalsMethod = EQUALS;
|
||||||
|
|||||||
@@ -142,7 +142,11 @@ class GenerationState @JvmOverloads constructor(
|
|||||||
this.bindingContext, classBuilderMode, IncompatibleClassTrackerImpl(extraJvmDiagnosticsTrace),
|
this.bindingContext, classBuilderMode, IncompatibleClassTrackerImpl(extraJvmDiagnosticsTrace),
|
||||||
this.moduleName, isJvm8Target, isJvm8TargetWithDefaults
|
this.moduleName, isJvm8Target, isJvm8TargetWithDefaults
|
||||||
)
|
)
|
||||||
val intrinsics: IntrinsicMethods = IntrinsicMethods(target, languageVersionSettings.supportsFeature(LanguageFeature.ConsistentExplicitEqualsForPrimitiveWrappers))
|
val intrinsics: IntrinsicMethods = run {
|
||||||
|
val shouldUseConsistentEquals = languageVersionSettings.supportsFeature(LanguageFeature.ThrowNpeOnExplicitEqualsForBoxedNull) &&
|
||||||
|
!configuration.getBoolean(JVMConfigurationKeys.NO_EXCEPTION_ON_EXPLICIT_EQUALS_FOR_BOXED_NULL)
|
||||||
|
IntrinsicMethods(target, shouldUseConsistentEquals)
|
||||||
|
}
|
||||||
val samWrapperClasses: SamWrapperClasses = SamWrapperClasses(this)
|
val samWrapperClasses: SamWrapperClasses = SamWrapperClasses(this)
|
||||||
val inlineCycleReporter: InlineCycleReporter = InlineCycleReporter(diagnostics)
|
val inlineCycleReporter: InlineCycleReporter = InlineCycleReporter(diagnostics)
|
||||||
val mappingsClassesForWhenByEnum: MappingsClassesForWhenByEnum = MappingsClassesForWhenByEnum(this)
|
val mappingsClassesForWhenByEnum: MappingsClassesForWhenByEnum = MappingsClassesForWhenByEnum(this)
|
||||||
|
|||||||
+6
@@ -167,6 +167,12 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
|
|||||||
)
|
)
|
||||||
var jsr305: String? by FreezableVar(Jsr305State.DEFAULT.description)
|
var jsr305: String? by FreezableVar(Jsr305State.DEFAULT.description)
|
||||||
|
|
||||||
|
@Argument(
|
||||||
|
value = "-Xno-exception-on-explicit-equals-for-boxed-null",
|
||||||
|
description = "Do not throw NPE on explicit 'equals' call for null receiver of platform boxed primitive type"
|
||||||
|
)
|
||||||
|
var noExceptionOnExplicitEqualsForBoxedNull by FreezableVar(false)
|
||||||
|
|
||||||
// Paths to output directories for friend modules.
|
// Paths to output directories for friend modules.
|
||||||
var friendPaths: Array<String>? by FreezableVar(null)
|
var friendPaths: Array<String>? by FreezableVar(null)
|
||||||
|
|
||||||
|
|||||||
@@ -343,6 +343,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
|||||||
configuration.put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, arguments.noCallAssertions)
|
configuration.put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, arguments.noCallAssertions)
|
||||||
configuration.put(JVMConfigurationKeys.DISABLE_RECEIVER_ASSERTIONS, arguments.noReceiverAssertions)
|
configuration.put(JVMConfigurationKeys.DISABLE_RECEIVER_ASSERTIONS, arguments.noReceiverAssertions)
|
||||||
configuration.put(JVMConfigurationKeys.DISABLE_PARAM_ASSERTIONS, arguments.noParamAssertions)
|
configuration.put(JVMConfigurationKeys.DISABLE_PARAM_ASSERTIONS, arguments.noParamAssertions)
|
||||||
|
configuration.put(JVMConfigurationKeys.NO_EXCEPTION_ON_EXPLICIT_EQUALS_FOR_BOXED_NULL, arguments.noExceptionOnExplicitEqualsForBoxedNull);
|
||||||
configuration.put(JVMConfigurationKeys.DISABLE_OPTIMIZATION, arguments.noOptimize)
|
configuration.put(JVMConfigurationKeys.DISABLE_OPTIMIZATION, arguments.noOptimize)
|
||||||
configuration.put(JVMConfigurationKeys.INHERIT_MULTIFILE_PARTS, arguments.inheritMultifileParts)
|
configuration.put(JVMConfigurationKeys.INHERIT_MULTIFILE_PARTS, arguments.inheritMultifileParts)
|
||||||
configuration.put(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK, arguments.skipRuntimeVersionCheck)
|
configuration.put(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK, arguments.skipRuntimeVersionCheck)
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ public class JVMConfigurationKeys {
|
|||||||
CompilerConfigurationKey.create("disable not-null call receiver assertions");
|
CompilerConfigurationKey.create("disable not-null call receiver assertions");
|
||||||
public static final CompilerConfigurationKey<Boolean> DISABLE_PARAM_ASSERTIONS =
|
public static final CompilerConfigurationKey<Boolean> DISABLE_PARAM_ASSERTIONS =
|
||||||
CompilerConfigurationKey.create("disable not-null parameter assertions");
|
CompilerConfigurationKey.create("disable not-null parameter assertions");
|
||||||
|
public static final CompilerConfigurationKey<Boolean> NO_EXCEPTION_ON_EXPLICIT_EQUALS_FOR_BOXED_NULL =
|
||||||
|
CompilerConfigurationKey.create("do not throw NPE on explicit 'equals' call for null receiver of platform boxed primitive type");
|
||||||
public static final CompilerConfigurationKey<Boolean> DISABLE_OPTIMIZATION =
|
public static final CompilerConfigurationKey<Boolean> DISABLE_OPTIMIZATION =
|
||||||
CompilerConfigurationKey.create("disable optimization");
|
CompilerConfigurationKey.create("disable optimization");
|
||||||
public static final CompilerConfigurationKey<Boolean> INHERIT_MULTIFILE_PARTS =
|
public static final CompilerConfigurationKey<Boolean> INHERIT_MULTIFILE_PARTS =
|
||||||
|
|||||||
+2
@@ -14,6 +14,8 @@ where advanced options include:
|
|||||||
-Xload-builtins-from-dependencies
|
-Xload-builtins-from-dependencies
|
||||||
Load definitions of built-in declarations from module dependencies, instead of from the compiler
|
Load definitions of built-in declarations from module dependencies, instead of from the compiler
|
||||||
-Xno-call-assertions Don't generate not-null assertions for arguments of platform types
|
-Xno-call-assertions Don't generate not-null assertions for arguments of platform types
|
||||||
|
-Xno-exception-on-explicit-equals-for-boxed-null
|
||||||
|
Do not throw NPE on explicit 'equals' call for null receiver of platform boxed primitive type
|
||||||
-Xno-optimize Disable optimizations
|
-Xno-optimize Disable optimizations
|
||||||
-Xno-param-assertions Don't generate not-null assertions on parameters of methods accessible from Java
|
-Xno-param-assertions Don't generate not-null assertions on parameters of methods accessible from Java
|
||||||
-Xno-receiver-assertions Don't generate not-null assertion for extension receiver arguments of platform types
|
-Xno-receiver-assertions Don't generate not-null assertion for extension receiver arguments of platform types
|
||||||
|
|||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
// LANGUAGE_VERSION: 1.2
|
||||||
|
// KOTLIN_CONFIGURATION_FLAGS: +JVM.NO_EXCEPTION_ON_EXPLICIT_EQUALS_FOR_BOXED_NULL
|
||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// FILE: test.kt
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals(J.BOOL_NULL.equals(null), true)
|
||||||
|
assertEquals(J.CHAR_NULL.equals(null), true)
|
||||||
|
assertEquals(J.BYTE_NULL.equals(null), true)
|
||||||
|
assertEquals(J.SHORT_NULL.equals(null), true)
|
||||||
|
assertEquals(J.INT_NULL.equals(null), true)
|
||||||
|
assertEquals(J.LONG_NULL.equals(null), true)
|
||||||
|
assertEquals(J.FLOAT_NULL.equals(null), true)
|
||||||
|
assertEquals(J.DOUBLE_NULL.equals(null), true)
|
||||||
|
|
||||||
|
assertEquals(J.BOOL_NULL == null, true)
|
||||||
|
assertEquals(J.CHAR_NULL == null, true)
|
||||||
|
assertEquals(J.BYTE_NULL == null, true)
|
||||||
|
assertEquals(J.SHORT_NULL == null, true)
|
||||||
|
assertEquals(J.INT_NULL == null, true)
|
||||||
|
assertEquals(J.LONG_NULL == null, true)
|
||||||
|
assertEquals(J.FLOAT_NULL == null, true)
|
||||||
|
assertEquals(J.DOUBLE_NULL == null, true)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: J.java
|
||||||
|
public class J {
|
||||||
|
public static Boolean BOOL_NULL = null;
|
||||||
|
public static Character CHAR_NULL = null;
|
||||||
|
public static Byte BYTE_NULL = null;
|
||||||
|
public static Short SHORT_NULL = null;
|
||||||
|
public static Integer INT_NULL = null;
|
||||||
|
public static Long LONG_NULL = null;
|
||||||
|
public static Float FLOAT_NULL = null;
|
||||||
|
public static Double DOUBLE_NULL = null;
|
||||||
|
}
|
||||||
+6
@@ -12400,6 +12400,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("equalsNull_withExplicitFlag.kt")
|
||||||
|
public void testEqualsNull_withExplicitFlag() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/platformTypes/primitives/equalsNull_withExplicitFlag.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("hashCode.kt")
|
@TestMetadata("hashCode.kt")
|
||||||
public void testHashCode() throws Exception {
|
public void testHashCode() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/platformTypes/primitives/hashCode.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/platformTypes/primitives/hashCode.kt");
|
||||||
|
|||||||
@@ -12400,6 +12400,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("equalsNull_withExplicitFlag.kt")
|
||||||
|
public void testEqualsNull_withExplicitFlag() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/platformTypes/primitives/equalsNull_withExplicitFlag.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("hashCode.kt")
|
@TestMetadata("hashCode.kt")
|
||||||
public void testHashCode() throws Exception {
|
public void testHashCode() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/platformTypes/primitives/hashCode.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/platformTypes/primitives/hashCode.kt");
|
||||||
|
|||||||
@@ -12400,6 +12400,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("equalsNull_withExplicitFlag.kt")
|
||||||
|
public void testEqualsNull_withExplicitFlag() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/platformTypes/primitives/equalsNull_withExplicitFlag.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("hashCode.kt")
|
@TestMetadata("hashCode.kt")
|
||||||
public void testHashCode() throws Exception {
|
public void testHashCode() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/platformTypes/primitives/hashCode.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/platformTypes/primitives/hashCode.kt");
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ enum class LanguageFeature(
|
|||||||
LateinitLocalVariables(KOTLIN_1_2),
|
LateinitLocalVariables(KOTLIN_1_2),
|
||||||
InnerClassInEnumEntryClass(KOTLIN_1_2),
|
InnerClassInEnumEntryClass(KOTLIN_1_2),
|
||||||
CallableReferencesToClassMembersWithEmptyLHS(KOTLIN_1_2),
|
CallableReferencesToClassMembersWithEmptyLHS(KOTLIN_1_2),
|
||||||
ConsistentExplicitEqualsForPrimitiveWrappers(KOTLIN_1_2),
|
ThrowNpeOnExplicitEqualsForBoxedNull(KOTLIN_1_2),
|
||||||
JvmPackageName(KOTLIN_1_2),
|
JvmPackageName(KOTLIN_1_2),
|
||||||
|
|
||||||
RestrictionOfValReassignmentViaBackingField(KOTLIN_1_3),
|
RestrictionOfValReassignmentViaBackingField(KOTLIN_1_3),
|
||||||
|
|||||||
Reference in New Issue
Block a user