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.SimpleFunctionDescriptor;
|
||||
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.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
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 java.util.HashMap;
|
||||
@@ -56,6 +59,9 @@ public class IntrinsicMethods {
|
||||
private static final EnumValueOf ENUM_VALUE_OF = new EnumValueOf();
|
||||
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 static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator();
|
||||
private final IntrinsicsMap intrinsicsMap = new IntrinsicsMap();
|
||||
@@ -111,11 +117,11 @@ public class IntrinsicMethods {
|
||||
declareIntrinsicFunction("CharSequence", "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, "equals", 1, EQUALS);
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, "identityEquals", 1, IDENTITY_EQUALS);
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, "plus", 1, STRING_PLUS);
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, "arrayOfNulls", 1, new NewArray());
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KOTLIN_ANY_FQ_NAME, "toString", 0, TO_STRING);
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KOTLIN_ANY_FQ_NAME, "equals", 1, EQUALS);
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KOTLIN_ANY_FQ_NAME, "identityEquals", 1, IDENTITY_EQUALS);
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KOTLIN_STRING_FQ_NAME, "plus", 1, STRING_PLUS);
|
||||
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, null, "arrayOfNulls", 1, new NewArray());
|
||||
|
||||
for (PrimitiveType type : PrimitiveType.values()) {
|
||||
String typeName = type.getTypeName().asString();
|
||||
@@ -171,7 +177,8 @@ public class IntrinsicMethods {
|
||||
int arity,
|
||||
@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
|
||||
|
||||
@@ -20,7 +20,9 @@ import com.google.common.collect.Maps;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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.ReceiverParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
||||
@@ -30,11 +32,13 @@ import java.util.Map;
|
||||
class IntrinsicsMap {
|
||||
private static final class Key {
|
||||
private final FqNameUnsafe owner;
|
||||
private final FqName receiverParameter;
|
||||
private final String name;
|
||||
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.receiverParameter = receiverParameter;
|
||||
this.name = name;
|
||||
this.valueParameterCount = valueParameterCount;
|
||||
}
|
||||
@@ -49,6 +53,7 @@ class IntrinsicsMap {
|
||||
if (valueParameterCount != key.valueParameterCount) return false;
|
||||
if (!name.equals(key.name)) return false;
|
||||
if (!owner.equals(key.owner)) return false;
|
||||
if (receiverParameter == null ? key.receiverParameter != null : !receiverParameter.equals(key.receiverParameter)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -58,6 +63,7 @@ class IntrinsicsMap {
|
||||
int result = owner.hashCode();
|
||||
result = 31 * result + name.hashCode();
|
||||
result = 31 * result + valueParameterCount;
|
||||
result = 31 * result + (receiverParameter != null ? receiverParameter.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -77,18 +83,35 @@ class IntrinsicsMap {
|
||||
/**
|
||||
* @param valueParameterCount -1 for property
|
||||
*/
|
||||
public void registerIntrinsic(@NotNull FqName owner, @NotNull String name, int valueParameterCount, @NotNull IntrinsicMethod impl) {
|
||||
intrinsicsMap.put(new Key(owner.toUnsafe(), name, valueParameterCount), impl);
|
||||
public void registerIntrinsic(
|
||||
@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
|
||||
public IntrinsicMethod getIntrinsic(@NotNull CallableMemberDescriptor descriptor) {
|
||||
Key key = new Key(
|
||||
DescriptorUtils.getFqName(descriptor.getContainingDeclaration()),
|
||||
getReceiverParameterFqName(descriptor),
|
||||
descriptor.getName().asString(),
|
||||
valueParameterCountForKey(descriptor)
|
||||
);
|
||||
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");
|
||||
}
|
||||
|
||||
@TestMetadata("stringPlusOnlyWorksOnString.kt")
|
||||
public void testStringPlusOnlyWorksOnString() throws Exception {
|
||||
doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/strings/stringPlusOnlyWorksOnString.kt");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/toArray")
|
||||
|
||||
Reference in New Issue
Block a user