Merge remote branch 'origin/master'
This commit is contained in:
@@ -1,4 +1,20 @@
|
|||||||
<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.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"/>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
|||||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
@@ -113,6 +114,7 @@ public class GenerationState {
|
|||||||
}
|
}
|
||||||
catch (Throwable e) {
|
catch (Throwable e) {
|
||||||
errorHandler.reportException(e, namespace.getContainingFile().getVirtualFile().getUrl());
|
errorHandler.reportException(e, namespace.getContainingFile().getVirtualFile().getUrl());
|
||||||
|
DiagnosticUtils.throwIfRunningOnServer(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.intellij.psi.util.PsiModificationTracker;
|
|||||||
import com.intellij.util.Function;
|
import com.intellij.util.Function;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||||
|
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
@@ -68,18 +69,8 @@ public class AnalyzerFacade {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
catch (Throwable e) {
|
catch (Throwable e) {
|
||||||
// This is needed for the Web Demo server to log the exceptions coming from the analyzer instead of showing them in the editor.
|
DiagnosticUtils.throwIfRunningOnServer(e);
|
||||||
if (System.getProperty("kotlin.running.in.server.mode", "false").equals("true")) {
|
|
||||||
if (e instanceof RuntimeException) {
|
|
||||||
RuntimeException runtimeException = (RuntimeException) e;
|
|
||||||
throw runtimeException;
|
|
||||||
}
|
|
||||||
if (e instanceof Error) {
|
|
||||||
Error error = (Error) e;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
||||||
bindingTraceContext.report(Errors.EXCEPTION_WHILE_ANALYZING.on(file, e));
|
bindingTraceContext.report(Errors.EXCEPTION_WHILE_ANALYZING.on(file, e));
|
||||||
@@ -93,5 +84,4 @@ public class AnalyzerFacade {
|
|||||||
}
|
}
|
||||||
return bindingContextCachedValue.getValue();
|
return bindingContextCachedValue.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -81,4 +81,19 @@ public class DiagnosticUtils {
|
|||||||
}
|
}
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void throwIfRunningOnServer(Throwable e) {
|
||||||
|
// This is needed for the Web Demo server to log the exceptions coming from the analyzer instead of showing them in the editor.
|
||||||
|
if (System.getProperty("kotlin.running.in.server.mode", "false").equals("true")) {
|
||||||
|
if (e instanceof RuntimeException) {
|
||||||
|
RuntimeException runtimeException = (RuntimeException) e;
|
||||||
|
throw runtimeException;
|
||||||
|
}
|
||||||
|
if (e instanceof Error) {
|
||||||
|
Error error = (Error) e;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import java.lang.reflect.Field;
|
|||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Severity.ERROR;
|
import static org.jetbrains.jet.lang.diagnostics.Severity.ERROR;
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Severity.WARNING;
|
import static org.jetbrains.jet.lang.diagnostics.Severity.WARNING;
|
||||||
@@ -288,7 +289,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) {
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
+55
@@ -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();
|
||||||
|
|||||||
+12
-2
@@ -1,11 +1,14 @@
|
|||||||
package org.jetbrains.jet.lang.types.expressions;
|
package org.jetbrains.jet.lang.types.expressions;
|
||||||
|
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.openapi.util.Ref;
|
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.TypeParameterDescriptor;
|
||||||
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 +20,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;
|
||||||
@@ -245,6 +247,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 +258,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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+40
-9
@@ -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("<?>");
|
||||||
|
} 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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import java.util.List;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
fun ff(c: Collection<String>) = c <!CAST_NEVER_SUCCEEDS!>as<!> List<Int>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import java.util.List;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
fun ff(c: Collection<String>) = c as List<String>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
fun ff(l: Any) = l as List<*>
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
fun ff(a: Any) = <!UNCHECKED_CAST!>a as List<String><!>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
fun ff(l: Collection<String>) = l is List<String>
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
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,3 @@
|
|||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
fun ff(l: Any) = l is <!CANNOT_CHECK_FOR_ERASED!>List<String><!>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
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,6 @@
|
|||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
fun ff(l: Any) = when(l) {
|
||||||
|
is <!CANNOT_CHECK_FOR_ERASED!>List<String><!> => 1
|
||||||
|
else 2
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
//KT-600 Problem with 'sure' extension function type inference
|
||||||
|
|
||||||
|
fun <T : Any> T?.sure() : T { if (this != null) return this else throw NullPointerException() }
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val i : Int? = 10
|
||||||
|
val <!UNUSED_VARIABLE!>i2<!> : Int = i.sure() // inferred type is Int? but Int was excepted
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
//KT-549 type inference failed
|
||||||
|
namespace demo
|
||||||
|
|
||||||
|
fun filter<T>(list : Array<T>, filter : fun (T) : Boolean) : java.util.List<T> {
|
||||||
|
val answer = java.util.ArrayList<T>();
|
||||||
|
for (l in list) {
|
||||||
|
if (filter(l)) answer.add(l)
|
||||||
|
}
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main(args : Array<String>) {
|
||||||
|
for (a in filter(args, {it.length > 1})) {
|
||||||
|
System.out?.println("Hello, ${a}!")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
//KT-580 Type inference failed
|
||||||
|
namespace whats.the.difference
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
fun iarray(vararg a : String) = a // BUG
|
||||||
|
|
||||||
|
fun main(vals : IntArray) {
|
||||||
|
val vals = iarray("789", "678", "567")
|
||||||
|
val diffs = ArrayList<Int>
|
||||||
|
for (i in vals.indices) {
|
||||||
|
for (j in i..vals.lastIndex()) // Type inference failed
|
||||||
|
diffs.add(vals[i].length - vals[j].length)
|
||||||
|
for (j in i..vals.lastIndex) // Type inference failed
|
||||||
|
diffs.add(vals[i].length - vals[j].length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> Array<T>.lastIndex() = size - 1
|
||||||
|
val <T> Array<T>.lastIndex : Int get() = size - 1
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
//KT-571 Type inference failed
|
||||||
|
fun <T, R> let(t : T, body : fun(T) : R) = body(t)
|
||||||
|
private fun double(d : Int) : Int = let(d * 2) {it / 10 + it * 2 % 10}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
fun typeName(a: Any?) : String {
|
fun typeName(a: Any?) : String {
|
||||||
return when(a) {
|
return when(a) {
|
||||||
is java.util.ArrayList<Int> => "array list"
|
is java.util.ArrayList<*> => "array list"
|
||||||
else => "no idea"
|
else => "no idea"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,4 +8,4 @@ fun typeName(a: Any?) : String {
|
|||||||
fun box() : String {
|
fun box() : String {
|
||||||
if(typeName(java.util.ArrayList<Int> ()) != "array list") return "array list failed"
|
if(typeName(java.util.ArrayList<Int> ()) != "array list") return "array list failed"
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ fun t3() {
|
|||||||
|
|
||||||
fun t4() {
|
fun t4() {
|
||||||
val e: E? = E()
|
val e: E? = E()
|
||||||
System.out?.println(e?.foo() == e) //verify error
|
System.out?.println(e?.bar() == e) //verify error
|
||||||
System.out?.println(e?.foo()) //verify error
|
System.out?.println(e?.foo()) //verify error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,4 +35,5 @@ class C(val x: Int)
|
|||||||
class D(val s: String)
|
class D(val s: String)
|
||||||
class E() {
|
class E() {
|
||||||
fun foo() = 1
|
fun foo() = 1
|
||||||
|
fun bar() = this
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,6 +162,22 @@ public class JetTypeCheckerTest extends JetLiteFixture {
|
|||||||
assertIntersection("Int?", "Int?", "Int?");
|
assertIntersection("Int?", "Int?", "Int?");
|
||||||
assertIntersection("Int", "Int?", "Int");
|
assertIntersection("Int", "Int?", "Int");
|
||||||
assertIntersection("Int", "Int", "Int?");
|
assertIntersection("Int", "Int", "Int?");
|
||||||
|
|
||||||
|
assertIntersection("Int", "Any", "Int");
|
||||||
|
assertIntersection("Int", "Int", "Any");
|
||||||
|
|
||||||
|
assertIntersection("Int", "Any", "Int?");
|
||||||
|
assertIntersection("Int", "Int?", "Any");
|
||||||
|
assertIntersection("Int", "Any?", "Int");
|
||||||
|
assertIntersection("Int", "Int", "Any?");
|
||||||
|
|
||||||
|
assertIntersection("Nothing", "Nothing", "Nothing");
|
||||||
|
assertIntersection("Nothing?", "Nothing?", "Nothing?");
|
||||||
|
assertIntersection("Nothing", "Nothing", "Nothing?");
|
||||||
|
assertIntersection("Nothing", "Nothing?", "Nothing");
|
||||||
|
|
||||||
|
assertIntersection("Nothing?", "String?", "Nothing?");
|
||||||
|
assertIntersection("Nothing?", "Nothing?", "String?");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBasicSubtyping() throws Exception {
|
public void testBasicSubtyping() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user