Store receiver parameter in JVM intrinsics map
To differentiate between "String?.plus" extension in builtins and "Iterable<*>.plus" extension in stdlib (they have the same owner, name and value parameter count)
This commit is contained in:
@@ -22,9 +22,12 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.CompileTimeConstantUtils;
|
import org.jetbrains.jet.lang.resolve.CompileTimeConstantUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
|
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||||
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||||
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
|
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -56,6 +59,9 @@ public class IntrinsicMethods {
|
|||||||
private static final EnumValueOf ENUM_VALUE_OF = new EnumValueOf();
|
private static final EnumValueOf ENUM_VALUE_OF = new EnumValueOf();
|
||||||
private static final ToString TO_STRING = new ToString();
|
private static final ToString TO_STRING = new ToString();
|
||||||
|
|
||||||
|
private static final FqName KOTLIN_ANY_FQ_NAME = DescriptorUtils.getFqNameSafe(KotlinBuiltIns.getInstance().getAny());
|
||||||
|
private static final FqName KOTLIN_STRING_FQ_NAME = DescriptorUtils.getFqNameSafe(KotlinBuiltIns.getInstance().getString());
|
||||||
|
|
||||||
private final Map<String, IntrinsicMethod> namedMethods = new HashMap<String, IntrinsicMethod>();
|
private final Map<String, IntrinsicMethod> namedMethods = new HashMap<String, IntrinsicMethod>();
|
||||||
private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator();
|
private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator();
|
||||||
private final IntrinsicsMap intrinsicsMap = new IntrinsicsMap();
|
private final IntrinsicsMap intrinsicsMap = new IntrinsicsMap();
|
||||||
@@ -111,11 +117,11 @@ public class IntrinsicMethods {
|
|||||||
declareIntrinsicFunction("CharSequence", "get", 1, new StringGetChar());
|
declareIntrinsicFunction("CharSequence", "get", 1, new StringGetChar());
|
||||||
declareIntrinsicFunction("String", "get", 1, new StringGetChar());
|
declareIntrinsicFunction("String", "get", 1, new StringGetChar());
|
||||||
|
|
||||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, "toString", 0, TO_STRING);
|
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KOTLIN_ANY_FQ_NAME, "toString", 0, TO_STRING);
|
||||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, "equals", 1, EQUALS);
|
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KOTLIN_ANY_FQ_NAME, "equals", 1, EQUALS);
|
||||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, "identityEquals", 1, IDENTITY_EQUALS);
|
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KOTLIN_ANY_FQ_NAME, "identityEquals", 1, IDENTITY_EQUALS);
|
||||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, "plus", 1, STRING_PLUS);
|
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KOTLIN_STRING_FQ_NAME, "plus", 1, STRING_PLUS);
|
||||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, "arrayOfNulls", 1, new NewArray());
|
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, null, "arrayOfNulls", 1, new NewArray());
|
||||||
|
|
||||||
for (PrimitiveType type : PrimitiveType.values()) {
|
for (PrimitiveType type : PrimitiveType.values()) {
|
||||||
String typeName = type.getTypeName().asString();
|
String typeName = type.getTypeName().asString();
|
||||||
@@ -171,7 +177,8 @@ public class IntrinsicMethods {
|
|||||||
int arity,
|
int arity,
|
||||||
@NotNull IntrinsicMethod implementation
|
@NotNull IntrinsicMethod implementation
|
||||||
) {
|
) {
|
||||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(className)), methodName, arity, implementation);
|
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(className)),
|
||||||
|
null, methodName, arity, implementation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ import com.google.common.collect.Maps;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||||
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
||||||
@@ -30,11 +32,13 @@ import java.util.Map;
|
|||||||
class IntrinsicsMap {
|
class IntrinsicsMap {
|
||||||
private static final class Key {
|
private static final class Key {
|
||||||
private final FqNameUnsafe owner;
|
private final FqNameUnsafe owner;
|
||||||
|
private final FqName receiverParameter;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final int valueParameterCount;
|
private final int valueParameterCount;
|
||||||
|
|
||||||
private Key(@NotNull FqNameUnsafe owner, @NotNull String name, int valueParameterCount) {
|
private Key(@NotNull FqNameUnsafe owner, @Nullable FqName receiverParameter, @NotNull String name, int valueParameterCount) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
|
this.receiverParameter = receiverParameter;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.valueParameterCount = valueParameterCount;
|
this.valueParameterCount = valueParameterCount;
|
||||||
}
|
}
|
||||||
@@ -49,6 +53,7 @@ class IntrinsicsMap {
|
|||||||
if (valueParameterCount != key.valueParameterCount) return false;
|
if (valueParameterCount != key.valueParameterCount) return false;
|
||||||
if (!name.equals(key.name)) return false;
|
if (!name.equals(key.name)) return false;
|
||||||
if (!owner.equals(key.owner)) return false;
|
if (!owner.equals(key.owner)) return false;
|
||||||
|
if (receiverParameter == null ? key.receiverParameter != null : !receiverParameter.equals(key.receiverParameter)) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -58,6 +63,7 @@ class IntrinsicsMap {
|
|||||||
int result = owner.hashCode();
|
int result = owner.hashCode();
|
||||||
result = 31 * result + name.hashCode();
|
result = 31 * result + name.hashCode();
|
||||||
result = 31 * result + valueParameterCount;
|
result = 31 * result + valueParameterCount;
|
||||||
|
result = 31 * result + (receiverParameter != null ? receiverParameter.hashCode() : 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,18 +83,35 @@ class IntrinsicsMap {
|
|||||||
/**
|
/**
|
||||||
* @param valueParameterCount -1 for property
|
* @param valueParameterCount -1 for property
|
||||||
*/
|
*/
|
||||||
public void registerIntrinsic(@NotNull FqName owner, @NotNull String name, int valueParameterCount, @NotNull IntrinsicMethod impl) {
|
public void registerIntrinsic(
|
||||||
intrinsicsMap.put(new Key(owner.toUnsafe(), name, valueParameterCount), impl);
|
@NotNull FqName owner,
|
||||||
|
@Nullable FqName receiverParameter,
|
||||||
|
@NotNull String name,
|
||||||
|
int valueParameterCount,
|
||||||
|
@NotNull IntrinsicMethod impl
|
||||||
|
) {
|
||||||
|
intrinsicsMap.put(new Key(owner.toUnsafe(), receiverParameter, name, valueParameterCount), impl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public IntrinsicMethod getIntrinsic(@NotNull CallableMemberDescriptor descriptor) {
|
public IntrinsicMethod getIntrinsic(@NotNull CallableMemberDescriptor descriptor) {
|
||||||
Key key = new Key(
|
Key key = new Key(
|
||||||
DescriptorUtils.getFqName(descriptor.getContainingDeclaration()),
|
DescriptorUtils.getFqName(descriptor.getContainingDeclaration()),
|
||||||
|
getReceiverParameterFqName(descriptor),
|
||||||
descriptor.getName().asString(),
|
descriptor.getName().asString(),
|
||||||
valueParameterCountForKey(descriptor)
|
valueParameterCountForKey(descriptor)
|
||||||
);
|
);
|
||||||
return intrinsicsMap.get(key);
|
return intrinsicsMap.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static FqName getReceiverParameterFqName(@NotNull CallableMemberDescriptor descriptor) {
|
||||||
|
ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
|
||||||
|
if (receiverParameter == null) return null;
|
||||||
|
|
||||||
|
ClassifierDescriptor classifier = receiverParameter.getType().getConstructor().getDeclarationDescriptor();
|
||||||
|
if (classifier == null) return null;
|
||||||
|
|
||||||
|
return DescriptorUtils.getFqNameSafe(classifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var x: MutableCollection<Int> = ArrayList()
|
||||||
|
x + ArrayList()
|
||||||
|
x += ArrayList()
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+5
@@ -1041,6 +1041,11 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/strings/forInString.kt");
|
doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/strings/forInString.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("stringPlusOnlyWorksOnString.kt")
|
||||||
|
public void testStringPlusOnlyWorksOnString() throws Exception {
|
||||||
|
doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/strings/stringPlusOnlyWorksOnString.kt");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/toArray")
|
@TestMetadata("compiler/testData/codegen/boxWithStdlib/toArray")
|
||||||
|
|||||||
Reference in New Issue
Block a user