Fix NPE on equals/hashCode of local function references
Anonymous classes for local function references implement their getOwner() as "return null" currently (KT-14291). To avoid NPE in this case, we now consider two local functions the same if their name and signature are equal. This is incorrect in general, but unlikely to cause major problems and is going to be fixed by KT-14291 eventually anyway #KT-17055
This commit is contained in:
+13
@@ -0,0 +1,13 @@
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
fun box(): String {
|
||||
fun bar() {}
|
||||
fun baz() {}
|
||||
|
||||
if (!::bar.equals(::bar)) return "Fail 1"
|
||||
if (::bar.hashCode() != ::bar.hashCode()) return "Fail 2"
|
||||
|
||||
if (::bar == ::baz) return "Fail 3"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+6
@@ -2040,6 +2040,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("equalsHashCode.kt")
|
||||
public void testEqualsHashCode() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/callableReference/function/local/equalsHashCode.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("extension.kt")
|
||||
public void testExtension() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/callableReference/function/local/extension.kt");
|
||||
|
||||
@@ -2040,6 +2040,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("equalsHashCode.kt")
|
||||
public void testEqualsHashCode() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/callableReference/function/local/equalsHashCode.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("extension.kt")
|
||||
public void testExtension() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/callableReference/function/local/extension.kt");
|
||||
|
||||
@@ -2040,6 +2040,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("equalsHashCode.kt")
|
||||
public void testEqualsHashCode() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/callableReference/function/local/equalsHashCode.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("extension.kt")
|
||||
public void testExtension() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/callableReference/function/local/extension.kt");
|
||||
|
||||
@@ -86,7 +86,7 @@ public class FunctionReference extends CallableReference implements FunctionBase
|
||||
if (obj instanceof FunctionReference) {
|
||||
FunctionReference other = (FunctionReference) obj;
|
||||
|
||||
return getOwner().equals(other.getOwner()) &&
|
||||
return (getOwner() == null ? other.getOwner() == null : getOwner().equals(other.getOwner())) &&
|
||||
getName().equals(other.getName()) &&
|
||||
getSignature().equals(other.getSignature()) &&
|
||||
Intrinsics.areEqual(getBoundReceiver(), other.getBoundReceiver());
|
||||
@@ -99,7 +99,7 @@ public class FunctionReference extends CallableReference implements FunctionBase
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (getOwner().hashCode() * 31 + getName().hashCode()) * 31 + getSignature().hashCode();
|
||||
return ((getOwner() == null ? 0 : getOwner().hashCode() * 31) + getName().hashCode()) * 31 + getSignature().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+12
@@ -2395,6 +2395,18 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("equalsHashCode.kt")
|
||||
public void testEqualsHashCode() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/callableReference/function/local/equalsHashCode.kt");
|
||||
try {
|
||||
doTest(fileName);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return;
|
||||
}
|
||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||
}
|
||||
|
||||
@TestMetadata("extension.kt")
|
||||
public void testExtension() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/callableReference/function/local/extension.kt");
|
||||
|
||||
Reference in New Issue
Block a user