提交 3ba947da 编写于 作者: A Andrey Breslav

Projections prohibited in constructor type arguments

上级 b5dce0d7
......@@ -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;
}
}
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;
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;
return JetProjectionKind.NONE;
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)
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册