Do not write "? extends" and "? super" in immediate arguments of supertypes in Java generic signatures
This commit is contained in:
@@ -301,7 +301,7 @@ public class ClosureCodegen extends GenerationStateAware {
|
||||
BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS, true);
|
||||
typeMapper.writeFormalTypeParameters(Collections.<TypeParameterDescriptor>emptyList(), sw);
|
||||
sw.writeSuperclass();
|
||||
typeMapper.mapType(supertype, sw, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
typeMapper.mapType(supertype, sw, JetTypeMapperMode.SUPER_TYPE);
|
||||
sw.writeSuperclassEnd();
|
||||
|
||||
String signature = sw.makeJavaGenericSignature();
|
||||
|
||||
@@ -366,7 +366,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
signatureVisitor.writeClassEnd();
|
||||
}
|
||||
else {
|
||||
typeMapper.mapType(superClassType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
typeMapper.mapType(superClassType, signatureVisitor, JetTypeMapperMode.SUPER_TYPE);
|
||||
}
|
||||
signatureVisitor.writeSuperclassEnd();
|
||||
}
|
||||
@@ -381,7 +381,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||
if (isInterface(superClassDescriptor)) {
|
||||
signatureVisitor.writeInterface();
|
||||
Type jvmName = typeMapper.mapType(superType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
Type jvmName = typeMapper.mapType(superType, signatureVisitor, JetTypeMapperMode.SUPER_TYPE);
|
||||
signatureVisitor.writeInterfaceEnd();
|
||||
superInterfacesLinkedHashSet.add(jvmName.getInternalName());
|
||||
}
|
||||
|
||||
@@ -267,12 +267,13 @@ public class JetTypeMapper extends BindingTraceAware {
|
||||
}
|
||||
}
|
||||
|
||||
boolean projectionsAllowed = kind != JetTypeMapperMode.SUPER_TYPE;
|
||||
if (known != null) {
|
||||
if (kind == JetTypeMapperMode.VALUE) {
|
||||
return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
|
||||
}
|
||||
else if (kind == JetTypeMapperMode.TYPE_PARAMETER) {
|
||||
return mapKnownAsmType(jetType, boxType(known), signatureVisitor, howThisTypeIsUsed, arrayParameter);
|
||||
else if (kind == JetTypeMapperMode.TYPE_PARAMETER || kind == JetTypeMapperMode.SUPER_TYPE) {
|
||||
return mapKnownAsmType(jetType, boxType(known), signatureVisitor, howThisTypeIsUsed, arrayParameter, projectionsAllowed);
|
||||
}
|
||||
else if (kind == JetTypeMapperMode.TRAIT_IMPL) {
|
||||
throw new IllegalStateException("TRAIT_IMPL is not possible for " + jetType);
|
||||
@@ -345,7 +346,7 @@ public class JetTypeMapper extends BindingTraceAware {
|
||||
asmType = descriptorAsmType;
|
||||
}
|
||||
|
||||
writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed);
|
||||
writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, projectionsAllowed);
|
||||
|
||||
checkValidType(asmType);
|
||||
return asmType;
|
||||
@@ -386,7 +387,8 @@ public class JetTypeMapper extends BindingTraceAware {
|
||||
BothSignatureWriter signatureVisitor,
|
||||
Type asmType,
|
||||
JetType jetType,
|
||||
Variance howThisTypeIsUsed
|
||||
Variance howThisTypeIsUsed,
|
||||
boolean projectionsAllowed
|
||||
) {
|
||||
if (signatureVisitor != null) {
|
||||
signatureVisitor.writeClassBegin(asmType);
|
||||
@@ -395,11 +397,13 @@ public class JetTypeMapper extends BindingTraceAware {
|
||||
for (TypeParameterDescriptor parameter : jetType.getConstructor().getParameters()) {
|
||||
TypeProjection argument = arguments.get(parameter.getIndex());
|
||||
|
||||
Variance projectionKind = getEffectiveVariance(
|
||||
parameter.getVariance(),
|
||||
argument.getProjectionKind(),
|
||||
howThisTypeIsUsed
|
||||
);
|
||||
Variance projectionKind = projectionsAllowed
|
||||
? getEffectiveVariance(
|
||||
parameter.getVariance(),
|
||||
argument.getProjectionKind(),
|
||||
howThisTypeIsUsed
|
||||
)
|
||||
: Variance.INVARIANT;
|
||||
signatureVisitor.writeTypeArgument(projectionKind);
|
||||
|
||||
mapType(argument.getType(), signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
|
||||
@@ -434,7 +438,7 @@ public class JetTypeMapper extends BindingTraceAware {
|
||||
@Nullable BothSignatureWriter signatureVisitor,
|
||||
@NotNull Variance howThisTypeIsUsed
|
||||
) {
|
||||
return mapKnownAsmType(jetType, asmType, signatureVisitor, howThisTypeIsUsed, false);
|
||||
return mapKnownAsmType(jetType, asmType, signatureVisitor, howThisTypeIsUsed, false, true);
|
||||
}
|
||||
|
||||
private Type mapKnownAsmType(
|
||||
@@ -442,7 +446,8 @@ public class JetTypeMapper extends BindingTraceAware {
|
||||
Type asmType,
|
||||
@Nullable BothSignatureWriter signatureVisitor,
|
||||
@NotNull Variance howThisTypeIsUsed,
|
||||
boolean arrayParameter
|
||||
boolean arrayParameter,
|
||||
boolean allowProjections
|
||||
) {
|
||||
if (signatureVisitor != null) {
|
||||
if (jetType.getArguments().isEmpty()) {
|
||||
@@ -452,7 +457,7 @@ public class JetTypeMapper extends BindingTraceAware {
|
||||
signatureVisitor.writeAsmType(asmType);
|
||||
}
|
||||
else {
|
||||
writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed);
|
||||
writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, allowProjections);
|
||||
}
|
||||
}
|
||||
checkValidType(asmType);
|
||||
|
||||
@@ -33,4 +33,9 @@ public enum JetTypeMapperMode {
|
||||
* jet.Int is mapped to Ljava/lang/Integer;
|
||||
*/
|
||||
TYPE_PARAMETER,
|
||||
/**
|
||||
* jet.Int is mapped to Ljava/lang/Integer;
|
||||
* No projections allowed in immediate arguments
|
||||
*/
|
||||
SUPER_TYPE
|
||||
}
|
||||
|
||||
@@ -9,15 +9,15 @@ fun A.baz() {}
|
||||
|
||||
fun box(): String {
|
||||
val f = "${::foo}"
|
||||
if (f != "jet.KFunctionImpl1<? super java.lang.String, ? extends jet.Unit>") return "Fail foo: $f"
|
||||
if (f != "jet.KFunctionImpl1<java.lang.String, jet.Unit>") return "Fail foo: $f"
|
||||
|
||||
val nameOfA = (A() as java.lang.Object).getClass().getName()
|
||||
|
||||
val g = "${A::bar}"
|
||||
if (g != "jet.KMemberFunctionImpl0<? super $nameOfA, ? extends java.lang.String>") return "Fail bar: $g"
|
||||
if (g != "jet.KMemberFunctionImpl0<$nameOfA, java.lang.String>") return "Fail bar: $g"
|
||||
|
||||
val h = "${A::baz}"
|
||||
if (h != "jet.KExtensionFunctionImpl0<? super $nameOfA, ? extends jet.Unit>") return "Fail baz: $h"
|
||||
if (h != "jet.KExtensionFunctionImpl0<$nameOfA, jet.Unit>") return "Fail baz: $h"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@@ -6,22 +6,22 @@ fun check(expected: String, obj: Any?) {
|
||||
|
||||
|
||||
fun box(): String {
|
||||
check("jet.FunctionImpl0<? extends jet.Unit>")
|
||||
check("jet.FunctionImpl0<jet.Unit>")
|
||||
{ () : Unit -> }
|
||||
check("jet.FunctionImpl0<? extends java.lang.Integer>")
|
||||
check("jet.FunctionImpl0<java.lang.Integer>")
|
||||
{ () : Int -> 42 }
|
||||
check("jet.FunctionImpl1<? super java.lang.String, ? extends java.lang.Long>")
|
||||
check("jet.FunctionImpl1<java.lang.String, java.lang.Long>")
|
||||
{ (s: String) : Long -> 42.toLong() }
|
||||
check("jet.FunctionImpl2<? super java.lang.Integer, ? super java.lang.Integer, ? extends jet.Unit>")
|
||||
check("jet.FunctionImpl2<java.lang.Integer, java.lang.Integer, jet.Unit>")
|
||||
{ (x: Int, y: Int) : Unit -> }
|
||||
|
||||
check("jet.ExtensionFunctionImpl0<? super java.lang.Integer, ? extends jet.Unit>")
|
||||
check("jet.ExtensionFunctionImpl0<java.lang.Integer, jet.Unit>")
|
||||
{ Int.() : Unit -> }
|
||||
check("jet.ExtensionFunctionImpl0<? super jet.Unit, ? extends java.lang.Integer>")
|
||||
check("jet.ExtensionFunctionImpl0<jet.Unit, java.lang.Integer>")
|
||||
{ Unit.() : Int -> 42 }
|
||||
check("jet.ExtensionFunctionImpl1<? super java.lang.String, ? super java.lang.String, ? extends java.lang.Long>")
|
||||
check("jet.ExtensionFunctionImpl1<java.lang.String, java.lang.String, java.lang.Long>")
|
||||
{ String.(s: String) : Long -> 42.toLong() }
|
||||
check("jet.ExtensionFunctionImpl2<? super java.lang.Integer, ? super java.lang.Integer, ? super java.lang.Integer, ? extends jet.Unit>")
|
||||
check("jet.ExtensionFunctionImpl2<java.lang.Integer, java.lang.Integer, java.lang.Integer, jet.Unit>")
|
||||
{ Int.(x: Int, y: Int) : Unit -> }
|
||||
|
||||
return "OK"
|
||||
|
||||
@@ -14,18 +14,22 @@ val stringParamFun = { (x: String) : Unit -> }
|
||||
val listFun = { (l: List<String>) : List<String> -> l }
|
||||
val mutableListFun = { (l: MutableList<Double>) : MutableList<Int> -> null!! }
|
||||
|
||||
trait In<in T>
|
||||
val funWithIn = { (x: In<String>) : Unit -> }
|
||||
|
||||
val extensionFun = { Any.() : Unit -> }
|
||||
val extensionWithArgFun = { Long.(x: Any) : Date -> Date() }
|
||||
|
||||
fun box(): String {
|
||||
assertGenericSuper("jet.FunctionImpl0<? extends jet.Unit>", unitFun)
|
||||
assertGenericSuper("jet.FunctionImpl0<? extends java.lang.Integer>", intFun)
|
||||
assertGenericSuper("jet.FunctionImpl1<? super java.lang.String, ? extends jet.Unit>", stringParamFun)
|
||||
assertGenericSuper("jet.FunctionImpl1<? super java.util.List<? extends java.lang.String>, ? extends java.util.List<? extends java.lang.String>>", listFun)
|
||||
assertGenericSuper("jet.FunctionImpl1<? super java.util.List<java.lang.Double>, ? extends java.util.List<java.lang.Integer>>", mutableListFun)
|
||||
|
||||
assertGenericSuper("jet.ExtensionFunctionImpl0<? super java.lang.Object, ? extends jet.Unit>", extensionFun)
|
||||
assertGenericSuper("jet.ExtensionFunctionImpl1<? super java.lang.Long, ? super java.lang.Object, ? extends java.util.Date>", extensionWithArgFun)
|
||||
|
||||
assertGenericSuper("jet.FunctionImpl0<jet.Unit>", unitFun)
|
||||
assertGenericSuper("jet.FunctionImpl0<java.lang.Integer>", intFun)
|
||||
assertGenericSuper("jet.FunctionImpl1<java.lang.String, jet.Unit>", stringParamFun)
|
||||
assertGenericSuper("jet.FunctionImpl1<java.util.List<? extends java.lang.String>, java.util.List<? extends java.lang.String>>", listFun)
|
||||
assertGenericSuper("jet.FunctionImpl1<java.util.List<java.lang.Double>, java.util.List<java.lang.Integer>>", mutableListFun)
|
||||
assertGenericSuper("jet.FunctionImpl1<In<? super java.lang.String>, jet.Unit>", funWithIn)
|
||||
|
||||
assertGenericSuper("jet.ExtensionFunctionImpl0<java.lang.Object, jet.Unit>", extensionFun)
|
||||
assertGenericSuper("jet.ExtensionFunctionImpl1<java.lang.Long, java.lang.Object, java.util.Date>", extensionWithArgFun)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
|
||||
trait Derived<A>: List<A>
|
||||
|
||||
// class: Derived
|
||||
// jvm signature: Derived
|
||||
// generic signature: <A:Ljava/lang/Object;>Ljava/lang/Object;Ljava/util/List<TA;>;
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
open class Base<A, in B, out C>
|
||||
class Derived<A, B, C>: Base<A, B, C>()
|
||||
|
||||
// class: Derived
|
||||
// jvm signature: Derived
|
||||
// generic signature: <A:Ljava/lang/Object;B:Ljava/lang/Object;C:Ljava/lang/Object;>LBase<TA;TB;TC;>;
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
trait Base<A, in B, out C>
|
||||
class Derived<A, B, C>: Base<A, B, C>
|
||||
|
||||
// class: Derived
|
||||
// jvm signature: Derived
|
||||
// generic signature: <A:Ljava/lang/Object;B:Ljava/lang/Object;C:Ljava/lang/Object;>Ljava/lang/Object;LBase<TA;TB;TC;>;
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
|
||||
trait Base<A, in B, out C>
|
||||
trait Intermediate<A>
|
||||
class Derived<A, B, C>: Intermediate<Base<A, B, C>>
|
||||
|
||||
// class: Derived
|
||||
// jvm signature: Derived
|
||||
// generic signature: <A:Ljava/lang/Object;B:Ljava/lang/Object;C:Ljava/lang/Object;>Ljava/lang/Object;LIntermediate<LBase<TA;-TB;+TC;>;>;
|
||||
@@ -186,6 +186,11 @@ public class WriteSignatureTestGenerated extends AbstractWriteSignatureTest {
|
||||
doTest("compiler/testData/writeSignature/declarationSiteVariance/InOfOutInOutPosition.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("MappedSupertypeWithVariance.kt")
|
||||
public void testMappedSupertypeWithVariance() throws Exception {
|
||||
doTest("compiler/testData/writeSignature/declarationSiteVariance/MappedSupertypeWithVariance.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("OutInInPosition.kt")
|
||||
public void testOutInInPosition() throws Exception {
|
||||
doTest("compiler/testData/writeSignature/declarationSiteVariance/OutInInPosition.kt");
|
||||
@@ -241,6 +246,21 @@ public class WriteSignatureTestGenerated extends AbstractWriteSignatureTest {
|
||||
doTest("compiler/testData/writeSignature/declarationSiteVariance/PropertySetterOut.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("SuperClassWithVariance.kt")
|
||||
public void testSuperClassWithVariance() throws Exception {
|
||||
doTest("compiler/testData/writeSignature/declarationSiteVariance/SuperClassWithVariance.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("SuperTraitWithVariance.kt")
|
||||
public void testSuperTraitWithVariance() throws Exception {
|
||||
doTest("compiler/testData/writeSignature/declarationSiteVariance/SuperTraitWithVariance.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("SuperTypeWithVarianceInArguments.kt")
|
||||
public void testSuperTypeWithVarianceInArguments() throws Exception {
|
||||
doTest("compiler/testData/writeSignature/declarationSiteVariance/SuperTypeWithVarianceInArguments.kt");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
|
||||
Reference in New Issue
Block a user