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">
<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">
<unzip dest="ideaSDK">
<fileset dir="ideaSDK" includes="ideaIC*.zip"/>
+2 -2
View File
@@ -20,7 +20,7 @@
<target name="compileRT">
<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"/>
<classpath refid="classpath"/>
</javac>
@@ -36,7 +36,7 @@
<target name="compile" depends="compileRT">
<mkdir dir="${output}/classes/compiler"/>
<javac destdir="${output}/classes/compiler">
<javac destdir="${output}/classes/compiler" debug="true" debuglevel="lines,vars,source">
<src refid="sourcepath"/>
<classpath refid="classpath"/>
</javac>
@@ -10,6 +10,7 @@ import org.objectweb.asm.commons.InstructionAdapter;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
/*
* @author max
@@ -38,6 +39,8 @@ public abstract class CodegenContext {
public final ObjectOrClosureCodegen closure;
HashMap<JetType,Integer> typeInfoConstants;
HashMap<Integer,JetType> reverseTypeInfoConstants;
int typeInfoConstantsCount;
HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors;
protected StackValue outerExpression;
@@ -177,13 +180,16 @@ public abstract class CodegenContext {
if(parentContext != STATIC)
return parentContext.getTypeInfoConstantIndex(type);
if(typeInfoConstants == null)
typeInfoConstants = new HashMap<JetType, Integer>();
if(typeInfoConstants == null) {
typeInfoConstants = new LinkedHashMap<JetType, Integer>();
reverseTypeInfoConstants = new LinkedHashMap<Integer, JetType>();
}
Integer index = typeInfoConstants.get(type);
if(index == null) {
index = typeInfoConstants.size();
index = typeInfoConstantsCount++;
typeInfoConstants.put(type, index);
reverseTypeInfoConstants.put(index, type);
}
return index;
}
@@ -2068,14 +2068,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return type;
}
private void generateNewArray(JetCallExpression expression, JetType arrayType) {
public void generateNewArray(JetCallExpression expression, JetType arrayType) {
List<? extends ValueArgument> args = expression.getValueArguments();
boolean isArray = state.getStandardLibrary().getArray().equals(arrayType.getConstructor().getDeclarationDescriptor());
if(isArray) {
if (args.size() != 2 && !arrayType.getArguments().get(0).getType().isNullable()) {
throw new CompilationException("array constructor of non-nullable type requires two arguments");
}
// if (args.size() != 2 && !arrayType.getArguments().get(0).getType().isNullable()) {
// throw new CompilationException("array constructor of non-nullable type requires two arguments");
// }
}
else {
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);
}
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) {
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
boolean javaClass = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor) instanceof PsiClass;
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 {
if (!hasTypeInfoForInstanceOf(jetType)) {
expressionToGen.put(OBJECT_TYPE, v);
if (leaveExpressionOnStack) {
v.dup();
@@ -2479,6 +2489,14 @@ If finally block is present, its last expression is the value of try expression.
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) {
@@ -2656,30 +2674,6 @@ If finally block is present, its last expression is the value of try expression.
conditionValue = generatePatternMatch(pattern, patternCondition.isNegated(),
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 {
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.commons.InstructionAdapter;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.objectweb.asm.Opcodes.*;
@@ -114,11 +112,12 @@ public class NamespaceCodegen {
private void generateTypeInfoFields(JetNamespace namespace, CodegenContext context) {
if(context.typeInfoConstants != null) {
String jvmClassName = getJVMClassName(namespace.getName());
for(Map.Entry<JetType,Integer> e : (context.typeInfoConstants != null ? context.typeInfoConstants : Collections.<JetType,Integer>emptyMap()).entrySet()) {
String fieldName = "$typeInfoCache$" + e.getValue();
for(int index = 0; index != context.typeInfoConstantsCount; index++) {
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);
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);
v.visitFieldInsn(GETSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;");
v.visitInsn(DUP);
@@ -126,7 +125,7 @@ public class NamespaceCodegen {
v.visitJumpInsn(IFNONNULL, end);
v.pop();
generateTypeInfo(context, v, e.getKey(), state.getTypeMapper(), e.getKey());
generateTypeInfo(context, v, type, state.getTypeMapper(), type);
v.dup();
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.StackValue;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetParenthesizedExpression;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
@@ -23,7 +24,10 @@ public class Increment implements IntrinsicMethod {
@Override
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) {
final int index = codegen.indexOfLocal((JetReferenceExpression) operand);
if (index >= 0 && JetTypeMapper.isIntPrimitive(expectedType)) {
@@ -33,6 +37,7 @@ public class Increment implements IntrinsicMethod {
}
StackValue value = codegen.genQualified(receiver, operand);
value. dupReceiver(v);
value. dupReceiver(v);
value.put(expectedType, v);
if (expectedType == Type.LONG_TYPE) {
v.lconst(myDelta);
@@ -44,10 +49,11 @@ public class Increment implements IntrinsicMethod {
v.dconst(myDelta);
}
else {
v.aconst(myDelta);
v.iconst(myDelta);
}
v.add(expectedType);
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.plugin.JetFileType;
import org.objectweb.asm.Opcodes;
import sun.tools.tree.NewArrayExpression;
import java.util.*;
@@ -85,6 +86,7 @@ public class IntrinsicMethods {
declareOverload(myStdLib.getLibraryScope().getFunctions("equals"), 1, EQUALS);
declareOverload(myStdLib.getLibraryScope().getFunctions("identityEquals"), 1, EQUALS);
declareOverload(myStdLib.getLibraryScope().getFunctions("plus"), 1, new StringPlus());
declareOverload(myStdLib.getLibraryScope().getFunctions("Array"), 1, new NewArray());
declareIntrinsicFunction("ByteIterator", "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>
}
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 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_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);
}
@@ -62,10 +62,6 @@ public class JetControlFlowProcessor {
private class CFPVisitor extends JetVisitorVoid {
private final boolean inCondition;
private final JetVisitorVoid conditionVisitor = new JetVisitorVoid() {
@Override
public void visitWhenConditionCall(JetWhenConditionCall condition) {
value(condition.getCallSuffixExpression(), CFPVisitor.this.inCondition); // TODO : inCondition?
}
@Override
public void visitWhenConditionInRange(JetWhenConditionInRange condition) {
@@ -21,7 +21,9 @@ public interface CallableDescriptor extends DeclarationDescriptor {
@NotNull
List<TypeParameterDescriptor> getTypeParameters();
@NotNull
/**
* Method may return null for not yet fully initialized object or if error occurred.
*/
JetType getReturnType();
@NotNull
@@ -120,7 +120,6 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
}
@Override
@NotNull
public JetType getReturnType() {
return unsubstitutedReturnType;
}
@@ -113,7 +113,6 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
return expectedThisObject;
}
@NotNull
@Override
public JetType getReturnType() {
return getOutType();
@@ -34,7 +34,6 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor {
return Collections.emptyList();
}
@NotNull
@Override
public JetType getReturnType() {
return returnType;
@@ -84,7 +84,6 @@ public abstract class VariableDescriptorImpl extends DeclarationDescriptorImpl i
return ReceiverDescriptor.NO_RECEIVER;
}
@NotNull
@Override
public JetType getReturnType() {
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, 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}");
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}") {
@Override
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}") {
@Override
protected String makeMessageForA(@NotNull JetClassOrObject jetClassOrObject) {
return jetClassOrObject.getName();
return JetPsiUtil.safeName(jetClassOrObject.getName());
}
@Override
@@ -419,7 +419,10 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
else return false;
}
else return false;
else {
return false;
}
return true;
}
@@ -764,7 +767,6 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* whenCondition
* : expression
* : ("." | "?." postfixExpression typeArguments? valueArguments?
* : ("in" | "!in") expression
* : ("is" | "!is") isRHS
* ;
@@ -793,21 +795,10 @@ public class JetExpressionParsing extends AbstractJetParsing {
parsePattern();
}
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 {
PsiBuilder.Marker expressionPattern = mark();
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 {
parseExpression();
}
@@ -356,10 +356,6 @@ public class JetVisitor<R, D> extends PsiElementVisitor {
return visitExpression(expression, data);
}
public R visitWhenConditionCall(JetWhenConditionCall condition, D data) {
return visitJetElement(condition, data);
}
public R visitWhenConditionIsPattern(JetWhenConditionIsPattern condition, D data) {
return visitJetElement(condition, data);
}
@@ -354,10 +354,6 @@ public class JetVisitorVoid extends PsiElementVisitor {
visitExpression(expression);
}
public void visitWhenConditionCall(JetWhenConditionCall condition) {
visitJetElement(condition);
}
public void visitWhenConditionIsPattern(JetWhenConditionIsPattern 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
*/
public class CallResolver {
private static final JetType DONT_CARE = ErrorUtils.createErrorTypeWithCustomDebugName("DONT_CARE");
private final JetSemanticServices semanticServices;
private final OverloadingConflictResolver overloadingConflictResolver;
private final DataFlowInfo dataFlowInfo;
@@ -412,7 +414,7 @@ public class CallResolver {
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()) {
ResolvedValueArgument valueArgument = entry.getValue();
@@ -428,7 +430,7 @@ public class CallResolver {
// We'll type check the arguments later, with the inferred types expected
TemporaryBindingTrace traceForUnknown = TemporaryBindingTrace.create(temporaryTrace);
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) {
constraintSystem.addSubtypingConstraint(type, effectiveExpectedType);
}
@@ -439,10 +441,10 @@ public class CallResolver {
}
// Error is already reported if something is missing
ReceiverDescriptor receiverParameter = candidateCall.getReceiverArgument();
ReceiverDescriptor candidateReceiver = candidate.getReceiverParameter();
if (receiverParameter.exists() && candidateReceiver.exists()) {
constraintSystem.addSubtypingConstraint(receiverParameter.getType(), candidateReceiver.getType());
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
ReceiverDescriptor receiverParameter = candidate.getReceiverParameter();
if (receiverArgument.exists() && receiverParameter.exists()) {
constraintSystem.addSubtypingConstraint(receiverArgument.getType(), receiverParameter.getType());
}
if (expectedType != NO_EXPECTED_TYPE) {
@@ -171,11 +171,20 @@ public class ErrorUtils {
}
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) {
return createErrorType(value + " is not allowed here]", value.getType().getMemberScope());
return createErrorType(value + " is not allowed here", value.getType().getMemberScope());
}
public static ClassifierDescriptor getErrorClass() {
@@ -284,7 +284,7 @@ public class JetStandardLibrary {
}
@NotNull
public ClassDescriptor getArray() {
public ClassDescriptor getArray() {
initStdClasses();
return arrayClass;
}
@@ -110,54 +110,65 @@ public class TypeUtils {
}
@Nullable
public static JetType intersect(JetTypeChecker typeChecker, Set<JetType> types) {
public static JetType intersect(@NotNull JetTypeChecker typeChecker, @NotNull Set<JetType> types) {
assert !types.isEmpty();
if (types.size() == 1) {
return types.iterator().next();
}
StringBuilder debugName = new StringBuilder();
boolean nullable = false;
Set<JetType> resultingTypes = Sets.newHashSet();
// Intersection of T1..Tn is an intersection of their non-null versions,
// made nullable is they all were nullable
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:
for (Iterator<JetType> iterator = types.iterator(); iterator.hasNext();) {
JetType type = iterator.next();
for (JetType type : nullabilityStripped) {
if (!canHaveSubtypes(typeChecker, type)) {
for (JetType other : types) {
for (JetType other : nullabilityStripped) {
// It makes sense to check for subtyping of other <: type, despite that
// type is not supposed to be open, for there're enums
if (!type.equals(other) && !typeChecker.isSubtypeOf(type, other) && !typeChecker.isSubtypeOf(other, type)) {
return null;
}
}
return type;
return makeNullableAsSpecified(type, allNullable);
}
else {
for (JetType other : types) {
for (JetType other : nullabilityStripped) {
if (!type.equals(other) && typeChecker.isSubtypeOf(other, type)) {
continue outer;
}
}
}
nullable |= type.isNullable();
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();
TypeConstructor constructor = new TypeConstructorImpl(
null,
noAnnotations,
false,
debugName.toString(),
makeDebugNameForIntersectionType(resultingTypes).toString(),
Collections.<TypeParameterDescriptor>emptyList(),
resultingTypes);
@@ -171,11 +182,25 @@ public class TypeUtils {
return new JetTypeImpl(
noAnnotations,
constructor,
nullable,
allNullable,
Collections.<TypeProjection>emptyList(),
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) {
if (type.isNullable()) {
return true;
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.types.expressions;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
@@ -8,6 +9,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
@@ -245,10 +247,63 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
else {
if (typeChecker.isSubtypeOf(actualType, targetType)) {
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
public JetType visitTupleExpression(JetTupleExpression expression, ExpressionTypingContext context) {
List<JetExpression> entries = expression.getEntries();
@@ -6,6 +6,7 @@ import com.intellij.openapi.util.Ref;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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.resolve.calls.autocasts.DataFlowInfo;
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.types.*;
import java.util.List;
import java.util.Set;
import java.util.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
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};
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
public void visitWhenConditionInRange(JetWhenConditionInRange condition) {
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) {
// TODO : Take auto casts into account?
if (type == null) {
@@ -253,6 +243,11 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
if (TypeUtils.intersect(context.semanticServices.getTypeChecker(), Sets.newHashSet(type, subjectType)) == null) {
// context.trace.getErrorHandler().genericError(reportErrorOn.getNode(), "Incompatible types: " + type + " and " + 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 java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -46,8 +47,19 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
public static abstract class TypeValue {
private final Set<TypeValue> upperBounds = Sets.newHashSet();
private final Set<TypeValue> lowerBounds = Sets.newHashSet();
private final Set<TypeValue> mutableUpperBounds = 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
public Set<TypeValue> getUpperBounds() {
@@ -86,8 +98,8 @@ public class ConstraintSystemImpl implements ConstraintSystem {
throw new LoopInTypeVariableConstraintsException();
}
if (value == null) {
JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
beingComputed = true;
JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
try {
if (positionVariance == Variance.IN_VARIANCE) {
// maximal solution
@@ -320,8 +332,8 @@ public class ConstraintSystemImpl implements ConstraintSystem {
private void addSubtypingConstraintOnTypeValues(TypeValue typeValueForLower, TypeValue typeValueForUpper) {
println(typeValueForLower + " :< " + typeValueForUpper);
if (typeValueForLower != typeValueForUpper) {
typeValueForLower.getUpperBounds().add(typeValueForUpper);
typeValueForUpper.getLowerBounds().add(typeValueForLower);
typeValueForLower.addUpperBound(typeValueForUpper);
typeValueForUpper.addLowerBound(typeValueForLower);
}
}
@@ -358,13 +370,20 @@ public class ConstraintSystemImpl implements ConstraintSystem {
// effective bounds for each node
Set<TypeValue> visited = Sets.newHashSet();
for (KnownType knownType : knownTypes.values()) {
transitiveClosure(knownType, visited);
}
for (UnknownType unknownType : unknownTypes.values()) {
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
Solution solution = new Solution();
@@ -382,6 +401,15 @@ public class ConstraintSystemImpl implements ConstraintSystem {
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) {
try {
KnownType resultingValue = typeValue.getValue();
@@ -416,7 +444,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
}
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())) {
if (upperBound instanceof KnownType) {
continue;
}
transitiveClosure(upperBound, visited);
Set<TypeValue> upperBounds = upperBound.getUpperBounds();
for (TypeValue transitiveBound : upperBounds) {
@@ -73,7 +73,11 @@ public class DescriptorRenderer implements Renderer {
}
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) {
@@ -222,7 +226,6 @@ public class DescriptorRenderer implements Renderer {
renderName(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())));
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
class MyClass() {
@@ -238,4 +240,4 @@ abstract class B3(i: Int) {
fun foo(a: 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")<!>
}
}
@@ -88,4 +88,4 @@ open class C {
t = <!UNUSED_VALUE!>this@C<!>
}
}
}
}
@@ -1,3 +1,5 @@
// +JDK
import java.util.*
namespace html {
@@ -1,3 +1,5 @@
// +JDK
namespace Jet86
class A {
@@ -27,4 +29,4 @@ val s = <!NO_CLASS_OBJECT!>System<!> // error
fun test() {
System.out?.println()
java.lang.System.out?.println()
}
}
@@ -1,3 +1,5 @@
// +JDK
trait A {
fun foo() : Int = 1
fun foo2() : Int = 1
@@ -1,3 +1,5 @@
// +JDK
fun Int?.optint() : Unit {}
val Int?.optval : Unit = ()
@@ -68,4 +70,4 @@ namespace null_safety {
if (command == null) 1
}
}
}
@@ -1,3 +1,5 @@
// +JDK
fun none() {}
fun unitEmptyInfer() {}
@@ -209,4 +211,4 @@ fun testFunctionLiterals() {
object A {}
}
}
}
@@ -1,3 +1,5 @@
// +JDK
namespace foobar
namespace a {
@@ -60,4 +62,4 @@ abstract class Collection<E> : Iterable<E> {
}
return iteratee.done()
}
}
}
@@ -1,3 +1,5 @@
// +JDK
fun test() {
val a : Int? = 0
if (a != null) {
@@ -277,4 +279,4 @@ fun f9(a : Int?) : Int {
if (a != null)
return a
return 1
}
}
@@ -1,3 +1,5 @@
// +JDK
// Fixpoint generic in Java: Enum<T extends Enum<T>>
fun test(a : annotation.RetentionPolicy) {
@@ -17,4 +19,4 @@ fun test(a : java.util.ArrayList<Int>) {
fun test(a : java.lang.Class<Int>) {
}
}
@@ -1,3 +1,5 @@
// +JDK
import java.*
import util.*
import <!UNRESOLVED_REFERENCE!>utils<!>.*
@@ -49,4 +51,4 @@ fun test(l : java.util.List<Int>) {
namespace xxx {
import java.lang.Class;
}
}
@@ -1,3 +1,5 @@
// +JDK
fun t1() : Int{
return 0
<!UNREACHABLE_CODE!>1<!>
@@ -50,7 +50,7 @@ class MyTest() {
i = <!UNUSED_VALUE!>456<!>;
}
fun testWhile(a : Any?, b : Any?) {
fun testWhile() {
var a : Any? = true
var b : Any? = 34
while (a is Any) {
@@ -139,4 +139,4 @@ fun testBackingFieldsNotMarked() {
}
}
fun doSmth(i : Int) {}
fun doSmth(i : Int) {}
@@ -1,4 +1,5 @@
// KT-389 Wrong type inference for varargs etc.
// +JDK
import java.util.*
@@ -23,4 +24,4 @@ fun test() {
fool(1, 2, 3)
food(1.0, 2.0, 3.0)
foof(1.0.flt, 2.0.flt, 3.0.flt)
}
}
@@ -13,16 +13,19 @@ fun foo() : Int {
1 + <!UNRESOLVED_REFERENCE!>a<!> => 1
in 1..<!UNRESOLVED_REFERENCE!>a<!> => 1
!in 1..<!UNRESOLVED_REFERENCE!>a<!> => 1
.<!UNRESOLVED_REFERENCE!>a<!> => 1
.equals(1).<!UNRESOLVED_REFERENCE!>a<!> => 1
<!UNNECESSARY_SAFE_CALL!>?.<!>equals(1) => 1
// Commented for KT-621 .<!!UNRESOLVED_REFERENCE!>a<!!> => 1
// Commented for KT-621 .equals(1).<!!UNRESOLVED_REFERENCE!>a<!!> => 1
// Commented for KT-621 <!UNNECESSARY_SAFE_CALL!!>?.<!!>equals(1) => 1
else => 1
}
return when (<!USELESS_ELVIS!>x<!>?:null) {
<!UNSAFE_CALL!>.<!>foo() => 1
.equals(1) => 1
?.equals(1).equals(2) => 1
}
// Commented for KT-621
// return when (<!!USELESS_ELVIS!>x<!!>?:null) {
// <!!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()
@@ -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 util.*
@@ -63,4 +65,4 @@ fun main(args: Array<String>) {
catch(e: Throwable) {
System.out?.println(e.getMessage())
}
}
}

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