Projections prohibited in constructor type arguments
This commit is contained in:
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lexer.JetToken;
|
||||
|
||||
@@ -37,11 +38,16 @@ public class JetModifierList extends JetElement {
|
||||
}
|
||||
|
||||
public boolean hasModifier(JetToken token) {
|
||||
return getModifierNode(token) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ASTNode getModifierNode(JetToken token) {
|
||||
ASTNode node = getNode().getFirstChildNode();
|
||||
while (node != null) {
|
||||
if (node.getElementType() == token) return true;
|
||||
if (node.getElementType() == token) return node;
|
||||
node = node.getTreeNext();
|
||||
}
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
@@ -16,20 +17,14 @@ public class JetTypeProjection extends JetDeclaration {
|
||||
|
||||
@NotNull
|
||||
public JetProjectionKind getProjectionKind() {
|
||||
JetModifierList modifierList = getModifierList();
|
||||
if (modifierList != null) {
|
||||
if (modifierList.hasModifier(JetTokens.IN_KEYWORD)) {
|
||||
return JetProjectionKind.IN;
|
||||
}
|
||||
if (modifierList.hasModifier(JetTokens.OUT_KEYWORD)) {
|
||||
return JetProjectionKind.OUT;
|
||||
}
|
||||
}
|
||||
if (findChildByType(JetTokens.MUL) != null) {
|
||||
return JetProjectionKind.STAR;
|
||||
}
|
||||
ASTNode projectionNode = getProjectionNode();
|
||||
if (projectionNode == null) return JetProjectionKind.NONE;
|
||||
|
||||
return JetProjectionKind.NONE;
|
||||
if (projectionNode.getElementType() == JetTokens.IN_KEYWORD) return JetProjectionKind.IN;
|
||||
if (projectionNode.getElementType() == JetTokens.OUT_KEYWORD) return JetProjectionKind.OUT;
|
||||
if (projectionNode.getElementType() == JetTokens.MUL) return JetProjectionKind.STAR;
|
||||
|
||||
throw new IllegalStateException(projectionNode.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -41,4 +36,25 @@ public class JetTypeProjection extends JetDeclaration {
|
||||
public JetTypeReference getTypeReference() {
|
||||
return (JetTypeReference) findChildByType(JetNodeTypes.TYPE_REFERENCE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ASTNode getProjectionNode() {
|
||||
JetModifierList modifierList = getModifierList();
|
||||
if (modifierList != null) {
|
||||
ASTNode node = modifierList.getModifierNode(JetTokens.IN_KEYWORD);
|
||||
if (node != null) {
|
||||
return node;
|
||||
}
|
||||
node = modifierList.getModifierNode(JetTokens.OUT_KEYWORD);
|
||||
if (node != null) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
PsiElement star = findChildByType(JetTokens.MUL);
|
||||
if (star != null) {
|
||||
return star.getNode();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ public class JetTypeInferrer {
|
||||
|
||||
@Override
|
||||
public void visitJetElement(JetElement elem) {
|
||||
throw new IllegalArgumentException("Unsupported element: " + elem);
|
||||
semanticServices.getErrorHandler().genericError(elem.getNode(), "Unsupported in call expression"); // TODO : Message
|
||||
}
|
||||
});
|
||||
return wrapForTracing(result[0], reference[0], argumentList, true);
|
||||
@@ -209,10 +209,11 @@ public class JetTypeInferrer {
|
||||
|
||||
private OverloadDomain wrapForTracing(
|
||||
@Nullable final OverloadDomain overloadDomain,
|
||||
@NotNull final JetReferenceExpression referenceExpression,
|
||||
final JetReferenceExpression referenceExpression,
|
||||
@Nullable final PsiElement argumentList,
|
||||
final boolean reportErrors) {
|
||||
if (overloadDomain == null) return OverloadDomain.EMPTY;
|
||||
assert referenceExpression != null;
|
||||
return new OverloadDomain() {
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -682,6 +683,19 @@ public class JetTypeInferrer {
|
||||
if (declarationDescriptor instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
|
||||
|
||||
for (JetTypeProjection typeProjection : userType.getTypeArguments()) {
|
||||
switch (typeProjection.getProjectionKind()) {
|
||||
case IN:
|
||||
case OUT:
|
||||
case STAR:
|
||||
// TODO : Bug in the editor
|
||||
semanticServices.getErrorHandler().genericError(typeProjection.getProjectionNode(), "Projections are not allowed in constructor type arguments");
|
||||
break;
|
||||
case NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
JetSimpleNameExpression referenceExpression = userType.getReferenceExpression();
|
||||
if (referenceExpression != null) {
|
||||
// When one writes 'new Array<in T>(...)' this does not make much sense, and an instance
|
||||
@@ -696,7 +710,6 @@ public class JetTypeInferrer {
|
||||
// The code below upcasts the type automatically
|
||||
|
||||
List<TypeProjection> typeArguments = receiverType.getArguments();
|
||||
System.out.println("typeArguments = " + typeArguments);
|
||||
|
||||
List<TypeProjection> projectionsStripped = new ArrayList<TypeProjection>();
|
||||
for (TypeProjection typeArgument : typeArguments) {
|
||||
@@ -706,7 +719,6 @@ public class JetTypeInferrer {
|
||||
else
|
||||
projectionsStripped.add(typeArgument);
|
||||
}
|
||||
System.out.println("projectionsStripped = " + projectionsStripped);
|
||||
|
||||
FunctionGroup constructors = classDescriptor.getConstructors(projectionsStripped);
|
||||
OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(constructors);
|
||||
@@ -729,7 +741,7 @@ public class JetTypeInferrer {
|
||||
result = constructorReturnedType;
|
||||
|
||||
// Automatic upcast:
|
||||
result = receiverType;
|
||||
// result = receiverType;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -89,7 +89,7 @@ public class TypeSubstitutor {
|
||||
Variance passedProjectionKind = passedProjection.getProjectionKind();
|
||||
Variance parameterVariance = correspondingTypeParameter.getVariance();
|
||||
|
||||
Variance effectiveProjectionKind = (passedProjectionKind == Variance.INVARIANT) ? parameterVariance : passedProjectionKind;
|
||||
Variance effectiveProjectionKind = asymmetricOr(passedProjectionKind, parameterVariance);
|
||||
Variance effectiveContextVariance = contextCallSiteVariance.superpose(effectiveProjectionKind);
|
||||
|
||||
TypeProjection projectionValue = substitutionContext.get(typeToSubstituteIn.getConstructor());
|
||||
@@ -118,15 +118,11 @@ public class TypeSubstitutor {
|
||||
effectiveContextVariance));
|
||||
}
|
||||
|
||||
// public Set<JetType> substituteInSet(Map<TypeConstructor, TypeProjection> substitutionContext, Set<JetType> types, Variance howTheseTypesWillBeUsed) {
|
||||
// Set<JetType> result = new HashSet<JetType>();
|
||||
// for (JetType type : types) {
|
||||
// result.add(safeSubstitute(substitutionContext, type, howTheseTypesWillBeUsed));
|
||||
// }
|
||||
// return result;
|
||||
// }
|
||||
private static Variance asymmetricOr(Variance a, Variance b) {
|
||||
return a == Variance.INVARIANT ? b : a;
|
||||
}
|
||||
|
||||
private boolean allows(Variance declarationSiteVariance, Variance callSiteVariance) {
|
||||
private static boolean allows(Variance declarationSiteVariance, Variance callSiteVariance) {
|
||||
switch (declarationSiteVariance) {
|
||||
case INVARIANT: return true;
|
||||
case IN_VARIANCE: return callSiteVariance != Variance.OUT_VARIANCE;
|
||||
|
||||
@@ -17,40 +17,40 @@ class Inv<T> {
|
||||
|
||||
fun testInOut() {
|
||||
new In<String>().`In.f:T->Unit`f("1");
|
||||
new In<in String>().`In.f:T->Unit`f("1");
|
||||
new In<out String>().`!`f("1")
|
||||
new In<*>().`!`f("1");
|
||||
(return : In<in String>).`In.f:T->Unit`f("1");
|
||||
(return : In<out String>).`!`f("1")
|
||||
(return : In<*>).`!`f("1");
|
||||
|
||||
new In<String>().`In.f:Int->Int`f(1);
|
||||
new In<in String>().`In.f:Int->Int`f(1);
|
||||
new In<out String>().`In.f:Int->Int`f(1)
|
||||
new In<out String>().`!`f1(1)
|
||||
new In<*>().`In.f:Int->Int`f(1);
|
||||
(return : In<in String>).`In.f:Int->Int`f(1);
|
||||
(return : In<out String>).`In.f:Int->Int`f(1)
|
||||
(return : In<out String>).`!`f1(1)
|
||||
(return : In<*>).`In.f:Int->Int`f(1);
|
||||
|
||||
new Out<Int>().`Out.f(a)`f(1)
|
||||
new Out<out Int>().`Out.f(a)`f(1)
|
||||
new Out<in Int>().`Out.f(a)`f(1)
|
||||
new Out<*>().`Out.f(a)`f(1)
|
||||
(return : Out<out Int>).`Out.f(a)`f(1)
|
||||
(return : Out<in Int>).`Out.f(a)`f(1)
|
||||
(return : Out<*>).`Out.f(a)`f(1)
|
||||
|
||||
new Out<Int>().`Out.f`f()
|
||||
new Out<out Int>().`Out.f`f()
|
||||
new Out<in Int>().`!`f()
|
||||
new Out<*>().`Out.f`f()
|
||||
(return : Out<out Int>).`Out.f`f()
|
||||
(return : Out<in Int>).`!`f()
|
||||
(return : Out<*>).`Out.f`f()
|
||||
|
||||
new Inv<Int>().`Inv.f`f(1)
|
||||
new Inv<in Int>().`!`f(1)
|
||||
new Inv<out Int>().`!`f(1)
|
||||
new Inv<*>().`!`f(1)
|
||||
(return : Inv<in Int>).`!`f(1)
|
||||
(return : Inv<out Int>).`!`f(1)
|
||||
(return : Inv<*>).`!`f(1)
|
||||
|
||||
new Inv<Int>().`Inv.inf`inf(1)
|
||||
new Inv<in Int>().`Inv.inf`inf(1)
|
||||
new Inv<out Int>().`!`inf(1)
|
||||
new Inv<*>().`!`inf(1)
|
||||
(return : Inv<in Int>).`Inv.inf`inf(1)
|
||||
(return : Inv<out Int>).`!`inf(1)
|
||||
(return : Inv<*>).`!`inf(1)
|
||||
|
||||
new Inv<Int>().`Inv.outf`outf()
|
||||
new Inv<in Int>().`Inv.outf`outf()`:std::Any?`
|
||||
new Inv<out Int>().`Inv.outf`outf()
|
||||
new Inv<*>().`Inv.outf`outf()
|
||||
(return : Inv<in Int>).`Inv.outf`outf()`:std::Any?`
|
||||
(return : Inv<out Int>).`Inv.outf`outf()
|
||||
(return : Inv<*>).`Inv.outf`outf()
|
||||
|
||||
new Inv<Int>().`Inv.outf`outf(1)
|
||||
}
|
||||
Reference in New Issue
Block a user