Approximate captured type before mapping

#KT-7415 Fixed
This commit is contained in:
Denis Zharkov
2016-01-27 14:39:35 +03:00
parent 5b0fdcb3fe
commit 36f21932bb
4 changed files with 32 additions and 19 deletions
@@ -83,6 +83,7 @@ import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeProjection;
import org.jetbrains.kotlin.types.TypeUtils;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import org.jetbrains.kotlin.types.typesApproximation.CapturedTypeApproximationKt;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes;
@@ -2452,19 +2453,19 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
TypeParameterMappings mappings = new TypeParameterMappings();
for (Map.Entry<TypeParameterDescriptor, KotlinType> entry : typeArguments.entrySet()) {
TypeParameterDescriptor key = entry.getKey();
KotlinType type = TypeUtils.uncaptureTypeForInlineMapping(entry.getValue());
KotlinType type = entry.getValue();
boolean isReified = key.isReified() || InlineUtil.isArrayConstructorWithLambda(resolvedCall.getResultingDescriptor());
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
if (typeParameterAndReificationArgument == null) {
KotlinType approximatedType = CapturedTypeApproximationKt.approximateCapturedTypes(entry.getValue()).getUpper();
// type is not generic
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE);
Type asmType = typeMapper.mapTypeParameter(type, signatureWriter);
Type asmType = typeMapper.mapTypeParameter(approximatedType, signatureWriter);
mappings.addParameterMappingToType(
key.getName().getIdentifier(), type, asmType, signatureWriter.toString(), isReified
key.getName().getIdentifier(), approximatedType, asmType, signatureWriter.toString(), isReified
);
}
else {
@@ -0,0 +1,21 @@
// Basically this test checks that no captured type used as argument for signature mapping
class SwOperator<T>: Operator<List<T>, T>
interface Operator<R, T>
open class Inv<T>
class Obs<Y> {
inline fun <reified X> lift(lift: Operator<out X, in Y>) = object : Inv<X>() {}
}
fun box(): String {
val o: Obs<CharSequence> = Obs()
val inv = o.lift(SwOperator())
val signature = inv.javaClass.genericSuperclass.toString()
if (signature != "Inv<java.util.List<?>>") return "fail 1: $signature"
return "OK"
}
@@ -4555,6 +4555,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
doTestWithStdlib(fileName);
}
@TestMetadata("approximateCapturedTypes.kt")
public void testApproximateCapturedTypes() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/approximateCapturedTypes.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("checkcast.kt")
public void testCheckcast() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/checkcast.kt");
@@ -26,11 +26,9 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType;
import org.jetbrains.kotlin.resolve.calls.inference.CapturedTypeConstructor;
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstructor;
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
import java.util.*;
@@ -509,19 +507,6 @@ public class TypeUtils {
return typeParameterDescriptor != null && typeParameterDescriptor.isReified();
}
@NotNull
public static KotlinType uncaptureTypeForInlineMapping(@NotNull KotlinType type) {
TypeConstructor constructor = type.getConstructor();
if (constructor instanceof CapturedTypeConstructor) {
TypeProjection projection = ((CapturedTypeConstructor) constructor).getTypeProjection();
if (Variance.IN_VARIANCE == projection.getProjectionKind()) {
//in variance could be captured only for <T> or <T: Any?> declarations
return TypeUtilsKt.getBuiltIns(type).getNullableAnyType();
}
return uncaptureTypeForInlineMapping(projection.getType());
}
return type;
}
@Nullable
public static TypeParameterDescriptor getTypeParameterDescriptorOrNull(@NotNull KotlinType type) {
if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {