diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 050bd7da483..a5ef0c787f7 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1307,6 +1307,9 @@ public class ExpressionCodegen extends JetVisitor { else if(type.getSort() == Type.DOUBLE) { v.aconst(0d); } + else if(type.getSort() == Type.LONG) { + v.aconst(0l); + } else { v.iconst(0); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index 21c99a991f5..e1a163ccd5d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -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(); + } } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index 75c951e3fe5..33e107c2143 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -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)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java b/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java index 36fadfc8f60..e05beea88c9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/JetSemanticServices.java @@ -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; /** diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java index d02bbb786af..1edf93c8743 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java index 0e85d64ce6d..c39f0f4ab03 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java @@ -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); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index 0ea7d1e60aa..ccd0c4d9385 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java index 1b50ad703bc..ef3f839a5e5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java @@ -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 superTypeParameters = superDescriptor.getTypeParameters(); List subTypeParameters = subDescriptor.getTypeParameters(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index 49fb12d2294..7ea0b24800c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java index 89989f037c9..661dc9913ea 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantResolver.java index 823a3183238..fc2ec113233 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantResolver.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/SubstitutingScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/SubstitutingScope.java index a45bab80eda..c2e0ffbc177 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/SubstitutingScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/SubstitutingScope.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/CommonSupertypes.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/CommonSupertypes.java index b656e962bd5..7239cb8752b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/CommonSupertypes.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/CommonSupertypes.java @@ -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.*; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeChecker.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeChecker.java deleted file mode 100644 index d06f37c4841..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeChecker.java +++ /dev/null @@ -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 subArguments = subtype.getArguments(); - List superArguments = supertype.getArguments(); - List 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 { -// -// 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 subArguments = subtype.getArguments(); -// List superArguments = supertype.getArguments(); -// List 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 { -// -// 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; -// } -// } - - -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeImpl.java index 69be07784c9..4e1fd0d08cd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeImpl.java @@ -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 EMPTY_AXIOMS = HashBiMap.create(); - private final TypeConstructor constructor; private final List 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 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 type1Arguments = type1.getArguments(); - List 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; - } - } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java index dac071017cd..e0e2a35b24d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java index 82e4416c056..2e3b5f83ede 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -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 substitution, @Nullable Multimap fullSubstitution) { List parameters = context.getConstructor().getParameters(); List 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); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/JetTypeChecker.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/JetTypeChecker.java new file mode 100644 index 00000000000..7147158c66c --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/JetTypeChecker.java @@ -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 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 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 + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java new file mode 100644 index 00000000000..4d3a96bb62c --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java @@ -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 type1Arguments = type1.getArguments(); + List 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 subArguments = subtype.getArguments(); + List superArguments = supertype.getArguments(); + List 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; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/TypingConstraints.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/TypingConstraints.java new file mode 100644 index 00000000000..0276f816184 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/TypingConstraints.java @@ -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); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 1e95b4414b6..09ef1b6e574 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -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 clearTypeSubstitutionMap = - TypeUtils.buildDeepSubstitutionMultimap(targetTypeClerared); + { + Multimap typeSubstitutionMap = + TypeUtils.buildDeepSubstitutionMultimap(targetType); - Set clearSubstituted = new HashSet(); + 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 subst = clearTypeSubstitutionMap.get(subjectTypeParameterDescriptor.getTypeConstructor()); - for (TypeProjection proj : subst) { - clearSubstituted.add(proj.getType()); + Collection 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 clearTypeSubstitutionMap = + TypeUtils.buildDeepSubstitutionMultimap(targetTypeClerared); + + Set clearSubstituted = new HashSet(); + + for (int i = 0; i < actualType.getConstructor().getParameters().size(); ++i) { + TypeParameterDescriptor subjectTypeParameterDescriptor = actualType.getConstructor().getParameters().get(i); + + Collection 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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java index f7980849808..9d1fcc2974e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java index f5c277970bb..eba525b41f7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java @@ -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)); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java index ed5e49d499c..f5baf6d6e77 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java @@ -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 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; } diff --git a/compiler/testData/diagnostics/tests/cast/IsErasedAllow.jet b/compiler/testData/diagnostics/tests/cast/IsErasedAllowSameClassParameter.jet similarity index 100% rename from compiler/testData/diagnostics/tests/cast/IsErasedAllow.jet rename to compiler/testData/diagnostics/tests/cast/IsErasedAllowSameClassParameter.jet diff --git a/compiler/testData/diagnostics/tests/cast/IsErasedAllowSameParameterParameter.jet b/compiler/testData/diagnostics/tests/cast/IsErasedAllowSameParameterParameter.jet new file mode 100644 index 00000000000..6d6e453858b --- /dev/null +++ b/compiler/testData/diagnostics/tests/cast/IsErasedAllowSameParameterParameter.jet @@ -0,0 +1,7 @@ +// +JDK + +import java.util.Collection; +import java.util.List; + +fun ff(l: Collection) = l is List + diff --git a/compiler/testData/diagnostics/tests/cast/IsErasedDisallowFromOut.jet b/compiler/testData/diagnostics/tests/cast/IsErasedDisallowFromOut.jet new file mode 100644 index 00000000000..b0cd9a510a0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cast/IsErasedDisallowFromOut.jet @@ -0,0 +1,5 @@ +// +JDK + +import java.util.List + +fun f(a : List) = a is List diff --git a/compiler/testData/diagnostics/tests/regressions/kt312.jet b/compiler/testData/diagnostics/tests/regressions/kt312.jet index 6701b24dbef..89085fbc485 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt312.jet +++ b/compiler/testData/diagnostics/tests/regressions/kt312.jet @@ -4,7 +4,7 @@ fun Array.safeGet(index : Int) : T? { return if (index < size) this[index] else null } -val args : Array = Array(1) +val args : Array = Array(1, {""}) val name : String = args.safeGet(0) // No error, must be type mismatch val name1 : String? = args.safeGet(0) diff --git a/compiler/testData/diagnostics/tests/regressions/kt498.jet b/compiler/testData/diagnostics/tests/regressions/kt498.jet index 91e85567a83..fcb1e8abd61 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt498.jet +++ b/compiler/testData/diagnostics/tests/regressions/kt498.jet @@ -4,5 +4,5 @@ class IdUnavailableException() : Exception() {} fun T.getJavaClass() : Class { - return ((this as Object).getClass()) as Class // Some error here, because of Exception() used above. ?!!! + return ((this as Object).getClass()) as Class // Some error here, because of Exception() used above. ?!!! } diff --git a/compiler/testData/diagnostics/tests/regressions/kt701.jet b/compiler/testData/diagnostics/tests/regressions/kt701.jet new file mode 100644 index 00000000000..cd536d66aa8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/kt701.jet @@ -0,0 +1,18 @@ +// KT-702 Type inference failed +// +JDK +fun getJavaClass() : java.lang.Class { return "" as Class } + +public class Throwables() { + class object { + public fun propagateIfInstanceOf(throwable : Throwable?, declaredType : Class?) { + if (((throwable != null) && declaredType?.isInstance(throwable).sure())) + { + throw declaredType?.cast(throwable) + } + } + public fun propagateIfPossible(throwable : Throwable?) { + propagateIfInstanceOf(throwable, getJavaClass) //; Type inference failed: Mismatch while expanding constraints + propagateIfInstanceOf(throwable, getJavaClass) // Type inference failed: Mismatch while expanding constraints + } + } +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java b/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java index d52a2e3c488..033f9c56b68 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java @@ -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(); + } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java index e4fd1beb534..6f7a57c8492 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java @@ -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 { + private static class JetTopKeywordCompletionProvider extends CompletionProvider { 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 notDotPlace = + PlatformPatterns.psiElement().and(new FilterPattern(new NotFilter(new LeftNeighbour(new TextFilter("."))))); + + extend(CompletionType.BASIC, + notDotPlace, + new JetTopKeywordCompletionProvider()); } } diff --git a/idea/testData/completion/keywords/AfterDot.kt b/idea/testData/completion/keywords/AfterDot.kt new file mode 100644 index 00000000000..f6d11044f90 --- /dev/null +++ b/idea/testData/completion/keywords/AfterDot.kt @@ -0,0 +1,9 @@ +fun foo() { + val str : String + str. +} + +// 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 + diff --git a/idea/testData/completion/keywords/AfterSpaceAndDot.kt b/idea/testData/completion/keywords/AfterSpaceAndDot.kt new file mode 100644 index 00000000000..bd0a7028c99 --- /dev/null +++ b/idea/testData/completion/keywords/AfterSpaceAndDot.kt @@ -0,0 +1,6 @@ +fun foo() { + val str : String + str. +} + +// ABSENT: public, val, in \ No newline at end of file