JET-26 Check bounds in generic types: fixed substitution problems

This commit is contained in:
Andrey Breslav
2011-05-11 18:26:53 +04:00
parent 7c263c3e95
commit d40bec3eba
22 changed files with 481 additions and 135 deletions
+11 -12
View File
@@ -7,7 +7,7 @@ class TypeInfo<T> {
class Iterator<out T> {
fun next() : T
val hasNext : Boolean
abstract val hasNext : Boolean
}
class Iterable<out T> {
@@ -38,7 +38,7 @@ class Boolean : Comparable<Boolean> {
fun equals(other : Any?) : Boolean
}
class String : Comparable<String> {
class String() : Comparable<String> {
fun get(index : Int) : Char
val length : Int
@@ -50,19 +50,18 @@ class Range<in T : Comparable<T>> {
fun contains(item : T) : Boolean
}
class IntRange<T> : Range<T>, Iterable<T> {
class IntRange<T : Comparable<T>> : Range<T>, Iterable<T> {
}
class Number : Hashable {
val dbl : Double
val flt : Float
val lng : Long
val int : Int
val chr : Char
val sht : Short
val byt : Byte
abstract val dbl : Double
abstract val flt : Float
abstract val lng : Long
abstract val int : Int
abstract val chr : Char
abstract val sht : Short
abstract val byt : Byte
// fun equals(other : Double) : Boolean
// fun equals(other : Float) : Boolean
// fun equals(other : Long) : Boolean
@@ -526,4 +525,4 @@ class Byte : Number, Comparable<Byte> {
fun dec() : Byte
fun plus() : Int
fun minus() : Int
}
}
@@ -467,7 +467,7 @@ public class ExpressionCodegen extends JetVisitor {
}
}
boolean isStatic = descriptor.getContainingDeclaration() instanceof NamespaceDescriptor;
boolean isStatic = descriptor.getContainingDeclaration() instanceof NamespaceDescriptorImpl;
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField);
if (!isStatic) {
@@ -482,7 +482,7 @@ public class ExpressionCodegen extends JetVisitor {
}
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean directToField) {
boolean isStatic = propertyDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor;
boolean isStatic = propertyDescriptor.getContainingDeclaration() instanceof NamespaceDescriptorImpl;
final JetType outType = propertyDescriptor.getOutType();
boolean isInsideClass = propertyDescriptor.getContainingDeclaration() == contextType;
Method getter;
@@ -572,7 +572,7 @@ public class ExpressionCodegen extends JetVisitor {
}
else {
methodDescriptor = typeMapper.mapSignature((JetFunction) declarationPsiElement);
if (functionParent instanceof NamespaceDescriptor && declarationPsiElement instanceof JetFunction) {
if (functionParent instanceof NamespaceDescriptorImpl && declarationPsiElement instanceof JetFunction) {
pushMethodArguments(expression, methodDescriptor);
final String owner = NamespaceCodegen.getJVMClassName(DescriptorUtil.getFQName(functionParent));
v.invokestatic(owner, methodDescriptor.getName(), methodDescriptor.getDescriptor());
@@ -86,7 +86,7 @@ public class JetTypeMapper {
static String getOwner(DeclarationDescriptor descriptor, OwnerKind kind) {
String owner;
if (descriptor.getContainingDeclaration() instanceof NamespaceDescriptor) {
if (descriptor.getContainingDeclaration() instanceof NamespaceDescriptorImpl) {
owner = jvmName((NamespaceDescriptor) descriptor.getContainingDeclaration());
}
else if (descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
@@ -0,0 +1,38 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.NamespaceType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.List;
/**
* @author abreslav
*/
public abstract class AbstractNamespaceDescriptorImpl extends DeclarationDescriptorImpl implements NamespaceDescriptor {
private NamespaceType namespaceType;
public AbstractNamespaceDescriptorImpl(DeclarationDescriptor containingDeclaration, List<Annotation> annotations, String name) {
super(containingDeclaration, annotations, name);
}
@Override
@NotNull
public NamespaceType getNamespaceType() {
if (namespaceType == null) {
namespaceType = new NamespaceType(getName(), getMemberScope());
}
return namespaceType;
}
@NotNull
@Override
public NamespaceDescriptor substitute(TypeSubstitutor substitutor) {
throw new UnsupportedOperationException("This operation does not make sense for a namespace");
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitNamespaceDescriptor(this, data);
}
}
@@ -14,7 +14,7 @@ import java.util.Set;
/**
* @author abreslav
*/
public class MutableClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor {
public class MutableClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor, NamespaceLike {
private ConstructorDescriptor primaryConstructor;
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
private final Set<FunctionDescriptor> functions = Sets.newHashSet();
@@ -71,7 +71,8 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
constructors.addFunction(constructorDescriptor);
}
public void addProperty(@NotNull PropertyDescriptor propertyDescriptor) {
@Override
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
properties.add(propertyDescriptor);
}
@@ -80,7 +81,8 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
return properties;
}
public void addFunction(@NotNull FunctionDescriptor functionDescriptor) {
@Override
public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
functions.add(functionDescriptor);
}
@@ -89,6 +91,21 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
return functions;
}
@Override
public NamespaceDescriptorImpl getNamespace(String name) {
throw new UnsupportedOperationException("Classes do not define namespaces");
}
@Override
public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
throw new UnsupportedOperationException("Classes do not define namespaces");
}
@Override
public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) {
classes.add(classDescriptor);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void setUnsubstitutedMemberScope(@NotNull JetScope unsubstitutedMemberScope) {
@@ -99,6 +116,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
@NotNull
@Override
public TypeConstructor getTypeConstructor() {
assert typeConstructor != null : "Type constructor is not set for " + getName();
return typeConstructor;
}
@@ -1,51 +1,16 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.types.NamespaceType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.List;
/**
* @author abreslav
*/
public class NamespaceDescriptor extends DeclarationDescriptorImpl {
private NamespaceType namespaceType;
private JetScope memberScope;
public NamespaceDescriptor(@Nullable DeclarationDescriptor containingDeclaration, @NotNull List<Annotation> annotations, @NotNull String name) {
super(containingDeclaration, annotations, name);
}
public void initialize(@NotNull JetScope memberScope) {
this.memberScope = memberScope;
}
public interface NamespaceDescriptor extends Annotated, Named, DeclarationDescriptor {
@NotNull
JetScope getMemberScope();
@NotNull
public JetScope getMemberScope() {
return memberScope;
}
@NotNull
public NamespaceType getNamespaceType() {
if (namespaceType == null) {
assert memberScope != null : "Member scope not set";
namespaceType = new NamespaceType(getName(), memberScope);
}
return namespaceType;
}
@NotNull
@Override
public NamespaceDescriptor substitute(TypeSubstitutor substitutor) {
return this;
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitNamespaceDescriptor(this, data);
}
NamespaceType getNamespaceType();
}
@@ -0,0 +1,54 @@
package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.WritableScope;
import java.util.List;
/**
* @author abreslav
*/
public class NamespaceDescriptorImpl extends AbstractNamespaceDescriptorImpl implements NamespaceLike {
private WritableScope memberScope;
public NamespaceDescriptorImpl(@Nullable DeclarationDescriptor containingDeclaration, @NotNull List<Annotation> annotations, @NotNull String name) {
super(containingDeclaration, annotations, name);
}
public void initialize(@NotNull WritableScope memberScope) {
this.memberScope = memberScope;
}
@Override
@NotNull
public WritableScope getMemberScope() {
return memberScope;
}
@Override
public NamespaceDescriptorImpl getNamespace(String name) {
return (NamespaceDescriptorImpl) memberScope.getDeclaredNamespace(name);
}
@Override
public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
memberScope.addNamespace(namespaceDescriptor);
}
@Override
public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) {
memberScope.addClassifierDescriptor(classDescriptor);
}
@Override
public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
memberScope.addFunctionDescriptor(functionDescriptor);
}
@Override
public void addPropertyDescriptor(@NotNull PropertyDescriptor variableDescriptor) {
memberScope.addVariableDescriptor(variableDescriptor);
}
}
@@ -58,9 +58,13 @@ public interface NamespaceLike extends DeclarationDescriptor {
}
@Nullable
NamespaceDescriptor getNamespace(String name);
NamespaceDescriptorImpl getNamespace(String name);
void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor);
void addClassifierDescriptor(MutableClassDescriptor classDescriptor);
void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor);
void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor);
void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor);
}
@@ -14,12 +14,15 @@ import org.jetbrains.jet.lang.ErrorHandler;
import org.jetbrains.jet.lang.JetDiagnostic;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.lang.resolve.java.JavaPackageScope;
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
import java.util.Collections;
/**
* @author abreslav
*/
@@ -51,13 +54,43 @@ public class AnalyzingUtils {
JavaSemanticServices javaSemanticServices = new JavaSemanticServices(project, semanticServices, bindingTraceContext);
JetScope libraryScope = semanticServices.getStandardLibrary().getLibraryScope();
WritableScope scope = new WritableScopeImpl(libraryScope, new ModuleDescriptor("<module>"), bindingTraceContext.getErrorHandler(), null);
ModuleDescriptor owner = new ModuleDescriptor("<module>");
final WritableScope scope = new WritableScopeImpl(libraryScope, owner, bindingTraceContext.getErrorHandler(), null);
// scope.importScope(javaSemanticServices.getDescriptorResolver().resolveNamespace("").getMemberScope());
// scope.importScope(javaSemanticServices.getDescriptorResolver().resolveNamespace("java.lang").getMemberScope());
scope.importScope(new JavaPackageScope("", null, javaSemanticServices));
scope.importScope(new JavaPackageScope("java.lang", null, javaSemanticServices));
new TopDownAnalyzer(semanticServices, bindingTraceContext, flowDataTraceFactory).process(scope, namespace);
TopDownAnalyzer topDownAnalyzer = new TopDownAnalyzer(semanticServices, bindingTraceContext, flowDataTraceFactory);
// topDownAnalyzer.process(scope, Collections.<JetDeclaration>singletonList(namespace));
// if (false)
topDownAnalyzer.process(scope, new NamespaceLike.Adapter(owner) {
@Override
public NamespaceDescriptorImpl getNamespace(String name) {
return null;
}
@Override
public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
scope.addNamespace(namespaceDescriptor);
}
@Override
public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) {
scope.addClassifierDescriptor(classDescriptor);
}
@Override
public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
scope.addFunctionDescriptor(functionDescriptor);
}
@Override
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
scope.addVariableDescriptor(propertyDescriptor);
}
}, Collections.<JetDeclaration>singletonList(namespace));
return bindingTraceContext;
}
@@ -54,7 +54,7 @@ public class ClassDescriptorResolver {
// TODO : assuming that the hierarchy is acyclic
Collection<JetType> supertypes = delegationSpecifiers.isEmpty()
? Collections.singleton(JetStandardClasses.getAnyType())
: resolveDelegationSpecifiers(parameterScope, delegationSpecifiers);
: resolveDelegationSpecifiers(parameterScope, delegationSpecifiers, typeResolver);
boolean open = classElement.hasModifier(JetTokens.OPEN_KEYWORD);
WritableScope members = resolveMembers(classDescriptor, classElement, typeParameters, scope, parameterScope, supertypes);
@@ -124,6 +124,9 @@ public class ClassDescriptorResolver {
if (extendsBound != null) {
typeParameterDescriptor.addUpperBound(typeResolverNotCheckingBounds.resolveType(classDescriptor.getClassHeaderScope(), extendsBound));
}
else {
typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound());
}
}
// TODO : Bounds from with
}
@@ -133,7 +136,7 @@ public class ClassDescriptorResolver {
// TODO : assuming that the hierarchy is acyclic
Collection<? extends JetType> superclasses = delegationSpecifiers.isEmpty()
? Collections.singleton(JetStandardClasses.getAnyType())
: resolveDelegationSpecifiers(descriptor.getClassHeaderScope(), delegationSpecifiers);
: resolveDelegationSpecifiers(descriptor.getClassHeaderScope(), delegationSpecifiers, typeResolverNotCheckingBounds);
((TypeConstructorImpl) descriptor.getTypeConstructor()).getSupertypes().addAll(superclasses);
}
@@ -164,7 +167,7 @@ public class ClassDescriptorResolver {
// TODO : assuming that the hierarchy is acyclic
Collection<? extends JetType> superclasses = delegationSpecifiers.isEmpty()
? Collections.singleton(JetStandardClasses.getAnyType())
: resolveDelegationSpecifiers(parameterScope, delegationSpecifiers);
: resolveDelegationSpecifiers(parameterScope, delegationSpecifiers, typeResolver);
// TODO : UGLY HACK
supertypes.addAll(superclasses);
@@ -325,7 +328,7 @@ public class ClassDescriptorResolver {
return typeParameterDescriptor;
}
private Collection<JetType> resolveDelegationSpecifiers(WritableScope extensibleScope, List<JetDelegationSpecifier> delegationSpecifiers) {
private Collection<JetType> resolveDelegationSpecifiers(WritableScope extensibleScope, List<JetDelegationSpecifier> delegationSpecifiers, @NotNull TypeResolver resolver) {
if (delegationSpecifiers.isEmpty()) {
return Collections.emptyList();
}
@@ -333,7 +336,7 @@ public class ClassDescriptorResolver {
for (JetDelegationSpecifier delegationSpecifier : delegationSpecifiers) {
JetTypeReference typeReference = delegationSpecifier.getTypeReference();
if (typeReference != null) {
result.add(typeResolver.resolveType(extensibleScope, typeReference));
result.add(resolver.resolveType(extensibleScope, typeReference));
}
else {
result.add(ErrorUtils.createErrorType("No type reference"));
@@ -489,19 +492,25 @@ public class ClassDescriptorResolver {
}
@NotNull
private JetType getType(@NotNull JetScope scope, @NotNull JetProperty property) {
private JetType getType(@NotNull final JetScope scope, @NotNull JetProperty property) {
// TODO : receiver?
JetTypeReference propertyTypeRef = property.getPropertyTypeRef();
JetType type;
if (propertyTypeRef == null) {
JetExpression initializer = property.getInitializer();
final JetExpression initializer = property.getInitializer();
if (initializer == null) {
trace.getErrorHandler().genericError(property.getNode(), "This property must either have a type annotation or be initialized");
type = ErrorUtils.createErrorType("No type, no body");
} else {
// TODO : ??? Fix-point here: what if we have something like "val a = foo {a.bar()}"
type = semanticServices.getTypeInferrer(trace, JetFlowInformationProvider.THROW_EXCEPTION).safeGetType(scope, initializer, false);
// TODO : a risk of a memory leak
type = new DeferredType(new LazyValue<JetType>() {
@Override
protected JetType compute() {
return semanticServices.getTypeInferrer(trace, JetFlowInformationProvider.THROW_EXCEPTION).safeGetType(scope, initializer, false);
}
});
}
} else {
type = typeResolver.resolveType(scope, propertyTypeRef);
@@ -590,6 +599,7 @@ public class ClassDescriptorResolver {
List<JetTypeReference> typeReferences = typeElement.getTypeArgumentsAsTypes();
assert typeReferences.size() == arguments.size() : typeElement.getText();
TypeSubstitutor substitutor = TypeSubstitutor.create(type);
for (int i = 0, projectionsSize = typeReferences.size(); i < projectionsSize; i++) {
JetTypeReference argumentTypeReference = typeReferences.get(i);
@@ -599,14 +609,19 @@ public class ClassDescriptorResolver {
checkBounds(argumentTypeReference, typeArgument);
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
checkBounds(argumentTypeReference, typeArgument, typeParameterDescriptor);
checkBounds(argumentTypeReference, typeArgument, typeParameterDescriptor, substitutor);
}
}
public void checkBounds(@NotNull JetTypeReference argumentTypeReference, @NotNull JetType typeArgument, @NotNull TypeParameterDescriptor typeParameterDescriptor) {
public void checkBounds(
@NotNull JetTypeReference argumentTypeReference,
@NotNull JetType typeArgument,
@NotNull TypeParameterDescriptor typeParameterDescriptor,
@NotNull TypeSubstitutor substitutor) {
for (JetType bound : typeParameterDescriptor.getUpperBounds()) {
if (!semanticServices.getTypeChecker().isSubtypeOf(typeArgument, bound)) {
trace.getErrorHandler().genericError(argumentTypeReference.getNode(), "An upper bound " + bound + " is violated"); // TODO : Message
JetType substitutedBound = substitutor.safeSubstitute(bound, Variance.INVARIANT);
if (!semanticServices.getTypeChecker().isSubtypeOf(typeArgument, substitutedBound)) {
trace.getErrorHandler().genericError(argumentTypeReference.getNode(), "An upper bound " + substitutedBound + " is violated"); // TODO : Message
}
}
}
@@ -25,8 +25,10 @@ import java.util.*;
public class TopDownAnalyzer {
private final Map<JetClass, MutableClassDescriptor> classes = Maps.newLinkedHashMap();
private final Map<JetNamespace, WritableScope> namespaceScopes = new LinkedHashMap<JetNamespace, WritableScope>();
private final Map<JetDeclaration, FunctionDescriptorImpl> functions = Maps.newLinkedHashMap();
private final Map<JetNamespace, WritableScope> namespaceScopes = Maps.newHashMap();
private final Map<JetNamespace, NamespaceDescriptorImpl> namespaceDescriptors = Maps.newHashMap();
private final Map<JetFunction, FunctionDescriptorImpl> functions = Maps.newLinkedHashMap();
private final Map<JetDeclaration, ConstructorDescriptor> constructors = Maps.newLinkedHashMap();
private final Map<JetProperty, PropertyDescriptor> properties = new LinkedHashMap<JetProperty, PropertyDescriptor>();
private final Map<JetDeclaration, JetScope> declaringScopes = Maps.newHashMap();
@@ -82,19 +84,24 @@ public class TopDownAnalyzer {
this(semanticServices, bindingTrace, JetControlFlowDataTraceFactory.EMPTY);
}
public void process(@NotNull JetScope outerScope, @NotNull JetDeclaration declaration) {
process(outerScope, Collections.singletonList(declaration));
}
// public void process(@NotNull JetScope outerScope, @NotNull JetDeclaration declaration) {
// process(outerScope, Collections.singletonList(declaration));
// }
public <T extends NamespaceDescriptor & NamespaceLike> void process(@NotNull WritableScope outerScope, T owner, @NotNull List<JetDeclaration> declarations) {
public void process(@NotNull WritableScope outerScope, NamespaceLike owner, @NotNull List<JetDeclaration> declarations) {
collectNamespacesAndClassifiers(outerScope, owner, declarations); // namespaceScopes, classes
createTypeConstructors(); // create type constructors for classes and generic parameters
resolveTypesInClassHeaders(); // Generic bounds and types in supertype lists (no expressions or constructor resolution)
checkGenericBoundsInClassHeaders(); // For the types resolved so far
resolveFunctionAndPropertyHeaders(); // TODO : for now, fail fast if something is unknown yet (i.e. some type annotation is omitted)
resolveFunctionAndPropertyHeaders(declarations); // TODO : for now, fail fast if something is unknown yet (i.e. some type annotation is omitted)
resolveExecutableCode();
// processBehaviorDeclarators(outerScope, declarations);
// readyToProcessExpressions = true;
// resolveBehaviorDeclarationBodies();
}
private void collectNamespacesAndClassifiers(
@@ -111,10 +118,10 @@ public class TopDownAnalyzer {
if (name == null) {
name = "<no name provided>";
}
NamespaceDescriptor namespaceDescriptor = owner.getNamespace(name);
NamespaceDescriptorImpl namespaceDescriptor = owner.getNamespace(name);
if (namespaceDescriptor == null) {
namespaceDescriptor = new NamespaceDescriptor(
owner, //declaringScope.getContainingDeclaration(),
namespaceDescriptor = new NamespaceDescriptorImpl(
owner.getOriginal(), //declaringScope.getContainingDeclaration(),
Collections.<Annotation>emptyList(), // TODO
name
);
@@ -122,8 +129,9 @@ public class TopDownAnalyzer {
owner.addNamespace(namespaceDescriptor);
trace.recordDeclarationResolution(namespace, namespaceDescriptor);
}
namespaceDescriptors.put(namespace, namespaceDescriptor);
WritableScope namespaceScope = new WritableScopeImpl(outerScope, owner, trace.getErrorHandler(), null);
WritableScope namespaceScope = new WriteThroughScope(outerScope, (WritableScope) namespaceDescriptor.getMemberScope());
namespaceScopes.put(namespace, namespaceScope);
for (JetImportDirective importDirective : importDirectives) {
@@ -143,23 +151,7 @@ public class TopDownAnalyzer {
}
}
final NamespaceDescriptor finalNamespaceDescriptor = namespaceDescriptor;
collectNamespacesAndClassifiers(namespaceScope, new NamespaceLike.Adapter(finalNamespaceDescriptor) {
@Override
public NamespaceDescriptor getNamespace(String name) {
return ((WritableScope) finalNamespaceDescriptor.getMemberScope()).getDeclaredNamespace(name);
}
@Override
public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
((WritableScope) namespaceDescriptor.getMemberScope()).addNamespace(namespaceDescriptor);
}
@Override
public void addClassifierDescriptor(MutableClassDescriptor classDescriptor) {
((WritableScope) finalNamespaceDescriptor.getMemberScope()).addClassifierDescriptor(classDescriptor);
}
}, namespace.getDeclarations());
collectNamespacesAndClassifiers(namespaceScope, namespaceDescriptor, namespace.getDeclarations());
}
@Override
@@ -228,12 +220,53 @@ public class TopDownAnalyzer {
}
private void resolveFunctionAndPropertyHeaders() {
throw new UnsupportedOperationException(); // TODO
private void resolveFunctionAndPropertyHeaders(@NotNull List<JetDeclaration> declarations) {
for (Map.Entry<JetNamespace, WritableScope> entry : namespaceScopes.entrySet()) {
JetNamespace namespace = entry.getKey();
final WritableScope namespaceScope = entry.getValue();
final NamespaceLike namespaceDescriptor = namespaceDescriptors.get(namespace);
resolveFunctionAndPropertyHeaders(namespace.getDeclarations(), namespaceScope, namespaceDescriptor);
}
for (Map.Entry<JetClass, MutableClassDescriptor> entry : classes.entrySet()) {
JetClass jetClass = entry.getKey();
final MutableClassDescriptor classDescriptor = entry.getValue();
resolveFunctionAndPropertyHeaders(jetClass.getDeclarations(), classDescriptor.getClassHeaderScope(), classDescriptor);
processPrimaryConstructor(classDescriptor, jetClass);
// processBehaviorDeclarators(classDescriptor.getWritableUnsubstitutedMemberScope(), jetClass.getDeclarations());
// TODO : Constructors
}
// TODO : Extensions
}
private void resolveFunctionAndPropertyHeaders(@NotNull List<JetDeclaration> declarations, final @NotNull JetScope scope, final @NotNull NamespaceLike namespaceLike) {
for (JetDeclaration declaration : declarations) {
declaration.accept(new JetVisitor() {
@Override
public void visitFunction(JetFunction function) {
FunctionDescriptorImpl functionDescriptor = classDescriptorResolver.resolveFunctionDescriptor(namespaceLike, scope, function);
namespaceLike.addFunctionDescriptor(functionDescriptor);
functions.put(function, functionDescriptor);
declaringScopes.put(function, scope);
}
@Override
public void visitProperty(JetProperty property) {
PropertyDescriptor propertyDescriptor = classDescriptorResolver.resolvePropertyDescriptor(namespaceLike, scope, property);
namespaceLike.addPropertyDescriptor(propertyDescriptor);
properties.put(property, propertyDescriptor);
declaringScopes.put(property, scope);
}
});
}
}
private void resolveExecutableCode() {
throw new UnsupportedOperationException(); // TODO
readyToProcessExpressions = true;
resolveBehaviorDeclarationBodies();
}
@NotNull
@@ -263,9 +296,9 @@ public class TopDownAnalyzer {
if (name == null) {
name = "<no name provided>";
}
NamespaceDescriptor namespaceDescriptor = declaringScope.getDeclaredNamespace(name);
NamespaceDescriptorImpl namespaceDescriptor = (NamespaceDescriptorImpl) declaringScope.getDeclaredNamespace(name);
if (namespaceDescriptor == null) {
namespaceDescriptor = new NamespaceDescriptor(
namespaceDescriptor = new NamespaceDescriptorImpl(
declaringScope.getContainingDeclaration(),
Collections.<Annotation>emptyList(), // TODO
name
@@ -814,7 +847,7 @@ public class TopDownAnalyzer {
}
private void resolveFunctionBodies() {
for (Map.Entry<JetDeclaration, FunctionDescriptorImpl> entry : functions.entrySet()) {
for (Map.Entry<JetFunction, FunctionDescriptorImpl> entry : functions.entrySet()) {
JetDeclaration declaration = entry.getKey();
FunctionDescriptor descriptor = entry.getValue();
@@ -92,17 +92,6 @@ public class TypeResolver {
trace.getErrorHandler().genericError(type.getTypeArgumentList().getNode(), errorMessage);
}
} else {
if (checkBounds) {
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
TypeParameterDescriptor parameter = parameters.get(i);
JetType argument = arguments.get(i).getType();
JetTypeReference typeReference = type.getTypeArguments().get(i).getTypeReference();
if (typeReference != null) {
semanticServices.getClassDescriptorResolver(trace).checkBounds(typeReference, argument, parameter);
}
}
}
result[0] = new JetTypeImpl(
annotations,
typeConstructor,
@@ -110,6 +99,18 @@ public class TypeResolver {
arguments,
classDescriptor.getMemberScope(arguments)
);
if (checkBounds) {
TypeSubstitutor substitutor = TypeSubstitutor.create(result[0]);
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
TypeParameterDescriptor parameter = parameters.get(i);
JetType argument = arguments.get(i).getType();
JetTypeReference typeReference = type.getTypeArguments().get(i).getTypeReference();
if (typeReference != null) {
semanticServices.getClassDescriptorResolver(trace).checkBounds(typeReference, argument, parameter, substitutor);
}
}
}
}
}
}
@@ -1,5 +1,6 @@
package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.ErrorHandler;
@@ -244,7 +245,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
@NotNull
public Map<String, NamespaceDescriptor> getNamespaceDescriptors() {
if (namespaceDescriptors == null) {
namespaceDescriptors = new HashMap<String, NamespaceDescriptor>();
namespaceDescriptors = Maps.newHashMap();
}
return namespaceDescriptors;
}
@@ -189,23 +189,23 @@ public class JavaDescriptorResolver {
}
private NamespaceDescriptor createJavaNamespaceDescriptor(PsiPackage psiPackage) {
NamespaceDescriptor namespaceDescriptor = new NamespaceDescriptor(
JavaNamespaceDescriptor namespaceDescriptor = new JavaNamespaceDescriptor(
JAVA_ROOT,
Collections.<Annotation>emptyList(), // TODO
psiPackage.getName()
);
namespaceDescriptor.initialize(new JavaPackageScope(psiPackage.getQualifiedName(), namespaceDescriptor, semanticServices));
namespaceDescriptor.setMemberScope(new JavaPackageScope(psiPackage.getQualifiedName(), namespaceDescriptor, semanticServices));
semanticServices.getTrace().recordDeclarationResolution(psiPackage, namespaceDescriptor);
return namespaceDescriptor;
}
private NamespaceDescriptor createJavaNamespaceDescriptor(@NotNull final PsiClass psiClass) {
NamespaceDescriptor namespaceDescriptor = new NamespaceDescriptor(
JavaNamespaceDescriptor namespaceDescriptor = new JavaNamespaceDescriptor(
JAVA_ROOT,
Collections.<Annotation>emptyList(), // TODO
psiClass.getName()
);
namespaceDescriptor.initialize(new JavaClassMembersScope(namespaceDescriptor, psiClass, semanticServices, true));
namespaceDescriptor.setMemberScope(new JavaClassMembersScope(namespaceDescriptor, psiClass, semanticServices, true));
semanticServices.getTrace().recordDeclarationResolution(psiClass, namespaceDescriptor);
return namespaceDescriptor;
}
@@ -0,0 +1,30 @@
package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.AbstractNamespaceDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.Annotation;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.resolve.JetScope;
import java.util.List;
/**
* @author abreslav
*/
public class JavaNamespaceDescriptor extends AbstractNamespaceDescriptorImpl {
private JetScope memberScope;
public JavaNamespaceDescriptor(DeclarationDescriptor containingDeclaration, List<Annotation> annotations, String name) {
super(containingDeclaration, annotations, name);
}
public void setMemberScope(@NotNull JetScope memberScope) {
this.memberScope = memberScope;
}
@NotNull
@Override
public JetScope getMemberScope() {
return memberScope;
}
}
@@ -0,0 +1,60 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.Annotation;
import org.jetbrains.jet.lang.resolve.JetScope;
import java.util.List;
/**
* @author abreslav
*/
public class DeferredType implements JetType {
private final LazyValue<JetType> lazyValue;
public DeferredType(LazyValue<JetType> lazyValue) {
this.lazyValue = lazyValue;
}
public JetType getActualType() {
return lazyValue.get();
}
@Override
@NotNull
public JetScope getMemberScope() {
return getActualType().getMemberScope();
}
@Override
@NotNull
public TypeConstructor getConstructor() {
return getActualType().getConstructor();
}
@Override
@NotNull
public List<TypeProjection> getArguments() {
return getActualType().getArguments();
}
@Override
public boolean isNullable() {
return getActualType().isNullable();
}
@Override
public List<Annotation> getAnnotations() {
return getActualType().getAnnotations();
}
@Override
public String toString() {
try {
return getActualType().toString();
}
catch (ReenteringLazyValueComputationException e) {
return "<Failed to compute this type>";
}
}
}
@@ -22,7 +22,7 @@ public class JetStandardClasses {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private static NamespaceDescriptor STANDARD_CLASSES_NAMESPACE = new NamespaceDescriptor(null, Collections.<Annotation>emptyList(), "jet");
/*package*/ static NamespaceDescriptorImpl STANDARD_CLASSES_NAMESPACE = new NamespaceDescriptorImpl(null, Collections.<Annotation>emptyList(), "jet");
private static final ClassDescriptor NOTHING_CLASS = new ClassDescriptorImpl(
STANDARD_CLASSES_NAMESPACE,
@@ -201,6 +201,7 @@ public class JetStandardClasses {
}
}
}
STANDARD_CLASSES_NAMESPACE.initialize(writableScope);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -4,14 +4,13 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.PsiFileFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.ErrorHandler;
import org.jetbrains.jet.lang.JetFileType;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.Annotation;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import org.jetbrains.jet.lang.resolve.*;
import java.io.IOException;
import java.io.InputStream;
@@ -73,7 +72,11 @@ public class JetStandardLibrary {
JetSemanticServices bootstrappingSemanticServices = JetSemanticServices.createSemanticServices(this);
BindingTraceContext bindingTraceContext = new BindingTraceContext();
TopDownAnalyzer bootstrappingTDA = new TopDownAnalyzer(bootstrappingSemanticServices, bindingTraceContext);
this.libraryScope = bootstrappingTDA.process(JetStandardClasses.STANDARD_CLASSES, file.getRootNamespace().getDeclarations());
WritableScopeImpl writableScope = new WritableScopeImpl(JetStandardClasses.STANDARD_CLASSES, JetStandardClasses.STANDARD_CLASSES_NAMESPACE, ErrorHandler.THROW_EXCEPTION, null);
// this.libraryScope = bootstrappingTDA.process(JetStandardClasses.STANDARD_CLASSES, file.getRootNamespace().getDeclarations());
bootstrappingTDA.process(writableScope, JetStandardClasses.STANDARD_CLASSES_NAMESPACE, file.getRootNamespace().getDeclarations());
this.libraryScope = JetStandardClasses.STANDARD_CLASSES_NAMESPACE.getMemberScope();
AnalyzingUtils.applyHandler(ErrorHandler.THROW_EXCEPTION, bindingTraceContext);
this.byteClass = (ClassDescriptor) libraryScope.getClassifier("Byte");
this.charClass = (ClassDescriptor) libraryScope.getClassifier("Char");
@@ -594,13 +594,19 @@ public class JetTypeInferrer {
@Nullable
public JetType getType(@NotNull JetExpression expression) {
assert result == null;
expression.accept(this);
if (result != null) {
trace.recordExpressionType(expression, result);
if (JetStandardClasses.isNothing(result) && !result.isNullable()) {
markDominatedExpressionsAsUnreachable(expression);
try {
expression.accept(this);
if (result != null) {
trace.recordExpressionType(expression, result);
if (JetStandardClasses.isNothing(result) && !result.isNullable()) {
markDominatedExpressionsAsUnreachable(expression);
}
}
}
catch (ReenteringLazyValueComputationException e) {
trace.getErrorHandler().genericError(expression.getNode(), "Type inference has run into a recursive problem"); // TODO : message
result = null;
}
return result;
}
@@ -0,0 +1,47 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
/**
* @author abreslav
*/
public abstract class LazyValue<T> {
private enum State {
NOT_COMPUTED,
BEING_COMPUTED,
COMPUTED,
ERROR
}
private State state = State.NOT_COMPUTED;
private T value;
protected abstract T compute();
public State getState() {
return state;
}
@NotNull
public final T get() {
switch (state) {
case NOT_COMPUTED:
state = State.BEING_COMPUTED;
value = compute();
state = State.COMPUTED;
return value;
case BEING_COMPUTED:
state = State.ERROR;
throw new ReenteringLazyValueComputationException();
case COMPUTED:
return value;
case ERROR:
throw new ReenteringLazyValueComputationException();
}
throw new IllegalStateException("Unreachable");
}
}
@@ -0,0 +1,21 @@
package org.jetbrains.jet.lang.types;
/**
* @author abreslav
*/
public class ReenteringLazyValueComputationException extends RuntimeException {
public ReenteringLazyValueComputationException() {
}
public ReenteringLazyValueComputationException(String message) {
super(message);
}
public ReenteringLazyValueComputationException(String message, Throwable cause) {
super(message, cause);
}
public ReenteringLazyValueComputationException(Throwable cause) {
super(cause);
}
}
+17
View File
@@ -1,3 +1,20 @@
namespace boundsWithSubstitutors {
class A<T>
class B<X : A<X>>()
class C : A<C>
val a = new B<C>()
val a1 = new B<<error>Int</error>>()
class X<A, B : A>()
val b = new X<Any, X<A<C>, C>>
val b0 = new X<Any, <error>Any?</error>>
val b1 = new X<Any, X<A<C>, <error>String</error>>>
}
class A
class B<T : A>()