new Out<in T>().produce() returns Any?

This commit is contained in:
Andrey Breslav
2011-03-23 17:06:45 +03:00
parent cd339fbb1b
commit a476377d35
5 changed files with 75 additions and 22 deletions
@@ -50,10 +50,12 @@ public class TypeSubstitutor {
if (value != null) {
assert constructor.getDeclarationDescriptor() instanceof TypeParameterDescriptor;
if (!allows(howThisTypeIsUsed, value.getProjectionKind())) {
throw new SubstitutionException("!!" + value.toString());
}
return value.getType();
return substitutionResult(substitutionContext, (TypeParameterDescriptor) constructor.getDeclarationDescriptor(), howThisTypeIsUsed, Variance.INVARIANT, value).getType();
//
// if (!allows(howThisTypeIsUsed, value.getProjectionKind())) {
// throw new SubstitutionException("!!" + value.toString());
// }
// return value.getType();
}
return specializeType(type, substitutionContext, howThisTypeIsUsed);
@@ -96,19 +98,11 @@ public class TypeSubstitutor {
if (projectionValue != null) {
assert typeToSubstituteIn.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor;
JetType typeValue = projectionValue.getType();
Variance projectionKindValue = projectionValue.getProjectionKind();
if (!allows(parameterVariance, passedProjectionKind)) {
return TypeUtils.makeStarProjection( correspondingTypeParameter);
return TypeUtils.makeStarProjection(correspondingTypeParameter);
}
if (!allows(effectiveContextVariance, projectionKindValue)) {
throw new SubstitutionException(""); // TODO : error message
}
Variance effectiveProjectionKindValue = passedProjectionKind == Variance.INVARIANT ? projectionKindValue : passedProjectionKind;
return new TypeProjection(effectiveProjectionKindValue, specializeType(typeValue, substitutionContext, effectiveContextVariance));
return substitutionResult(substitutionContext, correspondingTypeParameter, effectiveContextVariance, passedProjectionKind, projectionValue);
}
return new TypeProjection(
passedProjectionKind,
@@ -118,6 +112,51 @@ public class TypeSubstitutor {
effectiveContextVariance));
}
private TypeProjection substitutionResult(
Map<TypeConstructor, TypeProjection> substitutionContext,
TypeParameterDescriptor correspondingTypeParameter,
Variance effectiveContextVariance,
Variance passedProjectionKind,
TypeProjection value) throws SubstitutionException {
Variance projectionKindValue = value.getProjectionKind();
JetType typeValue = value.getType();
Variance effectiveProjectionKindValue = asymmetricOr(passedProjectionKind, projectionKindValue);
JetType effectiveTypeValue;
switch (effectiveContextVariance) {
case INVARIANT:
effectiveProjectionKindValue = projectionKindValue;
effectiveTypeValue = typeValue;
break;
case IN_VARIANCE:
if (projectionKindValue == Variance.OUT_VARIANCE) {
throw new SubstitutionException(""); // TODO
// effectiveProjectionKindValue = Variance.INVARIANT;
// effectiveTypeValue = JetStandardClasses.getNothingType();
}
else {
effectiveTypeValue = typeValue;
}
break;
case OUT_VARIANCE:
if (projectionKindValue == Variance.IN_VARIANCE) {
effectiveProjectionKindValue = Variance.INVARIANT;
effectiveTypeValue = correspondingTypeParameter.getBoundsAsType();
}
else {
effectiveTypeValue = typeValue;
}
break;
default:
throw new IllegalStateException(effectiveContextVariance.toString());
}
// if (!allows(effectiveContextVariance, projectionKindValue)) {
// throw new SubstitutionException(""); // TODO : error message
// }
//
return new TypeProjection(effectiveProjectionKindValue, specializeType(effectiveTypeValue, substitutionContext, effectiveContextVariance));
}
private static Variance asymmetricOr(Variance a, Variance b) {
return a == Variance.INVARIANT ? b : a;
}
@@ -10,6 +10,7 @@ import java.util.List;
*/
public class DescriptorUtil {
public static String renderPresentableText(DeclarationDescriptor declarationDescriptor) {
if (declarationDescriptor == null) return "<null>";
StringBuilder stringBuilder = new StringBuilder();
declarationDescriptor.accept(
new DeclarationDescriptorVisitor<Void, StringBuilder>() {
+3 -3
View File
@@ -34,11 +34,11 @@ fun testInOut() {
new Out<Int>().`Out.f`f()
(return : Out<out Int>).`Out.f`f()
(return : Out<in Int>).`!`f()
(return : Out<in Int>).`Out.f`f()
(return : Out<*>).`Out.f`f()
new Inv<Int>().`Inv.f`f(1)
(return : Inv<in Int>).`!`f(1)
(return : Inv<in Int>).`Inv.f`f(1)
(return : Inv<out Int>).`!`f(1)
(return : Inv<*>).`!`f(1)
@@ -48,7 +48,7 @@ fun testInOut() {
(return : Inv<*>).`!`inf(1)
new Inv<Int>().`Inv.outf`outf()
(return : Inv<in Int>).`Inv.outf`outf()`:std::Any?`
((return : Inv<in Int>).`Inv.outf`outf())`:std::Any`
(return : Inv<out Int>).`Inv.outf`outf()
(return : Inv<*>).`Inv.outf`outf()
@@ -27,11 +27,12 @@ public class ExpectedResolveData {
private final Map<Integer, String> positionToType = new HashMap<Integer, String>();
private final Map<String, DeclarationDescriptor> nameToDescriptor;
private final Map<String, PsiElement> nameToPsiElement;
// private final Map<String, JetType> nameToType;
public ExpectedResolveData(Map<String, DeclarationDescriptor> nameToDescriptor, Map<String, PsiElement> nameToPsiElement) {
public ExpectedResolveData(Map<String, DeclarationDescriptor> nameToDescriptor, Map<String, PsiElement> nameToPsiElement/*, Map<String, JetType> nameToType*/) {
this.nameToDescriptor = nameToDescriptor;
this.nameToPsiElement = nameToPsiElement;
// this.nameToType = nameToType;
}
public void extractData(final Document document) {
@@ -107,7 +108,18 @@ public class ExpectedResolveData {
if ("!".equals(name)) {
JetReferenceExpression referenceExpression = PsiTreeUtil.getParentOfType(element, JetReferenceExpression.class);
assertTrue("Must have been unresolved: " + referenceExpression.getText(), unresolvedReferences.contains(referenceExpression));
JetExpression statement = referenceExpression;
while (true) {
PsiElement parent = statement.getParent();
if (!(parent instanceof JetExpression)) break;
if (parent instanceof JetBlockExpression) break;
statement = (JetExpression) parent;
}
assertTrue(
"Must have been unresolved: " + referenceExpression.getText() +
" in " + statement.getText() +
" but was resolved to " + DescriptorUtil.renderPresentableText(bindingContext.resolveReferenceExpression(referenceExpression)),
unresolvedReferences.contains(referenceExpression));
continue;
}
@@ -160,7 +172,8 @@ public class ExpectedResolveData {
TypeConstructor expectedTypeConstructor;
if (typeName.startsWith("std::")) {
ClassDescriptor expectedClass = lib.getLibraryScope().getClass(typeName.substring(5));
assertNotNull("Expected class not found: " + typeName);
assertNotNull("Expected class not found: " + typeName, expectedClass);
expectedTypeConstructor = expectedClass.getTypeConstructor();
} else {
Integer declarationPosition = declarationToPosition.get(typeName);
@@ -333,7 +333,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
assertType("new Props<out Int>().p", "Int");
assertType("new Props<Properties>().p.p", "Int");
assertErrorType("(return : Props<in Int>).p");
assertType("(return : Props<in Int>).p", "Any?");
}
public void testOverloads() throws Exception {