From a476377d35a0b0f2652945c85594786137f29220 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 23 Mar 2011 17:06:45 +0300 Subject: [PATCH] new Out().produce() returns Any? --- .../jet/lang/types/TypeSubstitutor.java | 67 +++++++++++++++---- .../jetbrains/jet/resolve/DescriptorUtil.java | 1 + idea/testData/resolve/Projections.jet | 6 +- .../jet/resolve/ExpectedResolveData.java | 21 ++++-- .../jet/types/JetTypeCheckerTest.java | 2 +- 5 files changed, 75 insertions(+), 22 deletions(-) diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java b/idea/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java index f6fbe822f8b..cdad2a3480a 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java @@ -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 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; } diff --git a/idea/src/org/jetbrains/jet/resolve/DescriptorUtil.java b/idea/src/org/jetbrains/jet/resolve/DescriptorUtil.java index fe771a90582..f7c3c09bf75 100644 --- a/idea/src/org/jetbrains/jet/resolve/DescriptorUtil.java +++ b/idea/src/org/jetbrains/jet/resolve/DescriptorUtil.java @@ -10,6 +10,7 @@ import java.util.List; */ public class DescriptorUtil { public static String renderPresentableText(DeclarationDescriptor declarationDescriptor) { + if (declarationDescriptor == null) return ""; StringBuilder stringBuilder = new StringBuilder(); declarationDescriptor.accept( new DeclarationDescriptorVisitor() { diff --git a/idea/testData/resolve/Projections.jet b/idea/testData/resolve/Projections.jet index 508e316931b..a008e2488d3 100644 --- a/idea/testData/resolve/Projections.jet +++ b/idea/testData/resolve/Projections.jet @@ -34,11 +34,11 @@ fun testInOut() { new Out().`Out.f`f() (return : Out).`Out.f`f() - (return : Out).`!`f() + (return : Out).`Out.f`f() (return : Out<*>).`Out.f`f() new Inv().`Inv.f`f(1) - (return : Inv).`!`f(1) + (return : Inv).`Inv.f`f(1) (return : Inv).`!`f(1) (return : Inv<*>).`!`f(1) @@ -48,7 +48,7 @@ fun testInOut() { (return : Inv<*>).`!`inf(1) new Inv().`Inv.outf`outf() - (return : Inv).`Inv.outf`outf()`:std::Any?` + ((return : Inv).`Inv.outf`outf())`:std::Any` (return : Inv).`Inv.outf`outf() (return : Inv<*>).`Inv.outf`outf() diff --git a/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java b/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java index 8f977e1fbcf..4164a38e86b 100644 --- a/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java +++ b/idea/tests/org/jetbrains/jet/resolve/ExpectedResolveData.java @@ -27,11 +27,12 @@ public class ExpectedResolveData { private final Map positionToType = new HashMap(); private final Map nameToDescriptor; private final Map nameToPsiElement; +// private final Map nameToType; - - public ExpectedResolveData(Map nameToDescriptor, Map nameToPsiElement) { + public ExpectedResolveData(Map nameToDescriptor, Map nameToPsiElement/*, Map 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); diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 8ffddb7550b..dc14cd3c830 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -333,7 +333,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { assertType("new Props().p", "Int"); assertType("new Props().p.p", "Int"); - assertErrorType("(return : Props).p"); + assertType("(return : Props).p", "Any?"); } public void testOverloads() throws Exception {