Merge remote-tracking branch 'origin/master'

This commit is contained in:
svtk
2011-12-08 13:43:56 +04:00
80 changed files with 2197 additions and 498 deletions
@@ -0,0 +1,108 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import java.util.List;
import static org.jetbrains.jet.lang.diagnostics.Errors.UNRESOLVED_REFERENCE;
import static org.jetbrains.jet.lang.diagnostics.Errors.UNSUPPORTED;
/**
* @author abreslav
*/
public class ImportsResolver {
private final TopDownAnalysisContext context;
public ImportsResolver(@NotNull TopDownAnalysisContext context) {
this.context = context;
}
public void processTypeImports() {
for (JetNamespace jetNamespace : context.getNamespaceDescriptors().keySet()) {
processImports(jetNamespace, context.getNamespaceScopes().get(jetNamespace), context.getDeclaringScopes().get(jetNamespace));
}
}
private void processImports(@NotNull JetNamespace namespace, @NotNull WritableScope namespaceScope, @NotNull JetScope outerScope) {
context.getConfiguration().addDefaultImports(context.getTrace(), namespaceScope);
List<JetImportDirective> importDirectives = namespace.getImportDirectives();
for (JetImportDirective importDirective : importDirectives) {
if (importDirective.isAbsoluteInRootNamespace()) {
context.getTrace().report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO
continue;
}
if (importDirective.isAllUnder()) {
JetExpression importedReference = importDirective.getImportedReference();
if (importedReference != null) {
ExpressionTypingServices typeInferrerServices = context.getSemanticServices().getTypeInferrerServices(context.getTrace());
JetType type = typeInferrerServices.getTypeWithNamespaces(namespaceScope, importedReference);
if (type != null) {
namespaceScope.importScope(type.getMemberScope());
}
}
}
else {
ClassifierDescriptor classifierDescriptor = null;
NamespaceDescriptor namespaceDescriptor = null;
JetSimpleNameExpression referenceExpression = null;
JetExpression importedReference = importDirective.getImportedReference();
if (importedReference instanceof JetDotQualifiedExpression) {
JetDotQualifiedExpression reference = (JetDotQualifiedExpression) importedReference;
JetType type = context.getSemanticServices().getTypeInferrerServices(context.getTrace()).getTypeWithNamespaces(namespaceScope, reference.getReceiverExpression());
JetExpression selectorExpression = reference.getSelectorExpression();
if (selectorExpression != null) {
referenceExpression = (JetSimpleNameExpression) selectorExpression;
String referencedName = referenceExpression.getReferencedName();
if (type != null && referencedName != null) {
classifierDescriptor = type.getMemberScope().getClassifier(referencedName);
namespaceDescriptor = type.getMemberScope().getNamespace(referencedName);
}
}
}
else {
assert importedReference instanceof JetSimpleNameExpression;
referenceExpression = (JetSimpleNameExpression) importedReference;
String referencedName = referenceExpression.getReferencedName();
if (referencedName != null) {
classifierDescriptor = outerScope.getClassifier(referencedName);
namespaceDescriptor = outerScope.getNamespace(referencedName);
if (classifierDescriptor == null && namespaceDescriptor == null) {
context.getTrace().report(UNRESOLVED_REFERENCE.on(referenceExpression));
}
}
}
String aliasName = importDirective.getAliasName();
if (aliasName == null) {
aliasName = referenceExpression != null ? referenceExpression.getReferencedName() : null;
}
if (classifierDescriptor != null) {
context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor);
if (aliasName != null) {
namespaceScope.importClassifierAlias(aliasName, classifierDescriptor);
}
}
if (namespaceDescriptor != null) {
if (classifierDescriptor == null) {
context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, namespaceDescriptor);
}
if (aliasName != null) {
namespaceScope.importNamespaceAlias(aliasName, namespaceDescriptor);
}
}
}
}
}
}
@@ -0,0 +1,32 @@
package org.jetbrains.jet.lang.resolve;
import org.objectweb.asm.Type;
/**
* @author Stepan Koltsov
*/
public class StdlibNames {
public static final Type JET_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetParameter");
public static final String JET_PARAMETER_CLASS = "jet.typeinfo.JetParameter";
public static final String JET_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetParameter;";
public static final String JET_PARAMETER_NAME_FIELD = "name";
public static final String JET_PARAMETER_HAS_DEFAULT_FIELD = "hasDefault";
public static final String JET_PARAMETER_NULLABLE_FIELD = "nullable";
public static final Type JET_TYPE_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetTypeParameter");
public static final String JET_TYPE_PARAMETER_CLASS = "jet.typeinfo.JetTypeParameter";
public static final String JET_TYPE_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetTypeParameter;";
public static final String JET_TYPE_PARAMETER_NAME_FIELD = "name";
public static final Type JET_METHOD_TYPE = Type.getObjectType("jet/typeinfo/JetMethod");
public static final String JET_METHOD_CLASS = "jet.typeinfo.JetMethod";
public static final String JET_METHOD_DESCRIPTOR = "Ljet/typeinfo/JetMethod;";
public static final String JET_METHOD_NULLABLE_RETURN_TYPE_FIELD = "nullableReturnType";
}
@@ -15,7 +15,10 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope;
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.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lexer.JetTokens;
@@ -30,17 +33,19 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.*;
*/
public class TypeHierarchyResolver {
private final TopDownAnalysisContext context;
private final ImportsResolver importsResolver;
private LinkedList<MutableClassDescriptor> topologicalOrder;
public TypeHierarchyResolver(TopDownAnalysisContext context) {
this.context = context;
this.importsResolver = new ImportsResolver(context);
}
public void process(@NotNull JetScope outerScope, @NotNull NamespaceLike owner, @NotNull Collection<? extends JetDeclaration> declarations) {
collectNamespacesAndClassifiers(outerScope, outerScope, owner, declarations); // namespaceScopes, classes
processTypeImports();
importsResolver.processTypeImports();
createTypeConstructors(); // create type constructors for classes and generic parameters, supertypes are not filled in
resolveTypesInClassHeaders(); // Generic bounds and types in supertype lists (no expressions or constructor resolution)
@@ -75,7 +80,6 @@ public class TypeHierarchyResolver {
WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(), new TraceBasedRedeclarationHandler(context.getTrace()));
namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH);
context.getConfiguration().addDefaultImports(context.getTrace(), namespaceScope);
context.getNamespaceScopes().put(namespace, namespaceScope);
context.getDeclaringScopes().put(namespace, outerScope);
@@ -233,82 +237,6 @@ public class TypeHierarchyResolver {
return ClassKind.CLASS;
}
private void processTypeImports() {
for (JetNamespace jetNamespace : context.getNamespaceDescriptors().keySet()) {
processImports(jetNamespace, context.getNamespaceScopes().get(jetNamespace), context.getDeclaringScopes().get(jetNamespace));
}
}
private void processImports(@NotNull JetNamespace namespace, @NotNull WritableScope namespaceScope, @NotNull JetScope outerScope) {
List<JetImportDirective> importDirectives = namespace.getImportDirectives();
for (JetImportDirective importDirective : importDirectives) {
if (importDirective.isAbsoluteInRootNamespace()) {
context.getTrace().report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO
continue;
}
if (importDirective.isAllUnder()) {
JetExpression importedReference = importDirective.getImportedReference();
if (importedReference != null) {
ExpressionTypingServices typeInferrerServices = context.getSemanticServices().getTypeInferrerServices(context.getTrace());
JetType type = typeInferrerServices.getTypeWithNamespaces(namespaceScope, importedReference);
if (type != null) {
namespaceScope.importScope(type.getMemberScope());
}
}
}
else {
ClassifierDescriptor classifierDescriptor = null;
NamespaceDescriptor namespaceDescriptor = null;
JetSimpleNameExpression referenceExpression = null;
JetExpression importedReference = importDirective.getImportedReference();
if (importedReference instanceof JetDotQualifiedExpression) {
JetDotQualifiedExpression reference = (JetDotQualifiedExpression) importedReference;
JetType type = context.getSemanticServices().getTypeInferrerServices(context.getTrace()).getTypeWithNamespaces(namespaceScope, reference.getReceiverExpression());
JetExpression selectorExpression = reference.getSelectorExpression();
if (selectorExpression != null) {
referenceExpression = (JetSimpleNameExpression) selectorExpression;
String referencedName = referenceExpression.getReferencedName();
if (type != null && referencedName != null) {
classifierDescriptor = type.getMemberScope().getClassifier(referencedName);
namespaceDescriptor = type.getMemberScope().getNamespace(referencedName);
}
}
}
else {
assert importedReference instanceof JetSimpleNameExpression;
referenceExpression = (JetSimpleNameExpression) importedReference;
String referencedName = referenceExpression.getReferencedName();
if (referencedName != null) {
classifierDescriptor = outerScope.getClassifier(referencedName);
namespaceDescriptor = outerScope.getNamespace(referencedName);
}
}
String aliasName = importDirective.getAliasName();
if (aliasName == null) {
aliasName = referenceExpression != null ? referenceExpression.getReferencedName() : null;
}
if (classifierDescriptor != null) {
context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor);
if (aliasName != null) {
namespaceScope.importClassifierAlias(aliasName, classifierDescriptor);
}
}
if (namespaceDescriptor != null) {
if (classifierDescriptor == null) {
context.getTrace().record(BindingContext.REFERENCE_TARGET, referenceExpression, namespaceDescriptor);
}
if (aliasName != null) {
namespaceScope.importNamespaceAlias(aliasName, namespaceDescriptor);
}
}
}
}
}
private void createTypeConstructors() {
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
JetClass jetClass = entry.getKey();
@@ -13,16 +13,13 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.inference.*;
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.*;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
import org.jetbrains.jet.lang.resolve.calls.inference.SolutionStatus;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.*;
@@ -241,6 +238,12 @@ public class CallResolver {
@NotNull JetType expectedType,
@NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority
@NotNull final JetReferenceExpression reference) {
ResolutionDebugInfo.Data debugInfo = ResolutionDebugInfo.create();
trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, call.getCallElement(), debugInfo);
debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);
TracingStrategy tracing = new TracingStrategy() {
@Override
public <D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCallImpl<D> resolvedCall) {
@@ -371,6 +374,9 @@ public class CallResolver {
OverloadResolutionResults<D> results = performResolution(temporaryTrace, scope, expectedType, task, tracing);
if (results.isSuccess()) {
temporaryTrace.commit();
debugInfo.set(ResolutionDebugInfo.RESULT, results.getResult());
return results.getResult();
}
if (traceForFirstNonemptyCandidateSet == null && !task.getCandidates().isEmpty()) {
@@ -381,6 +387,9 @@ public class CallResolver {
if (traceForFirstNonemptyCandidateSet != null) {
traceForFirstNonemptyCandidateSet.commit();
if (resultsForFirstNonemptyCandidateSet.singleDescriptor()) {
debugInfo.set(ResolutionDebugInfo.RESULT, resultsForFirstNonemptyCandidateSet.getResult());
return resultsForFirstNonemptyCandidateSet.getResult();
}
}
@@ -420,7 +429,10 @@ public class CallResolver {
if (!candidate.getTypeParameters().isEmpty()) {
// Type argument inference
ConstraintSystem constraintSystem = new ConstraintSystemImpl();
ResolutionDebugInfo.Data debugInfo = trace.get(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, task.getCall().getCallElement());
ConstraintSystem constraintSystem = new ConstraintSystemImpl(new DebugConstraintResolutionListener(debugInfo));
for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) {
constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO
}
@@ -0,0 +1,115 @@
package org.jetbrains.jet.lang.resolve.calls;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.util.slicedmap.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
*/
public class ResolutionDebugInfo {
public static final WritableSlice<One, List<? extends ResolutionTask<? extends CallableDescriptor>>> TASKS = Slices.createSimpleSlice();
public static final WritableSlice<One, ResolvedCall<? extends CallableDescriptor>> RESULT = Slices.createSimpleSlice();
public static final WritableSlice<One, StringBuilder> ERRORS = Slices.createSimpleSlice();
public static final WritableSlice<One, StringBuilder> LOG = Slices.createSimpleSlice();
public static final WritableSlice<One, Map<TypeParameterDescriptor, ConstraintSystemImpl.TypeValue>> BOUNDS_FOR_UNKNOWNS = Slices.createSimpleSlice();
public static final WritableSlice<One, Map<JetType, ConstraintSystemImpl.TypeValue>> BOUNDS_FOR_KNOWNS = Slices.createSimpleSlice();
public static final WritableSlice<One, ConstraintSystemSolution> SOLUTION = Slices.createSimpleSlice();
public static final WritableSlice<One, Collection<TypeParameterDescriptor>> UNKNOWNS = Slices.createSimpleSlice();
static {
BasicWritableSlice.initSliceDebugNames(ResolutionDebugInfo.class);
}
public static boolean RESOLUTION_DEBUG_INFO_ENABLED = false;
public static boolean isResolutionDebugEnabled() {
Application application = ApplicationManager.getApplication();
return (RESOLUTION_DEBUG_INFO_ENABLED || application.isInternal()) && !application.isUnitTestMode();
}
public static final Data NO_DEBUG_INFO = new AbstractData() {
@Override
public String toString() {
return "NO_DEBUG_INFO";
}
@Override
public <K, V> V getByKey(ReadOnlySlice<K, V> slice, K key) {
return SlicedMap.DO_NOTHING.get(slice, key);
}
@Override
public <K, V> void putByKey(WritableSlice<K, V> slice, K key, V value) {
}
};
public static final WritableSlice<PsiElement, Data> RESOLUTION_DEBUG_INFO = new BasicWritableSlice<PsiElement, Data>(Slices.ONLY_REWRITE_TO_EQUAL) {
@Override
public boolean check(PsiElement key, Data value) {
return isResolutionDebugEnabled();
}
@Override
public Data computeValue(SlicedMap map, PsiElement key, Data value, boolean valueNotFound) {
if (valueNotFound) return NO_DEBUG_INFO;
return super.computeValue(map, key, value, valueNotFound);
}
};
public static Data create() {
return isResolutionDebugEnabled() ? new DataImpl() : NO_DEBUG_INFO;
}
public enum One { KEY }
public interface Data {
<K, V> V getByKey(ReadOnlySlice<K, V> slice, K key);
<K, V> void putByKey(WritableSlice<K, V> slice, K key, V value);
<V> void set(WritableSlice<One, ? super V> slice, V value);
<V> V get(ReadOnlySlice<One, V> slice);
}
private static abstract class AbstractData implements Data {
@Override
public <V> void set(WritableSlice<One, ? super V> slice, V value) {
putByKey(slice, One.KEY, value);
}
@Override
public <V> V get(ReadOnlySlice<One, V> slice) {
return getByKey(slice, One.KEY);
}
}
private static class DataImpl extends AbstractData {
private final MutableSlicedMap map = SlicedMapImpl.create();
@Override
public <K, V> V getByKey(ReadOnlySlice<K, V> slice, K key) {
return map.get(slice, key);
}
@Override
public <K, V> void putByKey(WritableSlice<K, V> slice, K key, V value) {
map.put(slice, key, value);
}
}
public static void println(Object message) {
if (isResolutionDebugEnabled()) {
System.out.println(message);
}
}
}
@@ -0,0 +1,19 @@
package org.jetbrains.jet.lang.resolve.calls.inference;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Set;
/**
* @author abreslav
*/
public interface ConstraintResolutionListener {
void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue);
void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue);
void done(ConstraintSystemSolution solution, Set<TypeParameterDescriptor> typeParameterDescriptors);
void log(Object message);
void error(Object message);
}
@@ -44,7 +44,6 @@ public class ConstraintSystemImpl implements ConstraintSystem {
});
}
private static class LoopInTypeVariableConstraintsException extends RuntimeException {
public LoopInTypeVariableConstraintsException() {}
}
@@ -80,6 +79,8 @@ public class ConstraintSystemImpl implements ConstraintSystem {
public abstract boolean equate(TypeValue other);
}
//==========================================================================================================================================================
private class UnknownType extends TypeValue {
private final TypeParameterDescriptor typeParameterDescriptor;
@@ -142,7 +143,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
}
println("minimal solution from lowerbounds for " + this + " is " + commonSupertype);
listener.log("minimal solution from lowerbounds for " + this + " is " + commonSupertype);
value = new KnownType(commonSupertype);
}
else {
@@ -238,16 +239,18 @@ public class ConstraintSystemImpl implements ConstraintSystem {
private static final class TypeConstraintBuilderAdapter implements TypingConstraints {
private final TypingConstraints delegate;
private final ConstraintResolutionListener listener;
private TypeConstraintBuilderAdapter(TypingConstraints delegate) {
private TypeConstraintBuilderAdapter(TypingConstraints delegate, ConstraintResolutionListener listener) {
this.delegate = delegate;
this.listener = listener;
}
@Override
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);
listener.error("-- Failed to equate " + a + " and " + b);
}
return result;
}
@@ -256,7 +259,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
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);
listener.error("-- Type constructors are not equal: " + a + " and " + b);
}
return result;
}
@@ -265,7 +268,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
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);
listener.error("-- " + subtype + " can't be a subtype of " + supertype);
}
return result;
}
@@ -274,60 +277,67 @@ public class ConstraintSystemImpl implements ConstraintSystem {
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
boolean result = delegate.noCorrespondingSupertype(subtype, supertype);
if (!result) {
println("-- " + subtype + " has no supertype corresponding to " + supertype);
listener.error("-- " + subtype + " has no supertype corresponding to " + supertype);
}
return result;
}
}
private final TypeCheckingProcedure constraintExpander = new TypeCheckingProcedure(new TypeConstraintBuilderAdapter(new TypingConstraints() {
@Override
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
TypeValue aValue = getTypeValueFor(a);
TypeValue bValue = getTypeValueFor(b);
return aValue.equate(bValue);
}
private final TypeCheckingProcedure constraintExpander;
private final ConstraintResolutionListener listener;
@Override
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
return a.equals(b)
|| unknownTypes.containsKey(a.getDeclarationDescriptor())
|| unknownTypes.containsKey(b.getDeclarationDescriptor());
}
public ConstraintSystemImpl(ConstraintResolutionListener listener) {
this.listener = listener;
this.constraintExpander = createConstraintExpander();
}
@Override
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
TypeValue subtypeValue = getTypeValueFor(subtype);
TypeValue supertypeValue = getTypeValueFor(supertype);
private TypeCheckingProcedure createConstraintExpander() {
return new TypeCheckingProcedure(new TypeConstraintBuilderAdapter(new TypingConstraints() {
@Override
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
TypeValue aValue = getTypeValueFor(a);
TypeValue bValue = getTypeValueFor(b);
if (someUnknown(subtypeValue, supertypeValue)) {
addSubtypingConstraintOnTypeValues(subtypeValue, supertypeValue);
return aValue.equate(bValue);
}
return true;
}
@Override
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
// If some of the types is an unknown, the constraint must be generated, and we should carry on
// otherwise there can be no solution, and we should fail
TypeValue subTypeValue = getTypeValueFor(subtype);
TypeValue superTypeValue = getTypeValueFor(supertype);
boolean someUnknown = someUnknown(subTypeValue, superTypeValue);
if (someUnknown) {
addSubtypingConstraintOnTypeValues(subTypeValue, superTypeValue);
@Override
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
return a.equals(b)
|| unknownTypes.containsKey(a.getDeclarationDescriptor())
|| unknownTypes.containsKey(b.getDeclarationDescriptor());
}
return someUnknown;
}
private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) {
return subtypeValue instanceof UnknownType || supertypeValue instanceof UnknownType;
}
@Override
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
TypeValue subtypeValue = getTypeValueFor(subtype);
TypeValue supertypeValue = getTypeValueFor(supertype);
}))
;
if (someUnknown(subtypeValue, supertypeValue)) {
addSubtypingConstraintOnTypeValues(subtypeValue, supertypeValue);
}
return true;
}
public ConstraintSystemImpl() {}
@Override
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
// If some of the types is an unknown, the constraint must be generated, and we should carry on
// otherwise there can be no solution, and we should fail
TypeValue subTypeValue = getTypeValueFor(subtype);
TypeValue superTypeValue = getTypeValueFor(supertype);
boolean someUnknown = someUnknown(subTypeValue, superTypeValue);
if (someUnknown) {
addSubtypingConstraintOnTypeValues(subTypeValue, superTypeValue);
}
return someUnknown;
}
private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) {
return subtypeValue instanceof UnknownType || supertypeValue instanceof UnknownType;
}
}, listener));
}
@NotNull
private TypeValue getTypeValueFor(@NotNull JetType type) {
@@ -368,7 +378,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
private void mergeUnknowns(@NotNull UnknownType a, @NotNull UnknownType b) {
System.err.println("!!!mergeUnknowns() is not implemented!!!");
listener.error("!!!mergeUnknowns() is not implemented!!!");
}
@Override
@@ -379,7 +389,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
private void addSubtypingConstraintOnTypeValues(TypeValue typeValueForLower, TypeValue typeValueForUpper) {
println(typeValueForLower + " :< " + typeValueForUpper);
listener.log("Constraint added: " + typeValueForLower + " :< " + typeValueForUpper);
if (typeValueForLower != typeValueForUpper) {
typeValueForLower.addUpperBound(typeValueForUpper);
typeValueForUpper.addLowerBound(typeValueForLower);
@@ -424,13 +434,11 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
for (UnknownType unknownType : unknownTypes.values()) {
println("Constraints for " + unknownType.getTypeParameterDescriptor());
printTypeValue(unknownType);
listener.constraintsForUnknown(unknownType.getTypeParameterDescriptor(), unknownType);
}
for (KnownType knownType : knownTypes.values()) {
println("Constraints for " + knownType.getType());
printTypeValue(knownType);
listener.constraintsForKnownType(knownType.getType(), knownType);
}
// Find inconsistencies
@@ -447,22 +455,11 @@ public class ConstraintSystemImpl implements ConstraintSystem {
// 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("");
listener.done(solution, unknownTypes.keySet());
return solution;
}
private void printTypeValue(TypeValue typeValue) {
for (TypeValue bound : typeValue.getUpperBounds()) {
println(" :< " + bound);
}
for (TypeValue bound : typeValue.getLowerBounds()) {
println(" :> " + bound);
}
}
private void check(TypeValue typeValue, Solution solution) {
try {
KnownType resultingValue = typeValue.getValue();
@@ -471,33 +468,20 @@ public class ConstraintSystemImpl implements ConstraintSystem {
JetType boundingType = solution.getSubstitutor().substitute(upperBound.getValue().getType(), Variance.INVARIANT);
if (!typeChecker.isSubtypeOf(type, boundingType)) { // TODO
solution.registerError("Constraint violation: " + type + " is not a subtype of " + boundingType);
println("Constraint violation: " + type + " :< " + boundingType);
listener.error("Constraint violation: " + type + " :< " + boundingType);
}
}
for (TypeValue lowerBound : typeValue.getLowerBounds()) {
JetType boundingType = solution.getSubstitutor().substitute(lowerBound.getValue().getType(), Variance.INVARIANT);
if (!typeChecker.isSubtypeOf(boundingType, type)) {
solution.registerError("Constraint violation: " + boundingType + " is not a subtype of " + type);
println("Constraint violation: " + boundingType + " :< " + type);
listener.error("Constraint violation: " + boundingType + " :< " + type);
}
}
}
catch (LoopInTypeVariableConstraintsException e) {
println("-------------------------------------------------------------------");
for (Map.Entry<TypeParameterDescriptor, UnknownType> entry : unknownTypes.entrySet()) {
println("Unknown: " + entry.getKey());
UnknownType unknownType = entry.getValue();
println("Lower bounds: ");
for (TypeValue lowerBound : unknownType.getLowerBounds()) {
println(" " + lowerBound);
}
println("Upper bounds: ");
for (TypeValue lowerBound : unknownType.getUpperBounds()) {
println(" " + lowerBound);
}
}
listener.error("Loop detected");
solution.registerError("[TODO] Loop in constraints");
// e.printStackTrace();
}
}
@@ -544,9 +528,14 @@ public class ConstraintSystemImpl implements ConstraintSystem {
DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor();
if (declarationDescriptor instanceof TypeParameterDescriptor) {
TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor;
if (!unknownTypes.containsKey(descriptor)) return null;
println(descriptor + " |-> " + getValue(descriptor));
return new TypeProjection(getValue(descriptor));
TypeProjection typeProjection = new TypeProjection(getValue(descriptor));
listener.log(descriptor + " |-> " + typeProjection);
return typeProjection;
}
return null;
}
@@ -588,7 +577,4 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
private static void println(String message) {
// System.out.println(message);
}
}
@@ -0,0 +1,75 @@
package org.jetbrains.jet.lang.resolve.calls.inference;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Map;
import java.util.Set;
import static org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo.*;
/**
* @author abreslav
*/
public class DebugConstraintResolutionListener implements ConstraintResolutionListener {
private final ResolutionDebugInfo.Data debugInfo;
public DebugConstraintResolutionListener(@NotNull ResolutionDebugInfo.Data debugInfo) {
this.debugInfo = debugInfo;
}
@Override
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue) {
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
Map<TypeParameterDescriptor, ConstraintSystemImpl.TypeValue> map = debugInfo.get(BOUNDS_FOR_UNKNOWNS);
if (map == null) {
map = Maps.newLinkedHashMap();
debugInfo.set(BOUNDS_FOR_UNKNOWNS, map);
}
map.put(typeParameterDescriptor, typeValue);
}
@Override
public void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue) {
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
Map<JetType,ConstraintSystemImpl.TypeValue> map = debugInfo.get(BOUNDS_FOR_KNOWNS);
if (map == null) {
map = Maps.newLinkedHashMap();
debugInfo.set(BOUNDS_FOR_KNOWNS, map);
}
map.put(type, typeValue);
}
@Override
public void done(ConstraintSystemSolution solution, Set<TypeParameterDescriptor> typeParameterDescriptors) {
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
debugInfo.set(SOLUTION, solution);
debugInfo.set(UNKNOWNS, typeParameterDescriptors);
}
@Override
public void log(Object message) {
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
StringBuilder stringBuilder = debugInfo.get(LOG);
if (stringBuilder == null) {
stringBuilder = new StringBuilder();
debugInfo.set(LOG, stringBuilder);
}
stringBuilder.append(message).append("\n");
}
@Override
public void error(Object message) {
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
StringBuilder stringBuilder = debugInfo.get(ERRORS);
if (stringBuilder == null) {
stringBuilder = new StringBuilder();
debugInfo.set(ERRORS, stringBuilder);
}
stringBuilder.append(message).append("\n");
}
}
@@ -0,0 +1,55 @@
package org.jetbrains.jet.lang.resolve.calls.inference;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Set;
/**
* @author abreslav
*/
public class PrintingConstraintResolutionListener implements ConstraintResolutionListener {
@Override
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue) {
println("Constraints for " + typeParameterDescriptor);
printTypeValue(typeValue);
}
@Override
public void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue) {
println("Constraints for " + type);
printTypeValue(typeValue);
}
@Override
public void done(ConstraintSystemSolution solution, Set<TypeParameterDescriptor> typeParameterDescriptors) {
println("==================================================");
println("");
println("");
}
@Override
public void log(Object message) {
println(message);
}
@Override
public void error(Object message) {
println(message);
}
private void printTypeValue(ConstraintSystemImpl.TypeValue typeValue) {
for (ConstraintSystemImpl.TypeValue bound : typeValue.getUpperBounds()) {
println(" :< " + bound);
}
for (ConstraintSystemImpl.TypeValue bound : typeValue.getLowerBounds()) {
println(" :> " + bound);
}
}
private static void println(Object message) {
ResolutionDebugInfo.println(message);
}
}
@@ -199,6 +199,10 @@ public class WriteThroughScope extends WritableScopeWithImports {
allDescriptors = Lists.newArrayList();
allDescriptors.addAll(writableWorker.getAllDescriptors());
allDescriptors.addAll(getWorkerScope().getAllDescriptors());
for (JetScope imported : getImports()) {
allDescriptors.addAll(imported.getAllDescriptors());
}
}
return allDescriptors;
}
@@ -1,12 +1,37 @@
package org.jetbrains.jet.util.slicedmap;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
/**
* @author abreslav
*/
public interface SlicedMap extends Iterable<Map.Entry<SlicedMapKey<?, ?>, ?>> {
SlicedMap DO_NOTHING = new SlicedMap() {
@Override
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
return slice.computeValue(this, key, null, true);
}
@Override
public <K, V> boolean containsKey(ReadOnlySlice<K, V> slice, K key) {
return false;
}
@Override
public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
return Collections.emptySet();
}
@Override
public Iterator<Map.Entry<SlicedMapKey<?, ?>, ?>> iterator() {
return Collections.<Map.Entry<SlicedMapKey<?, ?>, ?>>emptySet().iterator();
}
};
<K, V> V get(ReadOnlySlice<K, V> slice, K key);
<K, V> boolean containsKey(ReadOnlySlice<K, V> slice, K key);