Merge remote branch 'origin/master'
This commit is contained in:
@@ -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"/>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
+55
@@ -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();
|
||||
|
||||
+10
-15
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+40
-9
@@ -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>?
|
||||
+3
-1
@@ -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<!>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
// +JDK
|
||||
|
||||
import java.util.*
|
||||
|
||||
namespace html {
|
||||
+3
-1
@@ -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()
|
||||
}
|
||||
}
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
// +JDK
|
||||
|
||||
trait A {
|
||||
fun foo() : Int = 1
|
||||
fun foo2() : Int = 1
|
||||
+3
-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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
// +JDK
|
||||
|
||||
import java.util.*;
|
||||
|
||||
class NotRange1() {
|
||||
+3
-1
@@ -1,3 +1,5 @@
|
||||
// +JDK
|
||||
|
||||
fun none() {}
|
||||
|
||||
fun unitEmptyInfer() {}
|
||||
@@ -209,4 +211,4 @@ fun testFunctionLiterals() {
|
||||
object A {}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
// +JDK
|
||||
|
||||
namespace foo
|
||||
|
||||
class X {}
|
||||
+3
-1
@@ -1,3 +1,5 @@
|
||||
// +JDK
|
||||
|
||||
namespace foobar
|
||||
|
||||
namespace a {
|
||||
@@ -60,4 +62,4 @@ abstract class Collection<E> : Iterable<E> {
|
||||
}
|
||||
return iteratee.done()
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -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
|
||||
}
|
||||
}
|
||||
+3
-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>) {
|
||||
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -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;
|
||||
}
|
||||
}
|
||||
+2
@@ -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) {}
|
||||
|
||||
+2
@@ -1,3 +1,5 @@
|
||||
// +JDK
|
||||
|
||||
class Foo1() : java.util.ArrayList<Int>()
|
||||
|
||||
open class Bar() {
|
||||
+2
-1
@@ -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)
|
||||
}
|
||||
}
|
||||
+11
-8
@@ -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
|
||||
}
|
||||
+3
-1
@@ -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
Reference in New Issue
Block a user