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