Change behavior of equals/hashCode on adapted function references

Function references are now equal if they refer to the same function,
and if the parameter/return type adaptation, which happens when a
reference is used where some function type is expected, is exactly the
same. This includes the number of expected positional parameters (which
can be affected by defaults/varargs), whether the coercion of vararg
parameter to Array type happened, and whether the coercion of return
type to Unit happened.

 #KT-37543 Fixed
This commit is contained in:
Alexander Udalov
2020-03-16 22:26:46 +01:00
committed by Alexander Udalov
parent c344b85d4e
commit 3269a7e693
24 changed files with 942 additions and 22 deletions
@@ -62,20 +62,16 @@ public abstract class CallableReference implements KCallable, Serializable {
@SinceKotlin(version = "1.1")
protected CallableReference(Object receiver) {
this(receiver, null, null, null, 0);
this(receiver, null, null, null, false);
}
/**
* @param flags Bitmask where bits represent the following flags:<br/>
* <li><ul>0 - the owner of this reference is a package, not a class.</ul></li>
*/
@SinceKotlin(version = "1.4")
protected CallableReference(Object receiver, Class owner, String name, String signature, int flags) {
protected CallableReference(Object receiver, Class owner, String name, String signature, boolean isTopLevel) {
this.receiver = receiver;
this.owner = owner;
this.name = name;
this.signature = signature;
this.isTopLevel = (flags & 1) == 1;
this.isTopLevel = isTopLevel;
}
protected abstract KCallable computeReflected();
@@ -13,8 +13,26 @@ import kotlin.reflect.KFunction;
public class FunctionReference extends CallableReference implements FunctionBase, KFunction {
private final int arity;
/**
* Bitmask where bits represent the following flags:<br/>
* <li>
* <ul>0 - whether the vararg to element parameter type conversion happened, i.e.<pre>
* fun target(vararg xs: Int) {}
* fun use(f: (Int, Int, Int) -> Unit) {}
* use(::target)
* </pre></ul>
* <ul>1 - whether coercion of return type to Unit happened, i.e.<pre>
* fun target(): Boolean = true
* fun use(f: () -> Unit) {}
* use(::target)
* </pre></ul>
* </li>
*/
@SinceKotlin(version = "1.4")
private final int flags;
public FunctionReference(int arity) {
this.arity = arity;
this(arity, NO_RECEIVER, null, null, null, 0);
}
@SinceKotlin(version = "1.1")
@@ -24,8 +42,9 @@ public class FunctionReference extends CallableReference implements FunctionBase
@SinceKotlin(version = "1.4")
public FunctionReference(int arity, Object receiver, Class owner, String name, String signature, int flags) {
super(receiver, owner, name, signature, flags);
super(receiver, owner, name, signature, (flags & 1) == 1);
this.arity = arity;
this.flags = flags >> 1;
}
@Override
@@ -81,9 +100,11 @@ public class FunctionReference extends CallableReference implements FunctionBase
if (obj instanceof FunctionReference) {
FunctionReference other = (FunctionReference) obj;
return (getOwner() == null ? other.getOwner() == null : getOwner().equals(other.getOwner())) &&
return Intrinsics.areEqual(getOwner(), other.getOwner()) &&
getName().equals(other.getName()) &&
getSignature().equals(other.getSignature()) &&
flags == other.flags &&
arity == other.arity &&
Intrinsics.areEqual(getBoundReceiver(), other.getBoundReceiver());
}
if (obj instanceof KFunction) {
@@ -22,7 +22,7 @@ public abstract class PropertyReference extends CallableReference implements KPr
@SinceKotlin(version = "1.4")
public PropertyReference(Object receiver, Class owner, String name, String signature, int flags) {
super(receiver, owner, name, signature, flags);
super(receiver, owner, name, signature, (flags & 1) == 1);
}
@Override