Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -1307,6 +1307,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
else if(type.getSort() == Type.DOUBLE) {
|
||||
v.aconst(0d);
|
||||
}
|
||||
else if(type.getSort() == Type.LONG) {
|
||||
v.aconst(0l);
|
||||
}
|
||||
else {
|
||||
v.iconst(0);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.containers.Stack;
|
||||
@@ -115,6 +116,9 @@ public class GenerationState {
|
||||
catch (Throwable e) {
|
||||
errorHandler.reportException(e, namespace.getContainingFile().getVirtualFile().getUrl());
|
||||
DiagnosticUtils.throwIfRunningOnServer(e);
|
||||
if (ApplicationManager.getApplication().isInternal()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +176,8 @@ public class IntrinsicMethods {
|
||||
for (DeclarationDescriptor stringMember : stringMembers) {
|
||||
if (stringMember instanceof FunctionDescriptor) {
|
||||
final FunctionDescriptor stringMethod = (FunctionDescriptor) stringMember;
|
||||
final PsiMethod[] methods = stringPsiClass.findMethodsByName(stringMember.getName(), false);
|
||||
final PsiMethod[] methods = stringPsiClass != null?
|
||||
stringPsiClass.findMethodsByName(stringMember.getName(), false) : new PsiMethod[]{};
|
||||
for (PsiMethod method : methods) {
|
||||
if (method.getParameterList().getParametersCount() == stringMethod.getValueParameters().size()) {
|
||||
myMethods.put(stringMethod, new PsiMethodCall(stringMethod));
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
|
||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
import org.jetbrains.jet.util.lazy.LazyValue;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet.lang.diagnostics;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -13,6 +14,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @author abreslav
|
||||
*/
|
||||
public class DiagnosticUtils {
|
||||
private DiagnosticUtils() {
|
||||
}
|
||||
|
||||
public static String atLocation(@NotNull PsiElement element) {
|
||||
return atLocation(element.getNode());
|
||||
}
|
||||
@@ -28,10 +32,10 @@ public class DiagnosticUtils {
|
||||
|
||||
@Nullable
|
||||
public static PsiElement getClosestPsiElement(@NotNull ASTNode node) {
|
||||
while (node != null && node.getPsi() == null) {
|
||||
while (node.getPsi() == null) {
|
||||
node = node.getTreeParent();
|
||||
}
|
||||
return node == null ? null : node.getPsi();
|
||||
return node.getPsi();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -84,14 +88,12 @@ public class DiagnosticUtils {
|
||||
|
||||
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 (System.getProperty("kotlin.running.in.server.mode", "false").equals("true") || ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
if (e instanceof RuntimeException) {
|
||||
RuntimeException runtimeException = (RuntimeException) e;
|
||||
throw runtimeException;
|
||||
throw (RuntimeException) e;
|
||||
}
|
||||
if (e instanceof Error) {
|
||||
Error error = (Error) e;
|
||||
throw error;
|
||||
throw (Error) e;
|
||||
}
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.util.CommonSuppliers;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -153,7 +154,7 @@ public class OverridingUtil {
|
||||
TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
|
||||
TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
|
||||
|
||||
if (!JetTypeImpl.equalTypes(superTypeParameter.getUpperBoundsAsType(), subTypeParameter.getUpperBoundsAsType(), axioms)) {
|
||||
if (!JetTypeChecker.INSTANCE.equalTypes(superTypeParameter.getUpperBoundsAsType(), subTypeParameter.getUpperBoundsAsType(), axioms)) {
|
||||
return OverrideCompatibilityInfo.boundsMismatch(superTypeParameter, subTypeParameter);
|
||||
}
|
||||
}
|
||||
@@ -164,7 +165,7 @@ public class OverridingUtil {
|
||||
JetType superValueParameter = superValueParameters.get(i);
|
||||
JetType subValueParameter = subValueParameters.get(i);
|
||||
|
||||
if (!JetTypeImpl.equalTypes(superValueParameter, subValueParameter, axioms)) {
|
||||
if (!JetTypeChecker.INSTANCE.equalTypes(superValueParameter, subValueParameter, axioms)) {
|
||||
return OverrideCompatibilityInfo.valueParameterTypeMismatch(superValueParameter, subValueParameter);
|
||||
}
|
||||
}
|
||||
@@ -174,7 +175,6 @@ public class OverridingUtil {
|
||||
return OverrideCompatibilityInfo.success();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static boolean isReturnTypeOkForOverride(@NotNull JetTypeChecker typeChecker, @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
|
||||
List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
|
||||
List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WriteThroughScope;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.NamespaceType;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
+1
@@ -10,6 +10,7 @@ import org.jetbrains.jet.lang.psi.JetStringTemplateEntry;
|
||||
import org.jetbrains.jet.lang.psi.JetVisitorVoid;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -116,8 +116,10 @@ public class SubstitutingScope implements JetScope {
|
||||
allDescriptors = Sets.newHashSet();
|
||||
for (DeclarationDescriptor descriptor : workerScope.getAllDescriptors()) {
|
||||
DeclarationDescriptor substitute = substitute(descriptor);
|
||||
assert substitute != null;
|
||||
allDescriptors.add(substitute);
|
||||
// assert substitute != null : descriptor;
|
||||
if (substitute != null) {
|
||||
allDescriptors.add(substitute);
|
||||
}
|
||||
}
|
||||
}
|
||||
return allDescriptors;
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.types;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@@ -1,321 +0,0 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.types.Variance.INVARIANT;
|
||||
import static org.jetbrains.jet.lang.types.Variance.IN_VARIANCE;
|
||||
import static org.jetbrains.jet.lang.types.Variance.OUT_VARIANCE;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class JetTypeChecker {
|
||||
|
||||
public static final JetTypeChecker INSTANCE = new JetTypeChecker();
|
||||
|
||||
private JetTypeChecker() {
|
||||
}
|
||||
|
||||
public boolean isSubtypeOf(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
// return new TypeCheckingProcedure().run(subtype, supertype);
|
||||
return TYPE_CHECKER.run(subtype, supertype);
|
||||
}
|
||||
|
||||
// This method returns the supertype of the first parameter that has the same constructor
|
||||
// as the second parameter, applying the substitution of type arguments to it
|
||||
@Nullable
|
||||
private static JetType findCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
TypeConstructor constructor = subtype.getConstructor();
|
||||
if (constructor.equals(supertype.getConstructor())) {
|
||||
return subtype;
|
||||
}
|
||||
for (JetType immediateSupertype : constructor.getSupertypes()) {
|
||||
JetType correspondingSupertype = findCorrespondingSupertype(immediateSupertype, supertype);
|
||||
if (correspondingSupertype != null) {
|
||||
return TypeSubstitutor.create(subtype).safeSubstitute(correspondingSupertype, Variance.INVARIANT);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static JetType getOutType(TypeParameterDescriptor parameter, TypeProjection argument) {
|
||||
boolean isOutProjected = argument.getProjectionKind() == IN_VARIANCE || parameter.getVariance() == IN_VARIANCE;
|
||||
return isOutProjected ? parameter.getUpperBoundsAsType() : argument.getType();
|
||||
}
|
||||
|
||||
private static JetType getInType(TypeParameterDescriptor parameter, TypeProjection argument) {
|
||||
boolean isOutProjected = argument.getProjectionKind() == OUT_VARIANCE || parameter.getVariance() == OUT_VARIANCE;
|
||||
return isOutProjected ? JetStandardClasses.getNothingType() : argument.getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Methods of this class return true to continue type checking and false to fail
|
||||
*/
|
||||
public interface TypingConstraintBuilder {
|
||||
boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b);
|
||||
boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype);
|
||||
boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype);
|
||||
}
|
||||
|
||||
private static final TypeCheckingProcedure TYPE_CHECKER = new TypeCheckingProcedure(new TypingConstraintBuilder() {
|
||||
@Override
|
||||
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b) {
|
||||
return TypeUtils.equalTypes(a, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
return INSTANCE.isSubtypeOf(subtype, supertype);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
return false; // type checking fails
|
||||
}
|
||||
});
|
||||
|
||||
public static class TypeCheckingProcedure {
|
||||
|
||||
private final TypingConstraintBuilder constraintBuilder;
|
||||
|
||||
public TypeCheckingProcedure(TypingConstraintBuilder constraintBuilder) {
|
||||
this.constraintBuilder = constraintBuilder;
|
||||
}
|
||||
|
||||
public boolean run(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
return isSubtypeOf(subtype, supertype);
|
||||
}
|
||||
|
||||
public boolean isSubtypeOf(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
if (ErrorUtils.isErrorType(subtype) || ErrorUtils.isErrorType(supertype)) {
|
||||
return true;
|
||||
}
|
||||
if (!supertype.isNullable() && subtype.isNullable()) {
|
||||
return false;
|
||||
}
|
||||
subtype = TypeUtils.makeNotNullable(subtype);
|
||||
supertype = TypeUtils.makeNotNullable(supertype);
|
||||
if (JetStandardClasses.isNothingOrNullableNothing(subtype)) {
|
||||
return true;
|
||||
}
|
||||
@Nullable JetType closestSupertype = findCorrespondingSupertype(subtype, supertype);
|
||||
if (closestSupertype == null) {
|
||||
return constraintBuilder.noCorrespondingSupertype(subtype, supertype); // if this returns true, there still isn't any supertype to continue with
|
||||
}
|
||||
|
||||
return checkSubtypeForTheSameConstructor(closestSupertype, supertype);
|
||||
}
|
||||
|
||||
private boolean checkSubtypeForTheSameConstructor(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
TypeConstructor constructor = subtype.getConstructor();
|
||||
assert constructor.equals(supertype.getConstructor()) : constructor + " is not " + supertype.getConstructor();
|
||||
|
||||
List<TypeProjection> subArguments = subtype.getArguments();
|
||||
List<TypeProjection> superArguments = supertype.getArguments();
|
||||
List<TypeParameterDescriptor> parameters = constructor.getParameters();
|
||||
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
||||
TypeParameterDescriptor parameter = parameters.get(i);
|
||||
|
||||
|
||||
TypeProjection subArgument = subArguments.get(i);
|
||||
JetType subIn = getInType(parameter, subArgument);
|
||||
JetType subOut = getOutType(parameter, subArgument);
|
||||
|
||||
TypeProjection superArgument = superArguments.get(i);
|
||||
JetType superIn = getInType(parameter, superArgument);
|
||||
JetType superOut = getOutType(parameter, superArgument);
|
||||
|
||||
if (parameter.getVariance() == INVARIANT && subArgument.getProjectionKind() == INVARIANT && superArgument.getProjectionKind() == INVARIANT) {
|
||||
if (!constraintBuilder.assertEqualTypes(subArgument.getType(), superArgument.getType())) return false;
|
||||
}
|
||||
else {
|
||||
if (!constraintBuilder.assertSubtype(subOut, superOut)) return false;
|
||||
if (!constraintBuilder.assertSubtype(superIn, subIn)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// public static abstract class AbstractTypeCheckingProcedure<T> {
|
||||
//
|
||||
// protected enum StatusAction {
|
||||
// PROCEED(false),
|
||||
// DONE_WITH_CURRENT_TYPE(true),
|
||||
// ABORT_ALL(true);
|
||||
//
|
||||
// private final boolean abort;
|
||||
//
|
||||
// private StatusAction(boolean abort) {
|
||||
// this.abort = abort;
|
||||
// }
|
||||
//
|
||||
// public boolean isAbort() {
|
||||
// return abort;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public final T run(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
// proceedOrStop(subtype, supertype);
|
||||
// return result();
|
||||
// }
|
||||
//
|
||||
// protected abstract StatusAction startForPairOfTypes(@NotNull JetType subtype, @NotNull JetType supertype);
|
||||
//
|
||||
// protected abstract StatusAction noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype);
|
||||
//
|
||||
// protected abstract StatusAction equalTypesRequired(@NotNull JetType subArgumentType, @NotNull JetType superArgumentType);
|
||||
//
|
||||
// protected abstract StatusAction varianceConflictFound(@NotNull TypeProjection subArgument, @NotNull TypeProjection superArgument);
|
||||
//
|
||||
// protected abstract StatusAction doneForPairOfTypes(@NotNull JetType subtype, @NotNull JetType supertype);
|
||||
//
|
||||
// protected abstract T result();
|
||||
//
|
||||
// private StatusAction proceedOrStop(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
// StatusAction statusAction = startForPairOfTypes(subtype, supertype);
|
||||
// if (statusAction.isAbort()) {
|
||||
// return statusAction;
|
||||
// }
|
||||
//
|
||||
// JetType closestSupertype = findCorrespondingSupertype(subtype, supertype);
|
||||
// if (closestSupertype == null) {
|
||||
// return noCorrespondingSupertype(subtype, supertype);
|
||||
// }
|
||||
//
|
||||
// proceed(closestSupertype, supertype);
|
||||
// return doneForPairOfTypes(subtype, supertype);
|
||||
// }
|
||||
//
|
||||
// private void proceed(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
// TypeConstructor constructor = subtype.getConstructor();
|
||||
// assert constructor.equals(supertype.getConstructor()) : constructor + " is not " + supertype.getConstructor();
|
||||
//
|
||||
// List<TypeProjection> subArguments = subtype.getArguments();
|
||||
// List<TypeProjection> superArguments = supertype.getArguments();
|
||||
// List<TypeParameterDescriptor> parameters = constructor.getParameters();
|
||||
//
|
||||
// loop:
|
||||
// for (int i = 0; i < parameters.size(); i++) {
|
||||
// TypeParameterDescriptor parameter = parameters.get(i);
|
||||
// TypeProjection subArgument = subArguments.get(i);
|
||||
// TypeProjection superArgument = superArguments.get(i);
|
||||
//
|
||||
// JetType subArgumentType = subArgument.getType();
|
||||
// JetType superArgumentType = superArgument.getType();
|
||||
//
|
||||
// StatusAction action = null;
|
||||
// switch (parameter.getVariance()) {
|
||||
// case INVARIANT:
|
||||
// switch (superArgument.getProjectionKind()) {
|
||||
// case INVARIANT:
|
||||
// action = equalTypesRequired(subArgumentType, superArgumentType);
|
||||
// break;
|
||||
// case OUT_VARIANCE:
|
||||
// if (!subArgument.getProjectionKind().allowsOutPosition()) {
|
||||
// action = varianceConflictFound(subArgument, superArgument);
|
||||
// }
|
||||
// else {
|
||||
// action = proceedOrStop(subArgumentType, superArgumentType);
|
||||
// }
|
||||
// break;
|
||||
// case IN_VARIANCE:
|
||||
// if (!subArgument.getProjectionKind().allowsInPosition()) {
|
||||
// action = varianceConflictFound(subArgument, superArgument);
|
||||
// }
|
||||
// else {
|
||||
// action = proceedOrStop(superArgumentType, subArgumentType);
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// break;
|
||||
// case IN_VARIANCE:
|
||||
// switch (superArgument.getProjectionKind()) {
|
||||
// case INVARIANT:
|
||||
// case IN_VARIANCE:
|
||||
// action = proceedOrStop(superArgumentType, subArgumentType);
|
||||
// break;
|
||||
// case OUT_VARIANCE:
|
||||
// action = proceedOrStop(subArgumentType, superArgumentType);
|
||||
// break;
|
||||
// }
|
||||
// break;
|
||||
// case OUT_VARIANCE:
|
||||
// switch (superArgument.getProjectionKind()) {
|
||||
// case INVARIANT:
|
||||
// case OUT_VARIANCE:
|
||||
// case IN_VARIANCE:
|
||||
// action = proceedOrStop(subArgumentType, superArgumentType);
|
||||
// break;
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// switch (action) {
|
||||
// case ABORT_ALL: break loop;
|
||||
// case DONE_WITH_CURRENT_TYPE:
|
||||
// default:
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
// private static class TypeCheckingProcedure extends AbstractTypeCheckingProcedure<Boolean> {
|
||||
//
|
||||
// private boolean result = true;
|
||||
//
|
||||
// private StatusAction fail() {
|
||||
// result = false;
|
||||
// return StatusAction.ABORT_ALL;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public StatusAction startForPairOfTypes(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
// if (ErrorUtils.isErrorType(subtype) || ErrorUtils.isErrorType(supertype)) {
|
||||
// return StatusAction.DONE_WITH_CURRENT_TYPE;
|
||||
// }
|
||||
// if (!supertype.isNullable() && subtype.isNullable()) {
|
||||
// return fail();
|
||||
// }
|
||||
// if (JetStandardClasses.isNothingOrNullableNothing(subtype)) {
|
||||
// return StatusAction.DONE_WITH_CURRENT_TYPE;
|
||||
// }
|
||||
// return StatusAction.PROCEED;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected StatusAction noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
// return fail();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected StatusAction equalTypesRequired(@NotNull JetType subArgumentType, @NotNull JetType superArgumentType) {
|
||||
// if (!subArgumentType.equals(superArgumentType)) {
|
||||
// return fail();
|
||||
// }
|
||||
// return StatusAction.PROCEED;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected StatusAction varianceConflictFound(@NotNull TypeProjection subArgument, @NotNull TypeProjection superArgument) {
|
||||
// return fail();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected StatusAction doneForPairOfTypes(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
// return StatusAction.PROCEED;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected Boolean result() {
|
||||
// return result;
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotatedImpl;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
@@ -17,8 +16,6 @@ import java.util.List;
|
||||
*/
|
||||
public final class JetTypeImpl extends AnnotatedImpl implements JetType {
|
||||
|
||||
public static final HashBiMap<TypeConstructor,TypeConstructor> EMPTY_AXIOMS = HashBiMap.<TypeConstructor, TypeConstructor>create();
|
||||
|
||||
private final TypeConstructor constructor;
|
||||
private final List<TypeProjection> arguments;
|
||||
private final boolean nullable;
|
||||
@@ -96,7 +93,7 @@ public final class JetTypeImpl extends AnnotatedImpl implements JetType {
|
||||
JetTypeImpl type = (JetTypeImpl) o;
|
||||
|
||||
// TODO
|
||||
return nullable == type.nullable && equalTypes(this, type, EMPTY_AXIOMS);
|
||||
return nullable == type.nullable && JetTypeChecker.INSTANCE.equalTypes(this, type);
|
||||
// if (nullable != type.nullable) return false;
|
||||
// if (arguments != null ? !arguments.equals(type.arguments) : type.arguments != null) return false;
|
||||
// if (constructor != null ? !constructor.equals(type.constructor) : type.constructor != null) return false;
|
||||
@@ -113,38 +110,5 @@ public final class JetTypeImpl extends AnnotatedImpl implements JetType {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean equalTypes(@NotNull JetType type1, @NotNull JetType type2, @NotNull BiMap<TypeConstructor, TypeConstructor> equalityAxioms) {
|
||||
if (type1.isNullable() != type2.isNullable()) {
|
||||
return false;
|
||||
}
|
||||
TypeConstructor constructor1 = type1.getConstructor();
|
||||
TypeConstructor constructor2 = type2.getConstructor();
|
||||
if (!constructor1.equals(constructor2)) {
|
||||
TypeConstructor img1 = equalityAxioms.get(constructor1);
|
||||
TypeConstructor img2 = equalityAxioms.get(constructor2);
|
||||
if (!(img1 != null && img1.equals(constructor2)) &&
|
||||
!(img2 != null && img2.equals(constructor1))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
List<TypeProjection> type1Arguments = type1.getArguments();
|
||||
List<TypeProjection> type2Arguments = type2.getArguments();
|
||||
if (type1Arguments.size() != type2Arguments.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < type1Arguments.size(); i++) {
|
||||
TypeProjection typeProjection1 = type1Arguments.get(i);
|
||||
TypeProjection typeProjection2 = type2Arguments.get(i);
|
||||
if (typeProjection1.getProjectionKind() != typeProjection2.getProjectionKind()) {
|
||||
return false;
|
||||
}
|
||||
if (!equalTypes(typeProjection1.getType(), typeProjection2.getType(), equalityAxioms)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -125,22 +125,33 @@ public class TypeSubstitutor {
|
||||
private JetType unsafeSubstitute(@NotNull JetType type, @NotNull Variance howThisTypeIsUsed) throws SubstitutionException {
|
||||
if (ErrorUtils.isErrorType(type)) return type;
|
||||
|
||||
TypeConstructor constructor = type.getConstructor();
|
||||
TypeProjection value = substitution.get(constructor);
|
||||
TypeProjection value = getValueWithCorrectNullability(substitution, type);
|
||||
if (value != null) {
|
||||
TypeConstructor constructor = type.getConstructor();
|
||||
assert constructor.getDeclarationDescriptor() instanceof TypeParameterDescriptor;
|
||||
|
||||
return TypeUtils.makeNullableIfNeeded(substitutionResult((TypeParameterDescriptor) constructor.getDeclarationDescriptor(), howThisTypeIsUsed, Variance.INVARIANT, value).getType(), type.isNullable());
|
||||
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) constructor.getDeclarationDescriptor();
|
||||
|
||||
// if (!allows(howThisTypeIsUsed, value.getProjectionKind())) {
|
||||
// throw new SubstitutionException("!!" + value.toString());
|
||||
// }
|
||||
// return value.getType();
|
||||
TypeProjection result = substitutionResult(typeParameterDescriptor, howThisTypeIsUsed, Variance.INVARIANT, value);
|
||||
|
||||
return TypeUtils.makeNullableIfNeeded(result.getType(), type.isNullable());
|
||||
}
|
||||
|
||||
return specializeType(type, howThisTypeIsUsed);
|
||||
}
|
||||
|
||||
private TypeProjection getValueWithCorrectNullability(TypeSubstitution substitution, JetType type) {
|
||||
TypeProjection typeProjection = substitution.get(type.getConstructor());
|
||||
if (typeProjection == null) return null;
|
||||
|
||||
return type.isNullable() ? makeNullableProjection(typeProjection) : typeProjection;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static TypeProjection makeNullableProjection(@NotNull TypeProjection value) {
|
||||
return new TypeProjection(value.getProjectionKind(), TypeUtils.makeNullable(value.getType()));
|
||||
}
|
||||
|
||||
private JetType specializeType(JetType subjectType, Variance callSiteVariance) throws SubstitutionException {
|
||||
if (ErrorUtils.isErrorType(subjectType)) return subjectType;
|
||||
|
||||
@@ -178,7 +189,7 @@ public class TypeSubstitutor {
|
||||
Variance effectiveProjectionKind = asymmetricOr(passedProjectionKind, parameterVariance);
|
||||
Variance effectiveContextVariance = contextCallSiteVariance.superpose(effectiveProjectionKind);
|
||||
|
||||
TypeProjection projectionValue = substitutionContext.get(typeToSubstituteIn.getConstructor());
|
||||
TypeProjection projectionValue = getValueWithCorrectNullability(substitutionContext, typeToSubstituteIn);
|
||||
if (projectionValue != null) {
|
||||
assert typeToSubstituteIn.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.ChainedScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.util.CommonSuppliers;
|
||||
|
||||
import java.util.*;
|
||||
@@ -343,6 +344,11 @@ public class TypeUtils {
|
||||
private static void fillInDeepSubstitutor(@NotNull JetType context, @NotNull TypeSubstitutor substitutor, @NotNull Map<TypeConstructor, TypeProjection> substitution, @Nullable Multimap<TypeConstructor, TypeProjection> fullSubstitution) {
|
||||
List<TypeParameterDescriptor> parameters = context.getConstructor().getParameters();
|
||||
List<TypeProjection> arguments = context.getArguments();
|
||||
|
||||
if (parameters.size() != arguments.size()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
for (int i = 0; i < arguments.size(); i++) {
|
||||
TypeProjection argument = arguments.get(i);
|
||||
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package org.jetbrains.jet.lang.types.checker;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class JetTypeChecker {
|
||||
|
||||
public static final JetTypeChecker INSTANCE = new JetTypeChecker();
|
||||
public static final HashBiMap<TypeConstructor, TypeConstructor> EMPTY_AXIOMS = HashBiMap.create();
|
||||
|
||||
private JetTypeChecker() {
|
||||
}
|
||||
|
||||
public boolean isSubtypeOf(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
// return new TypeCheckingProcedure().run(subtype, supertype);
|
||||
return TYPE_CHECKER.isSubtypeOf(subtype, supertype);
|
||||
}
|
||||
|
||||
public boolean equalTypes(@NotNull JetType a, @NotNull JetType b) {
|
||||
return TYPE_CHECKER.equalTypes(a, b);
|
||||
}
|
||||
|
||||
public boolean equalTypes(@NotNull JetType a, @NotNull JetType b, @NotNull final BiMap<TypeConstructor, TypeConstructor> equalityAxioms) {
|
||||
return new TypeCheckingProcedure(new TypeCheckerTypingConstraints() {
|
||||
@Override
|
||||
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor constructor1, @NotNull TypeConstructor constructor2) {
|
||||
if (!constructor1.equals(constructor2)) {
|
||||
TypeConstructor img1 = equalityAxioms.get(constructor1);
|
||||
TypeConstructor img2 = equalityAxioms.get(constructor2);
|
||||
if (!(img1 != null && img1.equals(constructor2)) &&
|
||||
!(img2 != null && img2.equals(constructor1))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}).equalTypes(a, b);
|
||||
}
|
||||
|
||||
private static final TypeCheckingProcedure TYPE_CHECKER = new TypeCheckingProcedure(new TypeCheckerTypingConstraints());
|
||||
|
||||
private static class TypeCheckerTypingConstraints implements TypingConstraints {
|
||||
@Override
|
||||
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
|
||||
return typeCheckingProcedure.equalTypes(a, b);
|
||||
// return TypeUtils.equalTypes(a, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
|
||||
return a.equals(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
|
||||
return typeCheckingProcedure.isSubtypeOf(subtype, supertype);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
return false; // type checking fails
|
||||
}
|
||||
}
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
package org.jetbrains.jet.lang.types.checker;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.types.Variance.*;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TypeCheckingProcedure {
|
||||
|
||||
// This method returns the supertype of the first parameter that has the same constructor
|
||||
// as the second parameter, applying the substitution of type arguments to it
|
||||
@Nullable
|
||||
private static JetType findCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
TypeConstructor constructor = subtype.getConstructor();
|
||||
if (constructor.equals(supertype.getConstructor())) {
|
||||
return subtype;
|
||||
}
|
||||
for (JetType immediateSupertype : constructor.getSupertypes()) {
|
||||
JetType correspondingSupertype = findCorrespondingSupertype(immediateSupertype, supertype);
|
||||
if (correspondingSupertype != null) {
|
||||
return TypeSubstitutor.create(subtype).safeSubstitute(correspondingSupertype, Variance.INVARIANT);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static JetType getOutType(TypeParameterDescriptor parameter, TypeProjection argument) {
|
||||
boolean isOutProjected = argument.getProjectionKind() == IN_VARIANCE || parameter.getVariance() == IN_VARIANCE;
|
||||
return isOutProjected ? parameter.getUpperBoundsAsType() : argument.getType();
|
||||
}
|
||||
|
||||
private static JetType getInType(TypeParameterDescriptor parameter, TypeProjection argument) {
|
||||
boolean isOutProjected = argument.getProjectionKind() == OUT_VARIANCE || parameter.getVariance() == OUT_VARIANCE;
|
||||
return isOutProjected ? JetStandardClasses.getNothingType() : argument.getType();
|
||||
}
|
||||
|
||||
private final TypingConstraints constraints;
|
||||
|
||||
public TypeCheckingProcedure(TypingConstraints constraints) {
|
||||
this.constraints = constraints;
|
||||
}
|
||||
|
||||
public boolean equalTypes(@NotNull JetType type1, @NotNull JetType type2) {
|
||||
if (type1.isNullable() != type2.isNullable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type1.isNullable()) {
|
||||
// Then type2 is nullable, too (see the previous condition
|
||||
return constraints.assertEqualTypes(TypeUtils.makeNotNullable(type1), TypeUtils.makeNotNullable(type2), this);
|
||||
}
|
||||
|
||||
TypeConstructor constructor1 = type1.getConstructor();
|
||||
TypeConstructor constructor2 = type2.getConstructor();
|
||||
|
||||
if (!constraints.assertEqualTypeConstructors(constructor1, constructor2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<TypeProjection> type1Arguments = type1.getArguments();
|
||||
List<TypeProjection> type2Arguments = type2.getArguments();
|
||||
if (type1Arguments.size() != type2Arguments.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < type1Arguments.size(); i++) {
|
||||
TypeProjection typeProjection1 = type1Arguments.get(i);
|
||||
TypeProjection typeProjection2 = type2Arguments.get(i);
|
||||
if (typeProjection1.getProjectionKind() != typeProjection2.getProjectionKind()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!constraints.assertEqualTypes(typeProjection1.getType(), typeProjection2.getType(), this)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isSubtypeOf(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
if (ErrorUtils.isErrorType(subtype) || ErrorUtils.isErrorType(supertype)) {
|
||||
return true;
|
||||
}
|
||||
if (!supertype.isNullable() && subtype.isNullable()) {
|
||||
return false;
|
||||
}
|
||||
subtype = TypeUtils.makeNotNullable(subtype);
|
||||
supertype = TypeUtils.makeNotNullable(supertype);
|
||||
if (JetStandardClasses.isNothingOrNullableNothing(subtype)) {
|
||||
return true;
|
||||
}
|
||||
@Nullable JetType closestSupertype = findCorrespondingSupertype(subtype, supertype);
|
||||
if (closestSupertype == null) {
|
||||
return constraints.noCorrespondingSupertype(subtype, supertype); // if this returns true, there still isn't any supertype to continue with
|
||||
}
|
||||
|
||||
return checkSubtypeForTheSameConstructor(closestSupertype, supertype);
|
||||
}
|
||||
|
||||
private boolean checkSubtypeForTheSameConstructor(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
TypeConstructor constructor = subtype.getConstructor();
|
||||
assert constructor.equals(supertype.getConstructor()) : constructor + " is not " + supertype.getConstructor();
|
||||
|
||||
List<TypeProjection> subArguments = subtype.getArguments();
|
||||
List<TypeProjection> superArguments = supertype.getArguments();
|
||||
List<TypeParameterDescriptor> parameters = constructor.getParameters();
|
||||
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
||||
TypeParameterDescriptor parameter = parameters.get(i);
|
||||
|
||||
|
||||
TypeProjection subArgument = subArguments.get(i);
|
||||
JetType subIn = getInType(parameter, subArgument);
|
||||
JetType subOut = getOutType(parameter, subArgument);
|
||||
|
||||
TypeProjection superArgument = superArguments.get(i);
|
||||
JetType superIn = getInType(parameter, superArgument);
|
||||
JetType superOut = getOutType(parameter, superArgument);
|
||||
|
||||
if (parameter.getVariance() == INVARIANT && subArgument.getProjectionKind() == INVARIANT && superArgument.getProjectionKind() == INVARIANT) {
|
||||
if (!constraints.assertEqualTypes(subArgument.getType(), superArgument.getType(), this)) return false;
|
||||
}
|
||||
else {
|
||||
if (!constraints.assertSubtype(subOut, superOut, this)) return false;
|
||||
if (!constraints.assertSubtype(superIn, subIn, this)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.jetbrains.jet.lang.types.checker;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeConstructor;
|
||||
|
||||
/**
|
||||
* Methods of this class return true to continue type checking and false to fail
|
||||
*/
|
||||
public interface TypingConstraints {
|
||||
boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure);
|
||||
|
||||
boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b);
|
||||
|
||||
boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure);
|
||||
|
||||
boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype);
|
||||
}
|
||||
+54
-24
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.*;
|
||||
@@ -248,7 +249,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (typeChecker.isSubtypeOf(actualType, targetType)) {
|
||||
context.trace.report(USELESS_CAST.on(expression, expression.getOperationSign()));
|
||||
} else {
|
||||
if (isCastErased(actualType, targetType)) {
|
||||
if (isCastErased(actualType, targetType, typeChecker)) {
|
||||
context.trace.report(Errors.UNCHECKED_CAST.on(expression, actualType, targetType));
|
||||
}
|
||||
}
|
||||
@@ -259,46 +260,75 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
* 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) {
|
||||
public static boolean isCastErased(JetType actualType, JetType targetType, JetTypeChecker typeChecker) {
|
||||
|
||||
if (!(targetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) {
|
||||
// TODO: what if it is TypeParameterDescriptor?
|
||||
return false;
|
||||
}
|
||||
|
||||
JetType targetTypeClerared = TypeUtils.makeUnsubstitutedType(
|
||||
(ClassDescriptor) targetType.getConstructor().getDeclarationDescriptor(), null);
|
||||
// do not crash on error types
|
||||
if (ErrorUtils.isErrorType(actualType) || ErrorUtils.isErrorType(targetType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Multimap<TypeConstructor, TypeProjection> clearTypeSubstitutionMap =
|
||||
TypeUtils.buildDeepSubstitutionMultimap(targetTypeClerared);
|
||||
{
|
||||
Multimap<TypeConstructor, TypeProjection> typeSubstitutionMap =
|
||||
TypeUtils.buildDeepSubstitutionMultimap(targetType);
|
||||
|
||||
Set<JetType> clearSubstituted = new HashSet<JetType>();
|
||||
for (int i = 0; i < actualType.getConstructor().getParameters().size(); ++i) {
|
||||
TypeProjection actualTypeParameter = actualType.getArguments().get(i);
|
||||
TypeParameterDescriptor subjectTypeParameterDescriptor = actualType.getConstructor().getParameters().get(i);
|
||||
|
||||
for (int i = 0; i < actualType.getConstructor().getParameters().size(); ++i) {
|
||||
TypeParameterDescriptor subjectTypeParameterDescriptor = actualType.getConstructor().getParameters().get(i);
|
||||
if (subjectTypeParameterDescriptor.isReified()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Collection<TypeProjection> subst = clearTypeSubstitutionMap.get(subjectTypeParameterDescriptor.getTypeConstructor());
|
||||
for (TypeProjection proj : subst) {
|
||||
clearSubstituted.add(proj.getType());
|
||||
Collection<TypeProjection> subst = typeSubstitutionMap.get(subjectTypeParameterDescriptor.getTypeConstructor());
|
||||
for (TypeProjection proj : subst) {
|
||||
//if (!proj.getType().equals(actualTypeParameter.getType())) {
|
||||
if (!typeChecker.isSubtypeOf(actualTypeParameter.getType(), proj.getType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < targetType.getConstructor().getParameters().size(); ++i) {
|
||||
TypeParameterDescriptor typeParameter = targetType.getConstructor().getParameters().get(i);
|
||||
TypeProjection typeProjection = targetType.getArguments().get(i);
|
||||
{
|
||||
JetType targetTypeClerared = TypeUtils.makeUnsubstitutedType(
|
||||
(ClassDescriptor) targetType.getConstructor().getDeclarationDescriptor(), null);
|
||||
|
||||
if (typeParameter.isReified()) {
|
||||
continue;
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
// "is List<*>"
|
||||
if (typeProjection.equals(TypeUtils.makeStarProjection(typeParameter))) {
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < targetType.getConstructor().getParameters().size(); ++i) {
|
||||
TypeParameterDescriptor typeParameter = targetType.getConstructor().getParameters().get(i);
|
||||
TypeProjection typeProjection = targetType.getArguments().get(i);
|
||||
|
||||
// if parameter is mapped to nothing then it is erased
|
||||
if (!clearSubstituted.contains(typeParameter.getDefaultType())) {
|
||||
return true;
|
||||
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;
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
|
||||
+1
-1
@@ -246,7 +246,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
return;
|
||||
}
|
||||
|
||||
if (BasicExpressionTypingVisitor.isCastErased(subjectType, type)) {
|
||||
if (BasicExpressionTypingVisitor.isCastErased(subjectType, type, context.semanticServices.getTypeChecker())) {
|
||||
context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(reportErrorOn, type));
|
||||
}
|
||||
}
|
||||
|
||||
+38
-14
@@ -7,6 +7,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure;
|
||||
import org.jetbrains.jet.lang.types.checker.TypingConstraints;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -196,7 +199,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
||||
|
||||
}
|
||||
|
||||
private static class KnownType extends TypeValue {
|
||||
private class KnownType extends TypeValue {
|
||||
|
||||
private final JetType type;
|
||||
|
||||
@@ -223,7 +226,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
||||
public boolean equate(TypeValue other) {
|
||||
if (other instanceof KnownType) {
|
||||
KnownType knownType = (KnownType) other;
|
||||
return TypeUtils.equalTypes(type, knownType.getType());
|
||||
return constraintExpander.equalTypes(type, knownType.getType());
|
||||
}
|
||||
return other.equate(this);
|
||||
}
|
||||
@@ -233,16 +236,16 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
||||
private final Map<TypeParameterDescriptor, UnknownType> unknownTypes = Maps.newHashMap();
|
||||
private final JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
|
||||
|
||||
private static final class TypeConstraintBuilderAdapter implements JetTypeChecker.TypingConstraintBuilder {
|
||||
private final JetTypeChecker.TypingConstraintBuilder delegate;
|
||||
private static final class TypeConstraintBuilderAdapter implements TypingConstraints {
|
||||
private final TypingConstraints delegate;
|
||||
|
||||
private TypeConstraintBuilderAdapter(JetTypeChecker.TypingConstraintBuilder delegate) {
|
||||
private TypeConstraintBuilderAdapter(TypingConstraints delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b) {
|
||||
boolean result = delegate.assertEqualTypes(a, b);
|
||||
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
|
||||
boolean result = delegate.assertEqualTypes(a, b, typeCheckingProcedure);
|
||||
if (!result) {
|
||||
println("-- Failed to equate " + a + " and " + b);
|
||||
}
|
||||
@@ -250,8 +253,17 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
boolean result = delegate.assertSubtype(subtype, supertype);
|
||||
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
|
||||
boolean result = delegate.assertEqualTypeConstructors(a, b);
|
||||
if (!result) {
|
||||
println("-- Type constructors are not equal: " + a + " and " + b);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
|
||||
boolean result = delegate.assertSubtype(subtype, supertype, typeCheckingProcedure);
|
||||
if (!result) {
|
||||
println("-- " + subtype + " can't be a subtype of " + supertype);
|
||||
}
|
||||
@@ -268,9 +280,9 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
||||
}
|
||||
}
|
||||
|
||||
private final JetTypeChecker.TypeCheckingProcedure constraintExpander = new JetTypeChecker.TypeCheckingProcedure(new TypeConstraintBuilderAdapter(new JetTypeChecker.TypingConstraintBuilder() {
|
||||
private final TypeCheckingProcedure constraintExpander = new TypeCheckingProcedure(new TypeConstraintBuilderAdapter(new TypingConstraints() {
|
||||
@Override
|
||||
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b) {
|
||||
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
|
||||
TypeValue aValue = getTypeValueFor(a);
|
||||
TypeValue bValue = getTypeValueFor(b);
|
||||
|
||||
@@ -278,7 +290,14 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
|
||||
return a.equals(b)
|
||||
|| unknownTypes.containsKey(a.getDeclarationDescriptor())
|
||||
|| unknownTypes.containsKey(b.getDeclarationDescriptor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
|
||||
TypeValue subtypeValue = getTypeValueFor(subtype);
|
||||
TypeValue supertypeValue = getTypeValueFor(supertype);
|
||||
|
||||
@@ -305,7 +324,8 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
||||
return subtypeValue instanceof UnknownType || supertypeValue instanceof UnknownType;
|
||||
}
|
||||
|
||||
}));
|
||||
}))
|
||||
;
|
||||
|
||||
public ConstraintSystemImpl() {}
|
||||
|
||||
@@ -377,7 +397,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
||||
for (TypeValue upperBound : typeValue.getUpperBounds()) {
|
||||
if (upperBound instanceof KnownType) {
|
||||
KnownType knownBoundType = (KnownType) upperBound;
|
||||
boolean ok = constraintExpander.run(jetType, knownBoundType.getType());
|
||||
boolean ok = constraintExpander.isSubtypeOf(jetType, knownBoundType.getType());
|
||||
if (!ok) {
|
||||
return new Solution().registerError("Mismatch while expanding constraints");
|
||||
}
|
||||
@@ -426,6 +446,10 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
||||
// TODO : check that all bounds are respected by solutions:
|
||||
// we have set some of them from equality constraints with known types
|
||||
// and thus the bounds may be violated if some of the constraints conflict
|
||||
|
||||
println("====================================");
|
||||
println("");
|
||||
println("");
|
||||
|
||||
return solution;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
// +JDK
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
fun ff<T>(l: Collection<T>) = l is List<T>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// +JDK
|
||||
|
||||
import java.util.List
|
||||
|
||||
fun f(a : List<out Any>) = a is <!CANNOT_CHECK_FOR_ERASED!>List<out Int><!>
|
||||
@@ -4,7 +4,7 @@ fun <T> Array<out T>.safeGet(index : Int) : T? {
|
||||
return if (index < size) this[index] else null
|
||||
}
|
||||
|
||||
val args : Array<String> = Array<String>(1)
|
||||
val args : Array<String> = Array<String>(1, {""})
|
||||
val name : String = <!TYPE_MISMATCH!>args.safeGet<String>(0)<!> // No error, must be type mismatch
|
||||
val name1 : String? = args.safeGet(0)
|
||||
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
class IdUnavailableException() : Exception() {}
|
||||
|
||||
fun <T : Any> T.getJavaClass() : Class<T> {
|
||||
return ((this <!CAST_NEVER_SUCCEEDS!>as<!> Object).getClass()) as Class<T> // Some error here, because of Exception() used above. ?!!!
|
||||
return <!UNCHECKED_CAST!>((this <!CAST_NEVER_SUCCEEDS!>as<!> Object).getClass()) as Class<T><!> // Some error here, because of Exception() used above. ?!!!
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// KT-702 Type inference failed
|
||||
// +JDK
|
||||
fun getJavaClass<T>() : java.lang.Class<T> { return "" <!CAST_NEVER_SUCCEEDS!>as<!> Class<T> }
|
||||
|
||||
public class Throwables() {
|
||||
class object {
|
||||
public fun propagateIfInstanceOf<X : Throwable?>(throwable : Throwable?, declaredType : Class<X?>?) {
|
||||
if (((throwable != null) && declaredType?.isInstance(throwable).sure()))
|
||||
{
|
||||
throw declaredType?.cast(throwable)
|
||||
}
|
||||
}
|
||||
public fun propagateIfPossible(throwable : Throwable?) {
|
||||
propagateIfInstanceOf(throwable, getJavaClass<Error?>) //; Type inference failed: Mismatch while expanding constraints
|
||||
propagateIfInstanceOf(throwable, getJavaClass<RuntimeException?>) // Type inference failed: Mismatch while expanding constraints
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -284,4 +284,21 @@ public class PrimitiveTypesTest extends CodegenTestCase {
|
||||
public void testKt518 () throws Exception {
|
||||
blackBoxFile("regressions/kt518.jet");
|
||||
}
|
||||
|
||||
public void testKt665() throws Exception {
|
||||
loadText("fun f(x: Long, zzz: Long = 1): Long\n" +
|
||||
"{\n" +
|
||||
" return if (x <= 1) zzz\n" +
|
||||
" else f(x-1, x*zzz)\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"fun box() : String\n" +
|
||||
"{\n" +
|
||||
" val six: Long = 6;\n" +
|
||||
" System.out?.println(f(six))\n" +
|
||||
" return \"OK\"" +
|
||||
"}");
|
||||
System.out.println(generateToText());
|
||||
blackBox();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,12 @@ package org.jetbrains.jet.plugin.completion;
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.patterns.PlatformPatterns;
|
||||
import com.intellij.patterns.PsiElementPattern;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.filters.NotFilter;
|
||||
import com.intellij.psi.filters.TextFilter;
|
||||
import com.intellij.psi.filters.position.FilterPattern;
|
||||
import com.intellij.psi.filters.position.LeftNeighbour;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -14,7 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public class JetKeywordCompletionContributor extends CompletionContributor {
|
||||
|
||||
private static class JetKeywordCompletionProvider extends CompletionProvider<CompletionParameters> {
|
||||
private static class JetTopKeywordCompletionProvider extends CompletionProvider<CompletionParameters> {
|
||||
|
||||
private final static String[] COMPLETE_KEYWORD = new String[] {
|
||||
"namespace", "as", "type", "class", "this", "super", "val", "var", "fun", "for", "null", "true",
|
||||
@@ -43,6 +49,12 @@ public class JetKeywordCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
|
||||
public JetKeywordCompletionContributor() {
|
||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement(), new JetKeywordCompletionProvider());
|
||||
|
||||
PsiElementPattern.Capture<PsiElement> notDotPlace =
|
||||
PlatformPatterns.psiElement().and(new FilterPattern(new NotFilter(new LeftNeighbour(new TextFilter(".")))));
|
||||
|
||||
extend(CompletionType.BASIC,
|
||||
notDotPlace,
|
||||
new JetTopKeywordCompletionProvider());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
fun foo() {
|
||||
val str : String
|
||||
str.<caret>
|
||||
}
|
||||
|
||||
// ABSENT: namespace, as, type, class, this, super, val, var, fun, for, null, true
|
||||
// ABSENT: false, is, in, throw, return, break, continue, object, if, try, else, while
|
||||
// ABSENT: do, when, trait, This
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
fun foo() {
|
||||
val str : String
|
||||
str. <caret>
|
||||
}
|
||||
|
||||
// ABSENT: public, val, in
|
||||
Reference in New Issue
Block a user