Merge remote branch 'origin/master'

This commit is contained in:
Andrey Breslav
2011-11-25 18:32:24 +03:00
162 changed files with 898 additions and 642 deletions
+17
View File
@@ -1,4 +1,21 @@
<project name="Jet CI Bootstrap" default="unzipIdeaSDK"> <project name="Jet CI Bootstrap" default="unzipIdeaSDK">
<macrodef name="echoprop">
<attribute name="prop"/>
<sequential>
<echo>@{prop}=${@{prop}}</echo>
</sequential>
</macrodef>
<echoprop prop="os.name"/>
<echoprop prop="os.version"/>
<echoprop prop="os.arch"/>
<echoprop prop="java.home"/>
<echoprop prop="java.vendor"/>
<echoprop prop="java.version"/>
<echoprop prop="user.name"/>
<echoprop prop="user.home"/>
<echoprop prop="user.dir"/>
<target name="unzipIdeaSDK"> <target name="unzipIdeaSDK">
<unzip dest="ideaSDK"> <unzip dest="ideaSDK">
<fileset dir="ideaSDK" includes="ideaIC*.zip"/> <fileset dir="ideaSDK" includes="ideaIC*.zip"/>
+2 -2
View File
@@ -20,7 +20,7 @@
<target name="compileRT"> <target name="compileRT">
<mkdir dir="${output}/classes/runtime"/> <mkdir dir="${output}/classes/runtime"/>
<javac destdir="${output}/classes/runtime"> <javac destdir="${output}/classes/runtime" debug="true" debuglevel="lines,vars,source">
<src path="${basedir}/stdlib/src"/> <src path="${basedir}/stdlib/src"/>
<classpath refid="classpath"/> <classpath refid="classpath"/>
</javac> </javac>
@@ -36,7 +36,7 @@
<target name="compile" depends="compileRT"> <target name="compile" depends="compileRT">
<mkdir dir="${output}/classes/compiler"/> <mkdir dir="${output}/classes/compiler"/>
<javac destdir="${output}/classes/compiler"> <javac destdir="${output}/classes/compiler" debug="true" debuglevel="lines,vars,source">
<src refid="sourcepath"/> <src refid="sourcepath"/>
<classpath refid="classpath"/> <classpath refid="classpath"/>
</javac> </javac>
@@ -10,6 +10,7 @@ import org.objectweb.asm.commons.InstructionAdapter;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
/* /*
* @author max * @author max
@@ -38,6 +39,8 @@ public abstract class CodegenContext {
public final ObjectOrClosureCodegen closure; public final ObjectOrClosureCodegen closure;
HashMap<JetType,Integer> typeInfoConstants; HashMap<JetType,Integer> typeInfoConstants;
HashMap<Integer,JetType> reverseTypeInfoConstants;
int typeInfoConstantsCount;
HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors; HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors;
protected StackValue outerExpression; protected StackValue outerExpression;
@@ -177,13 +180,16 @@ public abstract class CodegenContext {
if(parentContext != STATIC) if(parentContext != STATIC)
return parentContext.getTypeInfoConstantIndex(type); return parentContext.getTypeInfoConstantIndex(type);
if(typeInfoConstants == null) if(typeInfoConstants == null) {
typeInfoConstants = new HashMap<JetType, Integer>(); typeInfoConstants = new LinkedHashMap<JetType, Integer>();
reverseTypeInfoConstants = new LinkedHashMap<Integer, JetType>();
}
Integer index = typeInfoConstants.get(type); Integer index = typeInfoConstants.get(type);
if(index == null) { if(index == null) {
index = typeInfoConstants.size(); index = typeInfoConstantsCount++;
typeInfoConstants.put(type, index); typeInfoConstants.put(type, index);
reverseTypeInfoConstants.put(index, type);
} }
return index; return index;
} }
@@ -2068,14 +2068,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return type; return type;
} }
private void generateNewArray(JetCallExpression expression, JetType arrayType) { public void generateNewArray(JetCallExpression expression, JetType arrayType) {
List<? extends ValueArgument> args = expression.getValueArguments(); List<? extends ValueArgument> args = expression.getValueArguments();
boolean isArray = state.getStandardLibrary().getArray().equals(arrayType.getConstructor().getDeclarationDescriptor()); boolean isArray = state.getStandardLibrary().getArray().equals(arrayType.getConstructor().getDeclarationDescriptor());
if(isArray) { if(isArray) {
if (args.size() != 2 && !arrayType.getArguments().get(0).getType().isNullable()) { // if (args.size() != 2 && !arrayType.getArguments().get(0).getType().isNullable()) {
throw new CompilationException("array constructor of non-nullable type requires two arguments"); // throw new CompilationException("array constructor of non-nullable type requires two arguments");
} // }
} }
else { else {
if (args.size() != 1) { if (args.size() != 1) {
@@ -2445,18 +2445,28 @@ If finally block is present, its last expression is the value of try expression.
return StackValue.onStack(Type.BOOLEAN_TYPE); return StackValue.onStack(Type.BOOLEAN_TYPE);
} }
public boolean hasTypeInfoForInstanceOf(JetType type) {
DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
if(declarationDescriptor instanceof TypeParameterDescriptor)
return true;
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor.getOriginal();
if(classDescriptor.equals(state.getStandardLibrary().getArray())) {
return hasTypeInfoForInstanceOf(type.getArguments().get(0).getType());
}
for(TypeParameterDescriptor proj : classDescriptor.getTypeConstructor().getParameters()) {
if(proj.isReified()) {
return true;
}
}
return false;
}
private void generateInstanceOf(StackValue expressionToGen, JetType jetType, boolean leaveExpressionOnStack) { private void generateInstanceOf(StackValue expressionToGen, JetType jetType, boolean leaveExpressionOnStack) {
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
boolean javaClass = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor) instanceof PsiClass; if (!hasTypeInfoForInstanceOf(jetType)) {
if (!javaClass && (jetType.getArguments().size() > 0 || !(descriptor instanceof ClassDescriptor))) {
generateTypeInfo(jetType);
expressionToGen.put(OBJECT_TYPE, v);
if (leaveExpressionOnStack) {
v.dupX1();
}
v.invokevirtual("jet/typeinfo/TypeInfo", "isInstance", "(Ljava/lang/Object;)Z");
}
else {
expressionToGen.put(OBJECT_TYPE, v); expressionToGen.put(OBJECT_TYPE, v);
if (leaveExpressionOnStack) { if (leaveExpressionOnStack) {
v.dup(); v.dup();
@@ -2479,6 +2489,14 @@ If finally block is present, its last expression is the value of try expression.
v.instanceOf(type); v.instanceOf(type);
} }
} }
else {
generateTypeInfo(jetType);
expressionToGen.put(OBJECT_TYPE, v);
if (leaveExpressionOnStack) {
v.dupX1();
}
v.invokevirtual("jet/typeinfo/TypeInfo", "isInstance", "(Ljava/lang/Object;)Z");
}
} }
public void generateTypeInfo(JetType jetType) { public void generateTypeInfo(JetType jetType) {
@@ -2656,30 +2674,6 @@ If finally block is present, its last expression is the value of try expression.
conditionValue = generatePatternMatch(pattern, patternCondition.isNegated(), conditionValue = generatePatternMatch(pattern, patternCondition.isNegated(),
StackValue.local(subjectLocal, subjectType), nextEntry); StackValue.local(subjectLocal, subjectType), nextEntry);
} }
else if (condition instanceof JetWhenConditionCall) {
final JetExpression call = ((JetWhenConditionCall) condition).getCallSuffixExpression();
if (call instanceof JetCallExpression) {
v.load(subjectLocal, subjectType);
final DeclarationDescriptor declarationDescriptor = resolveCalleeDescriptor((JetCallExpression) call);
if (!(declarationDescriptor instanceof FunctionDescriptor)) {
throw new UnsupportedOperationException("expected function descriptor in when condition with call, found " + declarationDescriptor);
}
conditionValue = invokeFunction((JetCallExpression) call, declarationDescriptor, StackValue.onStack(subjectType));
}
else if (call instanceof JetSimpleNameExpression) {
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) call);
if (descriptor instanceof PropertyDescriptor) {
v.load(subjectLocal, subjectType);
conditionValue = intermediateValueForProperty((PropertyDescriptor) descriptor, false, null);
}
else {
throw new UnsupportedOperationException("unknown simple name resolve result: " + descriptor);
}
}
else {
throw new UnsupportedOperationException("unsupported kind of call suffix");
}
}
else { else {
throw new UnsupportedOperationException("unsupported kind of when condition"); throw new UnsupportedOperationException("unsupported kind of when condition");
} }
@@ -14,9 +14,7 @@ import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import static org.objectweb.asm.Opcodes.*; import static org.objectweb.asm.Opcodes.*;
@@ -114,11 +112,12 @@ public class NamespaceCodegen {
private void generateTypeInfoFields(JetNamespace namespace, CodegenContext context) { private void generateTypeInfoFields(JetNamespace namespace, CodegenContext context) {
if(context.typeInfoConstants != null) { if(context.typeInfoConstants != null) {
String jvmClassName = getJVMClassName(namespace.getName()); String jvmClassName = getJVMClassName(namespace.getName());
for(Map.Entry<JetType,Integer> e : (context.typeInfoConstants != null ? context.typeInfoConstants : Collections.<JetType,Integer>emptyMap()).entrySet()) { for(int index = 0; index != context.typeInfoConstantsCount; index++) {
String fieldName = "$typeInfoCache$" + e.getValue(); JetType type = context.reverseTypeInfoConstants.get(index);
String fieldName = "$typeInfoCache$" + index;
v.newField(null, ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, fieldName, "Ljet/typeinfo/TypeInfo;", null, null); v.newField(null, ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, fieldName, "Ljet/typeinfo/TypeInfo;", null, null);
MethodVisitor mmv = v.newMethod(null, ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, "$getCachedTypeInfo$" + e.getValue(), "()Ljet/typeinfo/TypeInfo;", null, null); MethodVisitor mmv = v.newMethod(null, ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, "$getCachedTypeInfo$" + index, "()Ljet/typeinfo/TypeInfo;", null, null);
InstructionAdapter v = new InstructionAdapter(mmv); InstructionAdapter v = new InstructionAdapter(mmv);
v.visitFieldInsn(GETSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;"); v.visitFieldInsn(GETSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;");
v.visitInsn(DUP); v.visitInsn(DUP);
@@ -126,7 +125,7 @@ public class NamespaceCodegen {
v.visitJumpInsn(IFNONNULL, end); v.visitJumpInsn(IFNONNULL, end);
v.pop(); v.pop();
generateTypeInfo(context, v, e.getKey(), state.getTypeMapper(), e.getKey()); generateTypeInfo(context, v, type, state.getTypeMapper(), type);
v.dup(); v.dup();
v.visitFieldInsn(PUTSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;"); v.visitFieldInsn(PUTSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;");
@@ -5,6 +5,7 @@ import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.JetTypeMapper; import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetParenthesizedExpression;
import org.jetbrains.jet.lang.psi.JetReferenceExpression; import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
@@ -23,7 +24,10 @@ public class Increment implements IntrinsicMethod {
@Override @Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) { public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
final JetExpression operand = arguments.get(0); JetExpression operand = arguments.get(0);
while(operand instanceof JetParenthesizedExpression) {
operand = ((JetParenthesizedExpression)operand).getExpression();
}
if (operand instanceof JetReferenceExpression) { if (operand instanceof JetReferenceExpression) {
final int index = codegen.indexOfLocal((JetReferenceExpression) operand); final int index = codegen.indexOfLocal((JetReferenceExpression) operand);
if (index >= 0 && JetTypeMapper.isIntPrimitive(expectedType)) { if (index >= 0 && JetTypeMapper.isIntPrimitive(expectedType)) {
@@ -33,6 +37,7 @@ public class Increment implements IntrinsicMethod {
} }
StackValue value = codegen.genQualified(receiver, operand); StackValue value = codegen.genQualified(receiver, operand);
value. dupReceiver(v); value. dupReceiver(v);
value. dupReceiver(v);
value.put(expectedType, v); value.put(expectedType, v);
if (expectedType == Type.LONG_TYPE) { if (expectedType == Type.LONG_TYPE) {
v.lconst(myDelta); v.lconst(myDelta);
@@ -44,10 +49,11 @@ public class Increment implements IntrinsicMethod {
v.dconst(myDelta); v.dconst(myDelta);
} }
else { else {
v.aconst(myDelta); v.iconst(myDelta);
} }
v.add(expectedType); v.add(expectedType);
value.store(v); value.store(v);
return value; value.put(expectedType, v);
return StackValue.onStack(expectedType);
} }
} }
@@ -15,6 +15,7 @@ import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.plugin.JetFileType; import org.jetbrains.jet.plugin.JetFileType;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import sun.tools.tree.NewArrayExpression;
import java.util.*; import java.util.*;
@@ -85,6 +86,7 @@ public class IntrinsicMethods {
declareOverload(myStdLib.getLibraryScope().getFunctions("equals"), 1, EQUALS); declareOverload(myStdLib.getLibraryScope().getFunctions("equals"), 1, EQUALS);
declareOverload(myStdLib.getLibraryScope().getFunctions("identityEquals"), 1, EQUALS); declareOverload(myStdLib.getLibraryScope().getFunctions("identityEquals"), 1, EQUALS);
declareOverload(myStdLib.getLibraryScope().getFunctions("plus"), 1, new StringPlus()); declareOverload(myStdLib.getLibraryScope().getFunctions("plus"), 1, new StringPlus());
declareOverload(myStdLib.getLibraryScope().getFunctions("Array"), 1, new NewArray());
declareIntrinsicFunction("ByteIterator", "next", 0, ITERATOR_NEXT); declareIntrinsicFunction("ByteIterator", "next", 0, ITERATOR_NEXT);
declareIntrinsicFunction("ShortIterator", "next", 0, ITERATOR_NEXT); declareIntrinsicFunction("ShortIterator", "next", 0, ITERATOR_NEXT);
@@ -0,0 +1,24 @@
package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetCallExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import java.util.List;
/**
* @author alex.tkachman
*/
public class NewArray implements IntrinsicMethod {
@Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
codegen.generateNewArray((JetCallExpression) element, codegen.getBindingContext().get(BindingContext.EXPRESSION_TYPE, (JetExpression) element));
return StackValue.onStack(expectedType);
}
}
+3 -1
View File
@@ -105,7 +105,9 @@ trait Iterable<out T> {
fun iterator() : Iterator<T> fun iterator() : Iterator<T>
} }
class Array<T>(val size : Int, init : fun(Int) : T = null ) { fun Array<T>(val size : Int) : Array<T?>
class Array<T>(val size : Int, init : fun(Int) : T) {
fun get(index : Int) : T fun get(index : Int) : T
fun set(index : Int, value : T) : Unit fun set(index : Int, value : T) : Unit
@@ -141,7 +141,6 @@ public interface JetNodeTypes {
JetNodeType WHEN_CONDITION_IN_RANGE = new JetNodeType("WHEN_CONDITION_IN_RANGE", JetWhenConditionInRange.class); JetNodeType WHEN_CONDITION_IN_RANGE = new JetNodeType("WHEN_CONDITION_IN_RANGE", JetWhenConditionInRange.class);
JetNodeType WHEN_CONDITION_IS_PATTERN = new JetNodeType("WHEN_CONDITION_IS_PATTERN", JetWhenConditionIsPattern.class); JetNodeType WHEN_CONDITION_IS_PATTERN = new JetNodeType("WHEN_CONDITION_IS_PATTERN", JetWhenConditionIsPattern.class);
JetNodeType WHEN_CONDITION_CALL = new JetNodeType("WHEN_CONDITION_CALL", JetWhenConditionCall.class);
JetNodeType NAMESPACE_NAME = new JetNodeType("NAMESPACE_NAME", JetContainerNode.class); JetNodeType NAMESPACE_NAME = new JetNodeType("NAMESPACE_NAME", JetContainerNode.class);
} }
@@ -62,10 +62,6 @@ public class JetControlFlowProcessor {
private class CFPVisitor extends JetVisitorVoid { private class CFPVisitor extends JetVisitorVoid {
private final boolean inCondition; private final boolean inCondition;
private final JetVisitorVoid conditionVisitor = new JetVisitorVoid() { private final JetVisitorVoid conditionVisitor = new JetVisitorVoid() {
@Override
public void visitWhenConditionCall(JetWhenConditionCall condition) {
value(condition.getCallSuffixExpression(), CFPVisitor.this.inCondition); // TODO : inCondition?
}
@Override @Override
public void visitWhenConditionInRange(JetWhenConditionInRange condition) { public void visitWhenConditionInRange(JetWhenConditionInRange condition) {
@@ -21,7 +21,9 @@ public interface CallableDescriptor extends DeclarationDescriptor {
@NotNull @NotNull
List<TypeParameterDescriptor> getTypeParameters(); List<TypeParameterDescriptor> getTypeParameters();
@NotNull /**
* Method may return null for not yet fully initialized object or if error occurred.
*/
JetType getReturnType(); JetType getReturnType();
@NotNull @NotNull
@@ -120,7 +120,6 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
} }
@Override @Override
@NotNull
public JetType getReturnType() { public JetType getReturnType() {
return unsubstitutedReturnType; return unsubstitutedReturnType;
} }
@@ -113,7 +113,6 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
return expectedThisObject; return expectedThisObject;
} }
@NotNull
@Override @Override
public JetType getReturnType() { public JetType getReturnType() {
return getOutType(); return getOutType();
@@ -34,7 +34,6 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor {
return Collections.emptyList(); return Collections.emptyList();
} }
@NotNull
@Override @Override
public JetType getReturnType() { public JetType getReturnType() {
return returnType; return returnType;
@@ -84,7 +84,6 @@ public abstract class VariableDescriptorImpl extends DeclarationDescriptorImpl i
return ReceiverDescriptor.NO_RECEIVER; return ReceiverDescriptor.NO_RECEIVER;
} }
@NotNull
@Override @Override
public JetType getReturnType() { public JetType getReturnType() {
return getOutType(); return getOutType();
@@ -288,7 +288,10 @@ public interface Errors {
ParameterizedDiagnosticFactory2<JetType, Integer> TYPE_MISMATCH_IN_TUPLE_PATTERN = ParameterizedDiagnosticFactory2.create(ERROR, "Type mismatch: subject is of type {0} but the pattern is of type Tuple{1}"); // TODO: message ParameterizedDiagnosticFactory2<JetType, Integer> TYPE_MISMATCH_IN_TUPLE_PATTERN = ParameterizedDiagnosticFactory2.create(ERROR, "Type mismatch: subject is of type {0} but the pattern is of type Tuple{1}"); // TODO: message
ParameterizedDiagnosticFactory2<JetType, JetType> TYPE_MISMATCH_IN_BINDING_PATTERN = ParameterizedDiagnosticFactory2.create(ERROR, "{0} must be a supertype of {1}. Use 'is' to match against {0}"); ParameterizedDiagnosticFactory2<JetType, JetType> TYPE_MISMATCH_IN_BINDING_PATTERN = ParameterizedDiagnosticFactory2.create(ERROR, "{0} must be a supertype of {1}. Use 'is' to match against {0}");
ParameterizedDiagnosticFactory2<JetType, JetType> INCOMPATIBLE_TYPES = ParameterizedDiagnosticFactory2.create(ERROR, "Incompatible types: {0} and {1}"); ParameterizedDiagnosticFactory2<JetType, JetType> INCOMPATIBLE_TYPES = ParameterizedDiagnosticFactory2.create(ERROR, "Incompatible types: {0} and {1}");
ParameterizedDiagnosticFactory1<JetType> CANNOT_CHECK_FOR_ERASED = ParameterizedDiagnosticFactory1.create(ERROR, "Cannot check for instance of erased type: {0}");
ParameterizedDiagnosticFactory2<JetType, JetType> UNCHECKED_CAST = ParameterizedDiagnosticFactory2.create(WARNING, "Unchecked cast: {0} to {1}");
ParameterizedDiagnosticFactory3<TypeParameterDescriptor, ClassDescriptor, Collection<JetType>> INCONSISTENT_TYPE_PARAMETER_VALUES = new ParameterizedDiagnosticFactory3<TypeParameterDescriptor, ClassDescriptor, Collection<JetType>>(ERROR, "Type parameter {0} of {1} has inconsistent values: {2}") { ParameterizedDiagnosticFactory3<TypeParameterDescriptor, ClassDescriptor, Collection<JetType>> INCONSISTENT_TYPE_PARAMETER_VALUES = new ParameterizedDiagnosticFactory3<TypeParameterDescriptor, ClassDescriptor, Collection<JetType>>(ERROR, "Type parameter {0} of {1} has inconsistent values: {2}") {
@Override @Override
protected String makeMessageForA(@NotNull TypeParameterDescriptor typeParameterDescriptor) { protected String makeMessageForA(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
@@ -370,7 +373,7 @@ public interface Errors {
ParameterizedDiagnosticFactory2<JetClassOrObject, CallableMemberDescriptor> ABSTRACT_MEMBER_NOT_IMPLEMENTED = new ParameterizedDiagnosticFactory2<JetClassOrObject, CallableMemberDescriptor>(ERROR, "Class ''{0}'' must be declared abstract or implement abstract member {1}") { ParameterizedDiagnosticFactory2<JetClassOrObject, CallableMemberDescriptor> ABSTRACT_MEMBER_NOT_IMPLEMENTED = new ParameterizedDiagnosticFactory2<JetClassOrObject, CallableMemberDescriptor>(ERROR, "Class ''{0}'' must be declared abstract or implement abstract member {1}") {
@Override @Override
protected String makeMessageForA(@NotNull JetClassOrObject jetClassOrObject) { protected String makeMessageForA(@NotNull JetClassOrObject jetClassOrObject) {
return jetClassOrObject.getName(); return JetPsiUtil.safeName(jetClassOrObject.getName());
} }
@Override @Override
@@ -419,7 +419,10 @@ public class JetExpressionParsing extends AbstractJetParsing {
} }
else return false; else return false;
} }
else return false; else {
return false;
}
return true; return true;
} }
@@ -764,7 +767,6 @@ public class JetExpressionParsing extends AbstractJetParsing {
/* /*
* whenCondition * whenCondition
* : expression * : expression
* : ("." | "?." postfixExpression typeArguments? valueArguments?
* : ("in" | "!in") expression * : ("in" | "!in") expression
* : ("is" | "!is") isRHS * : ("is" | "!is") isRHS
* ; * ;
@@ -793,21 +795,10 @@ public class JetExpressionParsing extends AbstractJetParsing {
parsePattern(); parsePattern();
} }
condition.done(WHEN_CONDITION_IS_PATTERN); condition.done(WHEN_CONDITION_IS_PATTERN);
} else if (at(DOT) || at(SAFE_ACCESS)) {
advance(); // DOT or SAFE_ACCESS
PsiBuilder.Marker mark = mark();
parsePostfixExpression();
if (parseCallSuffix()) {
mark.done(CALL_EXPRESSION);
}
else {
mark.drop();
}
condition.done(WHEN_CONDITION_CALL);
} else { } else {
PsiBuilder.Marker expressionPattern = mark(); PsiBuilder.Marker expressionPattern = mark();
if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_DOUBLE_ARROW)) { if (atSet(WHEN_CONDITION_RECOVERY_SET_WITH_DOUBLE_ARROW)) {
error("Expecting an element, is-condition or in-condition"); error("Expecting an expression, is-condition or in-condition");
} else { } else {
parseExpression(); parseExpression();
} }
@@ -356,10 +356,6 @@ public class JetVisitor<R, D> extends PsiElementVisitor {
return visitExpression(expression, data); return visitExpression(expression, data);
} }
public R visitWhenConditionCall(JetWhenConditionCall condition, D data) {
return visitJetElement(condition, data);
}
public R visitWhenConditionIsPattern(JetWhenConditionIsPattern condition, D data) { public R visitWhenConditionIsPattern(JetWhenConditionIsPattern condition, D data) {
return visitJetElement(condition, data); return visitJetElement(condition, data);
} }
@@ -354,10 +354,6 @@ public class JetVisitorVoid extends PsiElementVisitor {
visitExpression(expression); visitExpression(expression);
} }
public void visitWhenConditionCall(JetWhenConditionCall condition) {
visitJetElement(condition);
}
public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) { public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) {
visitJetElement(condition); visitJetElement(condition);
} }
@@ -1,40 +0,0 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lexer.JetTokens;
/**
* @author abreslav
*/
public class JetWhenConditionCall extends JetWhenCondition {
public JetWhenConditionCall(@NotNull ASTNode node) {
super(node);
}
public boolean isSafeCall() {
return getNode().findChildByType(JetTokens.SAFE_ACCESS) != null;
}
@NotNull
public ASTNode getOperationTokenNode() {
return getNode().findChildByType(TokenSet.create(JetTokens.SAFE_ACCESS, JetTokens.DOT));
}
@Nullable @IfNotParsed
public JetExpression getCallSuffixExpression() {
return findChildByClass(JetExpression.class);
}
@Override
public void accept(@NotNull JetVisitorVoid visitor) {
visitor.visitWhenConditionCall(this);
}
@Override
public <R, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
return visitor.visitWhenConditionCall(this, data);
}
}
@@ -39,6 +39,8 @@ import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
* @author abreslav * @author abreslav
*/ */
public class CallResolver { public class CallResolver {
private static final JetType DONT_CARE = ErrorUtils.createErrorTypeWithCustomDebugName("DONT_CARE");
private final JetSemanticServices semanticServices; private final JetSemanticServices semanticServices;
private final OverloadingConflictResolver overloadingConflictResolver; private final OverloadingConflictResolver overloadingConflictResolver;
private final DataFlowInfo dataFlowInfo; private final DataFlowInfo dataFlowInfo;
@@ -412,7 +414,7 @@ public class CallResolver {
constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO
} }
TypeSubstitutor substituteUnknown = ConstraintSystemImpl.makeConstantSubstitutor(candidate.getTypeParameters(), ErrorUtils.createErrorType("Unknown")); TypeSubstitutor substituteDontCare = ConstraintSystemImpl.makeConstantSubstitutor(candidate.getTypeParameters(), DONT_CARE);
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) { for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
ResolvedValueArgument valueArgument = entry.getValue(); ResolvedValueArgument valueArgument = entry.getValue();
@@ -428,7 +430,7 @@ public class CallResolver {
// We'll type check the arguments later, with the inferred types expected // We'll type check the arguments later, with the inferred types expected
TemporaryBindingTrace traceForUnknown = TemporaryBindingTrace.create(temporaryTrace); TemporaryBindingTrace traceForUnknown = TemporaryBindingTrace.create(temporaryTrace);
ExpressionTypingServices temporaryServices = new ExpressionTypingServices(semanticServices, traceForUnknown); ExpressionTypingServices temporaryServices = new ExpressionTypingServices(semanticServices, traceForUnknown);
JetType type = temporaryServices.getType(scope, expression, substituteUnknown.substitute(valueParameterDescriptor.getOutType(), Variance.INVARIANT)); JetType type = temporaryServices.getType(scope, expression, substituteDontCare.substitute(valueParameterDescriptor.getOutType(), Variance.INVARIANT));
if (type != null) { if (type != null) {
constraintSystem.addSubtypingConstraint(type, effectiveExpectedType); constraintSystem.addSubtypingConstraint(type, effectiveExpectedType);
} }
@@ -439,10 +441,10 @@ public class CallResolver {
} }
// Error is already reported if something is missing // Error is already reported if something is missing
ReceiverDescriptor receiverParameter = candidateCall.getReceiverArgument(); ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
ReceiverDescriptor candidateReceiver = candidate.getReceiverParameter(); ReceiverDescriptor receiverParameter = candidate.getReceiverParameter();
if (receiverParameter.exists() && candidateReceiver.exists()) { if (receiverArgument.exists() && receiverParameter.exists()) {
constraintSystem.addSubtypingConstraint(receiverParameter.getType(), candidateReceiver.getType()); constraintSystem.addSubtypingConstraint(receiverArgument.getType(), receiverParameter.getType());
} }
if (expectedType != NO_EXPECTED_TYPE) { if (expectedType != NO_EXPECTED_TYPE) {
@@ -171,11 +171,20 @@ public class ErrorUtils {
} }
private static JetType createErrorType(String debugMessage, JetScope memberScope) { private static JetType createErrorType(String debugMessage, JetScope memberScope) {
return new ErrorTypeImpl(new TypeConstructorImpl(ERROR_CLASS, Collections.<AnnotationDescriptor>emptyList(), false, "[ERROR : " + debugMessage + "]", Collections.<TypeParameterDescriptor>emptyList(), Collections.singleton(JetStandardClasses.getAnyType())), memberScope); return createErrorTypeWithCustomDebugName(memberScope, "[ERROR : " + debugMessage + "]");
}
@NotNull
public static JetType createErrorTypeWithCustomDebugName(String debugName) {
return createErrorTypeWithCustomDebugName(ERROR_SCOPE, debugName);
}
private static JetType createErrorTypeWithCustomDebugName(JetScope memberScope, String debugName) {
return new ErrorTypeImpl(new TypeConstructorImpl(ERROR_CLASS, Collections.<AnnotationDescriptor>emptyList(), false, debugName, Collections.<TypeParameterDescriptor>emptyList(), Collections.singleton(JetStandardClasses.getAnyType())), memberScope);
} }
public static JetType createWrongVarianceErrorType(TypeProjection value) { public static JetType createWrongVarianceErrorType(TypeProjection value) {
return createErrorType(value + " is not allowed here]", value.getType().getMemberScope()); return createErrorType(value + " is not allowed here", value.getType().getMemberScope());
} }
public static ClassifierDescriptor getErrorClass() { public static ClassifierDescriptor getErrorClass() {
@@ -284,7 +284,7 @@ public class JetStandardLibrary {
} }
@NotNull @NotNull
public ClassDescriptor getArray() { public ClassDescriptor getArray() {
initStdClasses(); initStdClasses();
return arrayClass; return arrayClass;
} }
@@ -110,54 +110,65 @@ public class TypeUtils {
} }
@Nullable @Nullable
public static JetType intersect(JetTypeChecker typeChecker, Set<JetType> types) { public static JetType intersect(@NotNull JetTypeChecker typeChecker, @NotNull Set<JetType> types) {
assert !types.isEmpty(); assert !types.isEmpty();
if (types.size() == 1) { if (types.size() == 1) {
return types.iterator().next(); return types.iterator().next();
} }
StringBuilder debugName = new StringBuilder(); // Intersection of T1..Tn is an intersection of their non-null versions,
boolean nullable = false; // made nullable is they all were nullable
Set<JetType> resultingTypes = Sets.newHashSet(); boolean allNullable = true;
boolean nothingTypePresent = false;
List<JetType> nullabilityStripped = Lists.newArrayList();
for (JetType type : types) {
nothingTypePresent |= JetStandardClasses.isNothingOrNullableNothing(type);
allNullable &= type.isNullable();
nullabilityStripped.add(makeNotNullable(type));
}
if (nothingTypePresent) {
return allNullable ? JetStandardClasses.getNullableNothingType() : JetStandardClasses.getNothingType();
}
// Now we remove types that have subtypes in the list
List<JetType> resultingTypes = Lists.newArrayList();
outer: outer:
for (Iterator<JetType> iterator = types.iterator(); iterator.hasNext();) { for (JetType type : nullabilityStripped) {
JetType type = iterator.next();
if (!canHaveSubtypes(typeChecker, type)) { if (!canHaveSubtypes(typeChecker, type)) {
for (JetType other : types) { for (JetType other : nullabilityStripped) {
// It makes sense to check for subtyping of other <: type, despite that // It makes sense to check for subtyping of other <: type, despite that
// type is not supposed to be open, for there're enums // type is not supposed to be open, for there're enums
if (!type.equals(other) && !typeChecker.isSubtypeOf(type, other) && !typeChecker.isSubtypeOf(other, type)) { if (!type.equals(other) && !typeChecker.isSubtypeOf(type, other) && !typeChecker.isSubtypeOf(other, type)) {
return null; return null;
} }
} }
return type; return makeNullableAsSpecified(type, allNullable);
} }
else { else {
for (JetType other : types) { for (JetType other : nullabilityStripped) {
if (!type.equals(other) && typeChecker.isSubtypeOf(other, type)) { if (!type.equals(other) && typeChecker.isSubtypeOf(other, type)) {
continue outer; continue outer;
} }
} }
} }
nullable |= type.isNullable();
resultingTypes.add(type); resultingTypes.add(type);
debugName.append(type.toString());
if (iterator.hasNext()) {
debugName.append(" & ");
}
} }
if (resultingTypes.size() == 1) {
return makeNullableAsSpecified(resultingTypes.get(0), allNullable);
}
List<AnnotationDescriptor> noAnnotations = Collections.<AnnotationDescriptor>emptyList(); List<AnnotationDescriptor> noAnnotations = Collections.<AnnotationDescriptor>emptyList();
TypeConstructor constructor = new TypeConstructorImpl( TypeConstructor constructor = new TypeConstructorImpl(
null, null,
noAnnotations, noAnnotations,
false, false,
debugName.toString(), makeDebugNameForIntersectionType(resultingTypes).toString(),
Collections.<TypeParameterDescriptor>emptyList(), Collections.<TypeParameterDescriptor>emptyList(),
resultingTypes); resultingTypes);
@@ -171,11 +182,25 @@ public class TypeUtils {
return new JetTypeImpl( return new JetTypeImpl(
noAnnotations, noAnnotations,
constructor, constructor,
nullable, allNullable,
Collections.<TypeProjection>emptyList(), Collections.<TypeProjection>emptyList(),
new ChainedScope(null, scopes)); // TODO : check intersectibility, don't use a chanied scope new ChainedScope(null, scopes)); // TODO : check intersectibility, don't use a chanied scope
} }
private static StringBuilder makeDebugNameForIntersectionType(Iterable<JetType> resultingTypes) {
StringBuilder debugName = new StringBuilder("{");
for (Iterator<JetType> iterator = resultingTypes.iterator(); iterator.hasNext(); ) {
JetType type = iterator.next();
debugName.append(type.toString());
if (iterator.hasNext()) {
debugName.append(" & ");
}
}
debugName.append("}");
return debugName;
}
public static boolean canHaveSubtypes(JetTypeChecker typeChecker, JetType type) { public static boolean canHaveSubtypes(JetTypeChecker typeChecker, JetType type) {
if (type.isNullable()) { if (type.isNullable()) {
return true; return true;
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.types.expressions; package org.jetbrains.jet.lang.types.expressions;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IElementType;
@@ -8,6 +9,7 @@ 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;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.CallMaker; import org.jetbrains.jet.lang.resolve.calls.CallMaker;
@@ -245,10 +247,63 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
else { else {
if (typeChecker.isSubtypeOf(actualType, targetType)) { if (typeChecker.isSubtypeOf(actualType, targetType)) {
context.trace.report(USELESS_CAST.on(expression, expression.getOperationSign())); context.trace.report(USELESS_CAST.on(expression, expression.getOperationSign()));
} else {
if (isCastErased(actualType, targetType)) {
context.trace.report(Errors.UNCHECKED_CAST.on(expression, actualType, targetType));
}
} }
} }
} }
/**
* Check if assignment from ActualType to TargetType is erased.
* It is an error in "is" statement and warning in "as".
*/
public static boolean isCastErased(JetType actualType, JetType targetType) {
if (!(targetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) {
// TODO: what if it is TypeParameterDescriptor?
return false;
}
JetType targetTypeClerared = TypeUtils.makeUnsubstitutedType(
(ClassDescriptor) targetType.getConstructor().getDeclarationDescriptor(), null);
Multimap<TypeConstructor, TypeProjection> clearTypeSubstitutionMap =
TypeUtils.buildDeepSubstitutionMultimap(targetTypeClerared);
Set<JetType> clearSubstituted = new HashSet<JetType>();
for (int i = 0; i < actualType.getConstructor().getParameters().size(); ++i) {
TypeParameterDescriptor subjectTypeParameterDescriptor = actualType.getConstructor().getParameters().get(i);
Collection<TypeProjection> subst = clearTypeSubstitutionMap.get(subjectTypeParameterDescriptor.getTypeConstructor());
for (TypeProjection proj : subst) {
clearSubstituted.add(proj.getType());
}
}
for (int i = 0; i < targetType.getConstructor().getParameters().size(); ++i) {
TypeParameterDescriptor typeParameter = targetType.getConstructor().getParameters().get(i);
TypeProjection typeProjection = targetType.getArguments().get(i);
if (typeParameter.isReified()) {
continue;
}
// "is List<*>"
if (typeProjection.equals(TypeUtils.makeStarProjection(typeParameter))) {
continue;
}
// if parameter is mapped to nothing then it is erased
if (!clearSubstituted.contains(typeParameter.getDefaultType())) {
return true;
}
}
return false;
}
@Override @Override
public JetType visitTupleExpression(JetTupleExpression expression, ExpressionTypingContext context) { public JetType visitTupleExpression(JetTupleExpression expression, ExpressionTypingContext context) {
List<JetExpression> entries = expression.getEntries(); List<JetExpression> entries = expression.getEntries();
@@ -6,6 +6,7 @@ import com.intellij.openapi.util.Ref;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
@@ -17,8 +18,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import java.util.List; import java.util.*;
import java.util.Set;
import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.ensureBooleanResultWithCustomSubject; import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.ensureBooleanResultWithCustomSubject;
@@ -113,19 +113,6 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
final DataFlowInfo[] newDataFlowInfo = new DataFlowInfo[]{context.dataFlowInfo}; final DataFlowInfo[] newDataFlowInfo = new DataFlowInfo[]{context.dataFlowInfo};
condition.accept(new JetVisitorVoid() { condition.accept(new JetVisitorVoid() {
@Override
public void visitWhenConditionCall(JetWhenConditionCall condition) {
JetExpression callSuffixExpression = condition.getCallSuffixExpression();
// JetScope compositeScope = new ScopeWithReceiver(context.scope, subjectType, semanticServices.getTypeChecker());
if (callSuffixExpression != null) {
// JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false, context);
assert subjectExpression != null;
JetType selectorReturnType = facade.getSelectorReturnType(new ExpressionReceiver(subjectExpression, subjectType), condition.getOperationTokenNode(), callSuffixExpression, context);//getType(compositeScope, callSuffixExpression, false, context);
ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression", context);
// context.getServices().checkNullSafety(subjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression, context), condition);
}
}
@Override @Override
public void visitWhenConditionInRange(JetWhenConditionInRange condition) { public void visitWhenConditionInRange(JetWhenConditionInRange condition) {
JetExpression rangeExpression = condition.getRangeExpression(); JetExpression rangeExpression = condition.getRangeExpression();
@@ -245,6 +232,9 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
} }
} }
/*
* (a: SubjectType) is Type
*/
private void checkTypeCompatibility(@Nullable JetType type, @NotNull JetType subjectType, @NotNull JetElement reportErrorOn) { private void checkTypeCompatibility(@Nullable JetType type, @NotNull JetType subjectType, @NotNull JetElement reportErrorOn) {
// TODO : Take auto casts into account? // TODO : Take auto casts into account?
if (type == null) { if (type == null) {
@@ -253,6 +243,11 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
if (TypeUtils.intersect(context.semanticServices.getTypeChecker(), Sets.newHashSet(type, subjectType)) == null) { if (TypeUtils.intersect(context.semanticServices.getTypeChecker(), Sets.newHashSet(type, subjectType)) == null) {
// context.trace.getErrorHandler().genericError(reportErrorOn.getNode(), "Incompatible types: " + type + " and " + subjectType); // context.trace.getErrorHandler().genericError(reportErrorOn.getNode(), "Incompatible types: " + type + " and " + subjectType);
context.trace.report(INCOMPATIBLE_TYPES.on(reportErrorOn, type, subjectType)); context.trace.report(INCOMPATIBLE_TYPES.on(reportErrorOn, type, subjectType));
return;
}
if (BasicExpressionTypingVisitor.isCastErased(subjectType, type)) {
context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(reportErrorOn, type));
} }
} }
@@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -46,8 +47,19 @@ public class ConstraintSystemImpl implements ConstraintSystem {
} }
public static abstract class TypeValue { public static abstract class TypeValue {
private final Set<TypeValue> upperBounds = Sets.newHashSet(); private final Set<TypeValue> mutableUpperBounds = Sets.newHashSet();
private final Set<TypeValue> lowerBounds = Sets.newHashSet(); private final Set<TypeValue> upperBounds = Collections.unmodifiableSet(mutableUpperBounds);
private final Set<TypeValue> mutableLowerBounds = Sets.newHashSet();
private final Set<TypeValue> lowerBounds = Collections.unmodifiableSet(mutableLowerBounds);
public void addUpperBound(@NotNull TypeValue bound) {
mutableUpperBounds.add(bound);
}
public void addLowerBound(@NotNull TypeValue bound) {
mutableLowerBounds.add(bound);
}
@NotNull @NotNull
public Set<TypeValue> getUpperBounds() { public Set<TypeValue> getUpperBounds() {
@@ -86,8 +98,8 @@ public class ConstraintSystemImpl implements ConstraintSystem {
throw new LoopInTypeVariableConstraintsException(); throw new LoopInTypeVariableConstraintsException();
} }
if (value == null) { if (value == null) {
JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
beingComputed = true; beingComputed = true;
JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
try { try {
if (positionVariance == Variance.IN_VARIANCE) { if (positionVariance == Variance.IN_VARIANCE) {
// maximal solution // maximal solution
@@ -320,8 +332,8 @@ public class ConstraintSystemImpl implements ConstraintSystem {
private void addSubtypingConstraintOnTypeValues(TypeValue typeValueForLower, TypeValue typeValueForUpper) { private void addSubtypingConstraintOnTypeValues(TypeValue typeValueForLower, TypeValue typeValueForUpper) {
println(typeValueForLower + " :< " + typeValueForUpper); println(typeValueForLower + " :< " + typeValueForUpper);
if (typeValueForLower != typeValueForUpper) { if (typeValueForLower != typeValueForUpper) {
typeValueForLower.getUpperBounds().add(typeValueForUpper); typeValueForLower.addUpperBound(typeValueForUpper);
typeValueForUpper.getLowerBounds().add(typeValueForLower); typeValueForUpper.addLowerBound(typeValueForLower);
} }
} }
@@ -358,13 +370,20 @@ public class ConstraintSystemImpl implements ConstraintSystem {
// effective bounds for each node // effective bounds for each node
Set<TypeValue> visited = Sets.newHashSet(); Set<TypeValue> visited = Sets.newHashSet();
for (KnownType knownType : knownTypes.values()) {
transitiveClosure(knownType, visited);
}
for (UnknownType unknownType : unknownTypes.values()) { for (UnknownType unknownType : unknownTypes.values()) {
transitiveClosure(unknownType, visited); transitiveClosure(unknownType, visited);
} }
for (UnknownType unknownType : unknownTypes.values()) {
println("Constraints for " + unknownType.getTypeParameterDescriptor());
printTypeValue(unknownType);
}
for (KnownType knownType : knownTypes.values()) {
println("Constraints for " + knownType.getType());
printTypeValue(knownType);
}
// Find inconsistencies // Find inconsistencies
Solution solution = new Solution(); Solution solution = new Solution();
@@ -382,6 +401,15 @@ public class ConstraintSystemImpl implements ConstraintSystem {
return solution; return solution;
} }
private void printTypeValue(TypeValue typeValue) {
for (TypeValue bound : typeValue.getUpperBounds()) {
println(" :< " + bound);
}
for (TypeValue bound : typeValue.getLowerBounds()) {
println(" :> " + bound);
}
}
private void check(TypeValue typeValue, Solution solution) { private void check(TypeValue typeValue, Solution solution) {
try { try {
KnownType resultingValue = typeValue.getValue(); KnownType resultingValue = typeValue.getValue();
@@ -416,7 +444,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
} }
} }
solution.registerError("[TODO] Loop in constraints"); solution.registerError("[TODO] Loop in constraints");
e.printStackTrace(); // e.printStackTrace();
} }
} }
@@ -426,6 +454,9 @@ public class ConstraintSystemImpl implements ConstraintSystem {
} }
for (TypeValue upperBound : Sets.newHashSet(current.getUpperBounds())) { for (TypeValue upperBound : Sets.newHashSet(current.getUpperBounds())) {
if (upperBound instanceof KnownType) {
continue;
}
transitiveClosure(upperBound, visited); transitiveClosure(upperBound, visited);
Set<TypeValue> upperBounds = upperBound.getUpperBounds(); Set<TypeValue> upperBounds = upperBound.getUpperBounds();
for (TypeValue transitiveBound : upperBounds) { for (TypeValue transitiveBound : upperBounds) {
@@ -73,7 +73,11 @@ public class DescriptorRenderer implements Renderer {
} }
public String renderType(JetType type) { public String renderType(JetType type) {
return escape(type.toString()); if (type == null) {
return escape("[NULL]");
} else {
return escape(type.toString());
}
} }
protected String escape(String s) { protected String escape(String s) {
@@ -222,7 +226,6 @@ public class DescriptorRenderer implements Renderer {
renderName(descriptor, builder); renderName(descriptor, builder);
renderValueParameters(descriptor, builder); renderValueParameters(descriptor, builder);
// TODO: getReturnType may be uninitialized and throw IllegalStateException // stepan.koltsov@ 2011-11-21
builder.append(" : ").append(escape(renderType(descriptor.getReturnType()))); builder.append(" : ").append(escape(renderType(descriptor.getReturnType())));
return super.visitFunctionDescriptor(descriptor, builder); return super.visitFunctionDescriptor(descriptor, builder);
} }
@@ -1,4 +0,0 @@
import java.util.Collections
import java.util.List
val ab = Collections.emptyList<Int>() : List<Int>?
@@ -1,3 +1,5 @@
// +JDK
namespace abstract namespace abstract
class MyClass() { class MyClass() {
@@ -238,4 +240,4 @@ abstract class B3(i: Int) {
fun foo(a: B3) { fun foo(a: B3) {
val <!UNUSED_VARIABLE!>a<!> = <!CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS!>B3()<!> val <!UNUSED_VARIABLE!>a<!> = <!CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS!>B3()<!>
val <!UNUSED_VARIABLE!>b<!> = <!CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS!>B1(2, "s")<!> val <!UNUSED_VARIABLE!>b<!> = <!CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS!>B1(2, "s")<!>
} }
@@ -88,4 +88,4 @@ open class C {
t = <!UNUSED_VALUE!>this@C<!> t = <!UNUSED_VALUE!>this@C<!>
} }
} }
} }
@@ -1,3 +1,5 @@
// +JDK
import java.util.* import java.util.*
namespace html { namespace html {
@@ -1,3 +1,5 @@
// +JDK
namespace Jet86 namespace Jet86
class A { class A {
@@ -27,4 +29,4 @@ val s = <!NO_CLASS_OBJECT!>System<!> // error
fun test() { fun test() {
System.out?.println() System.out?.println()
java.lang.System.out?.println() java.lang.System.out?.println()
} }
@@ -1,3 +1,5 @@
// +JDK
trait A { trait A {
fun foo() : Int = 1 fun foo() : Int = 1
fun foo2() : Int = 1 fun foo2() : Int = 1
@@ -1,3 +1,5 @@
// +JDK
fun Int?.optint() : Unit {} fun Int?.optint() : Unit {}
val Int?.optval : Unit = () val Int?.optval : Unit = ()
@@ -68,4 +70,4 @@ namespace null_safety {
if (command == null) 1 if (command == null) 1
} }
} }
@@ -1,3 +1,5 @@
// +JDK
import java.util.*; import java.util.*;
class NotRange1() { class NotRange1() {
@@ -1,3 +1,5 @@
// +JDK
fun none() {} fun none() {}
fun unitEmptyInfer() {} fun unitEmptyInfer() {}
@@ -209,4 +211,4 @@ fun testFunctionLiterals() {
object A {} object A {}
} }
} }
@@ -1,3 +1,5 @@
// +JDK
namespace foobar namespace foobar
namespace a { namespace a {
@@ -60,4 +62,4 @@ abstract class Collection<E> : Iterable<E> {
} }
return iteratee.done() return iteratee.done()
} }
} }
@@ -1,3 +1,5 @@
// +JDK
fun test() { fun test() {
val a : Int? = 0 val a : Int? = 0
if (a != null) { if (a != null) {
@@ -277,4 +279,4 @@ fun f9(a : Int?) : Int {
if (a != null) if (a != null)
return a return a
return 1 return 1
} }
@@ -1,3 +1,5 @@
// +JDK
// Fixpoint generic in Java: Enum<T extends Enum<T>> // Fixpoint generic in Java: Enum<T extends Enum<T>>
fun test(a : annotation.RetentionPolicy) { fun test(a : annotation.RetentionPolicy) {
@@ -17,4 +19,4 @@ fun test(a : java.util.ArrayList<Int>) {
fun test(a : java.lang.Class<Int>) { fun test(a : java.lang.Class<Int>) {
} }
@@ -1,3 +1,5 @@
// +JDK
import java.* import java.*
import util.* import util.*
import <!UNRESOLVED_REFERENCE!>utils<!>.* import <!UNRESOLVED_REFERENCE!>utils<!>.*
@@ -49,4 +51,4 @@ fun test(l : java.util.List<Int>) {
namespace xxx { namespace xxx {
import java.lang.Class; import java.lang.Class;
} }
@@ -1,3 +1,5 @@
// +JDK
fun t1() : Int{ fun t1() : Int{
return 0 return 0
<!UNREACHABLE_CODE!>1<!> <!UNREACHABLE_CODE!>1<!>
@@ -50,7 +50,7 @@ class MyTest() {
i = <!UNUSED_VALUE!>456<!>; i = <!UNUSED_VALUE!>456<!>;
} }
fun testWhile(a : Any?, b : Any?) { fun testWhile() {
var a : Any? = true var a : Any? = true
var b : Any? = 34 var b : Any? = 34
while (a is Any) { while (a is Any) {
@@ -139,4 +139,4 @@ fun testBackingFieldsNotMarked() {
} }
} }
fun doSmth(i : Int) {} fun doSmth(i : Int) {}
@@ -1,3 +1,5 @@
// +JDK
class Foo1() : java.util.ArrayList<Int>() class Foo1() : java.util.ArrayList<Int>()
open class Bar() { open class Bar() {
@@ -1,4 +1,5 @@
// KT-389 Wrong type inference for varargs etc. // KT-389 Wrong type inference for varargs etc.
// +JDK
import java.util.* import java.util.*
@@ -23,4 +24,4 @@ fun test() {
fool(1, 2, 3) fool(1, 2, 3)
food(1.0, 2.0, 3.0) food(1.0, 2.0, 3.0)
foof(1.0.flt, 2.0.flt, 3.0.flt) foof(1.0.flt, 2.0.flt, 3.0.flt)
} }
@@ -13,16 +13,19 @@ fun foo() : Int {
1 + <!UNRESOLVED_REFERENCE!>a<!> => 1 1 + <!UNRESOLVED_REFERENCE!>a<!> => 1
in 1..<!UNRESOLVED_REFERENCE!>a<!> => 1 in 1..<!UNRESOLVED_REFERENCE!>a<!> => 1
!in 1..<!UNRESOLVED_REFERENCE!>a<!> => 1 !in 1..<!UNRESOLVED_REFERENCE!>a<!> => 1
.<!UNRESOLVED_REFERENCE!>a<!> => 1 // Commented for KT-621 .<!!UNRESOLVED_REFERENCE!>a<!!> => 1
.equals(1).<!UNRESOLVED_REFERENCE!>a<!> => 1 // Commented for KT-621 .equals(1).<!!UNRESOLVED_REFERENCE!>a<!!> => 1
<!UNNECESSARY_SAFE_CALL!>?.<!>equals(1) => 1 // Commented for KT-621 <!UNNECESSARY_SAFE_CALL!!>?.<!!>equals(1) => 1
else => 1 else => 1
} }
return when (<!USELESS_ELVIS!>x<!>?:null) {
<!UNSAFE_CALL!>.<!>foo() => 1 // Commented for KT-621
.equals(1) => 1 // return when (<!!USELESS_ELVIS!>x<!!>?:null) {
?.equals(1).equals(2) => 1 // <!!UNSAFE_CALL!!>.<!!>foo() => 1
} // .equals(1) => 1
// ?.equals(1).equals(2) => 1
// }
return 0
} }
val _type_test : Int = foo() // this is needed to ensure the inferred return type of foo() val _type_test : Int = foo() // this is needed to ensure the inferred return type of foo()
@@ -0,0 +1,6 @@
// +JDK
import java.util.List;
import java.util.Collection;
fun ff(c: Collection<String>) = c <!CAST_NEVER_SUCCEEDS!>as<!> List<Int>
@@ -0,0 +1,6 @@
// +JDK
import java.util.List;
import java.util.Collection;
fun ff(c: Collection<String>) = c as List<String>
@@ -0,0 +1,6 @@
// +JDK
import java.util.List;
fun ff(l: Any) = l as List<*>
@@ -0,0 +1,5 @@
// +JDK
import java.util.List;
fun ff(a: Any) = <!UNCHECKED_CAST!>a as List<String><!>
@@ -0,0 +1,7 @@
// +JDK
import java.util.Collection;
import java.util.List;
fun ff(l: Collection<String>) = l is List<String>
@@ -0,0 +1,11 @@
// +JDK
import java.util.Collection;
import java.util.List;
open class A
class B : A
fun ff(l: Collection<B>) = l is List<out A>
@@ -0,0 +1,5 @@
// +JDK
import java.util.List;
fun ff(l: Any) = l is <!CANNOT_CHECK_FOR_ERASED!>List<String><!>
@@ -0,0 +1,5 @@
// +JDK
import java.util.List;
fun ff(l: Any) = l is List<*>
@@ -0,0 +1,3 @@
class MyList<T>
fun ff(a: Any) = a is MyList<String>
@@ -0,0 +1,4 @@
trait Aaa
trait Bbb
fun f(a: Aaa) = a is Bbb
@@ -0,0 +1,8 @@
// +JDK
import java.util.List;
fun ff(l: Any) = when(l) {
is <!CANNOT_CHECK_FOR_ERASED!>List<String><!> => 1
else 2
}
@@ -1,3 +1,5 @@
// +JDK
import java.* import java.*
import util.* import util.*
@@ -63,4 +65,4 @@ fun main(args: Array<String>) {
catch(e: Throwable) { catch(e: Throwable) {
System.out?.println(e.getMessage()) System.out?.println(e.getMessage())
} }
} }

Some files were not shown because too many files have changed in this diff Show More