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
+10 -11
View File
@@ -7,7 +7,7 @@ class TypeInfo<T> {
class Iterator<out T> { class Iterator<out T> {
fun next() : T fun next() : T
val hasNext : Boolean abstract val hasNext : Boolean
} }
class Iterable<out T> { class Iterable<out T> {
@@ -38,7 +38,7 @@ class Boolean : Comparable<Boolean> {
fun equals(other : Any?) : Boolean fun equals(other : Any?) : Boolean
} }
class String : Comparable<String> { class String() : Comparable<String> {
fun get(index : Int) : Char fun get(index : Int) : Char
val length : Int val length : Int
@@ -50,19 +50,18 @@ class Range<in T : Comparable<T>> {
fun contains(item : T) : Boolean fun contains(item : T) : Boolean
} }
class IntRange<T> : Range<T>, Iterable<T> { class IntRange<T : Comparable<T>> : Range<T>, Iterable<T> {
} }
class Number : Hashable { class Number : Hashable {
val dbl : Double abstract val dbl : Double
val flt : Float abstract val flt : Float
val lng : Long abstract val lng : Long
val int : Int abstract val int : Int
val chr : Char abstract val chr : Char
val sht : Short abstract val sht : Short
val byt : Byte abstract val byt : Byte
// fun equals(other : Double) : Boolean // fun equals(other : Double) : Boolean
// fun equals(other : Float) : Boolean // fun equals(other : Float) : Boolean
// fun equals(other : Long) : Boolean // fun equals(other : Long) : Boolean
@@ -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 boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField); final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField);
if (!isStatic) { if (!isStatic) {
@@ -482,7 +482,7 @@ public class ExpressionCodegen extends JetVisitor {
} }
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean directToField) { 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(); final JetType outType = propertyDescriptor.getOutType();
boolean isInsideClass = propertyDescriptor.getContainingDeclaration() == contextType; boolean isInsideClass = propertyDescriptor.getContainingDeclaration() == contextType;
Method getter; Method getter;
@@ -572,7 +572,7 @@ public class ExpressionCodegen extends JetVisitor {
} }
else { else {
methodDescriptor = typeMapper.mapSignature((JetFunction) declarationPsiElement); methodDescriptor = typeMapper.mapSignature((JetFunction) declarationPsiElement);
if (functionParent instanceof NamespaceDescriptor && declarationPsiElement instanceof JetFunction) { if (functionParent instanceof NamespaceDescriptorImpl && declarationPsiElement instanceof JetFunction) {
pushMethodArguments(expression, methodDescriptor); pushMethodArguments(expression, methodDescriptor);
final String owner = NamespaceCodegen.getJVMClassName(DescriptorUtil.getFQName(functionParent)); final String owner = NamespaceCodegen.getJVMClassName(DescriptorUtil.getFQName(functionParent));
v.invokestatic(owner, methodDescriptor.getName(), methodDescriptor.getDescriptor()); v.invokestatic(owner, methodDescriptor.getName(), methodDescriptor.getDescriptor());
@@ -86,7 +86,7 @@ public class JetTypeMapper {
static String getOwner(DeclarationDescriptor descriptor, OwnerKind kind) { static String getOwner(DeclarationDescriptor descriptor, OwnerKind kind) {
String owner; String owner;
if (descriptor.getContainingDeclaration() instanceof NamespaceDescriptor) { if (descriptor.getContainingDeclaration() instanceof NamespaceDescriptorImpl) {
owner = jvmName((NamespaceDescriptor) descriptor.getContainingDeclaration()); owner = jvmName((NamespaceDescriptor) descriptor.getContainingDeclaration());
} }
else if (descriptor.getContainingDeclaration() instanceof ClassDescriptor) { 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 * @author abreslav
*/ */
public class MutableClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor { public class MutableClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor, NamespaceLike {
private ConstructorDescriptor primaryConstructor; private ConstructorDescriptor primaryConstructor;
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>"); private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
private final Set<FunctionDescriptor> functions = Sets.newHashSet(); private final Set<FunctionDescriptor> functions = Sets.newHashSet();
@@ -71,7 +71,8 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
constructors.addFunction(constructorDescriptor); constructors.addFunction(constructorDescriptor);
} }
public void addProperty(@NotNull PropertyDescriptor propertyDescriptor) { @Override
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
properties.add(propertyDescriptor); properties.add(propertyDescriptor);
} }
@@ -80,7 +81,8 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
return properties; return properties;
} }
public void addFunction(@NotNull FunctionDescriptor functionDescriptor) { @Override
public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
functions.add(functionDescriptor); functions.add(functionDescriptor);
} }
@@ -89,6 +91,21 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
return functions; 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) { public void setUnsubstitutedMemberScope(@NotNull JetScope unsubstitutedMemberScope) {
@@ -99,6 +116,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
@NotNull @NotNull
@Override @Override
public TypeConstructor getTypeConstructor() { public TypeConstructor getTypeConstructor() {
assert typeConstructor != null : "Type constructor is not set for " + getName();
return typeConstructor; return typeConstructor;
} }
@@ -1,51 +1,16 @@
package org.jetbrains.jet.lang.descriptors; package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.JetScope; import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.types.NamespaceType; import org.jetbrains.jet.lang.types.NamespaceType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import java.util.List;
/** /**
* @author abreslav * @author abreslav
*/ */
public class NamespaceDescriptor extends DeclarationDescriptorImpl { public interface NamespaceDescriptor extends Annotated, Named, DeclarationDescriptor {
private NamespaceType namespaceType; @NotNull
JetScope getMemberScope();
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;
}
@NotNull @NotNull
public JetScope getMemberScope() { NamespaceType getNamespaceType();
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);
}
} }
@@ -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 @Nullable
NamespaceDescriptor getNamespace(String name); NamespaceDescriptorImpl getNamespace(String name);
void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor); 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.JetDiagnostic;
import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; 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.JetFile;
import org.jetbrains.jet.lang.psi.JetNamespace; import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.lang.resolve.java.JavaPackageScope; import org.jetbrains.jet.lang.resolve.java.JavaPackageScope;
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
import java.util.Collections;
/** /**
* @author abreslav * @author abreslav
*/ */
@@ -51,13 +54,43 @@ public class AnalyzingUtils {
JavaSemanticServices javaSemanticServices = new JavaSemanticServices(project, semanticServices, bindingTraceContext); JavaSemanticServices javaSemanticServices = new JavaSemanticServices(project, semanticServices, bindingTraceContext);
JetScope libraryScope = semanticServices.getStandardLibrary().getLibraryScope(); 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("").getMemberScope());
// scope.importScope(javaSemanticServices.getDescriptorResolver().resolveNamespace("java.lang").getMemberScope()); // scope.importScope(javaSemanticServices.getDescriptorResolver().resolveNamespace("java.lang").getMemberScope());
scope.importScope(new JavaPackageScope("", null, javaSemanticServices)); scope.importScope(new JavaPackageScope("", null, javaSemanticServices));
scope.importScope(new JavaPackageScope("java.lang", 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; return bindingTraceContext;
} }
@@ -54,7 +54,7 @@ public class ClassDescriptorResolver {
// TODO : assuming that the hierarchy is acyclic // TODO : assuming that the hierarchy is acyclic
Collection<JetType> supertypes = delegationSpecifiers.isEmpty() Collection<JetType> supertypes = delegationSpecifiers.isEmpty()
? Collections.singleton(JetStandardClasses.getAnyType()) ? Collections.singleton(JetStandardClasses.getAnyType())
: resolveDelegationSpecifiers(parameterScope, delegationSpecifiers); : resolveDelegationSpecifiers(parameterScope, delegationSpecifiers, typeResolver);
boolean open = classElement.hasModifier(JetTokens.OPEN_KEYWORD); boolean open = classElement.hasModifier(JetTokens.OPEN_KEYWORD);
WritableScope members = resolveMembers(classDescriptor, classElement, typeParameters, scope, parameterScope, supertypes); WritableScope members = resolveMembers(classDescriptor, classElement, typeParameters, scope, parameterScope, supertypes);
@@ -124,6 +124,9 @@ public class ClassDescriptorResolver {
if (extendsBound != null) { if (extendsBound != null) {
typeParameterDescriptor.addUpperBound(typeResolverNotCheckingBounds.resolveType(classDescriptor.getClassHeaderScope(), extendsBound)); typeParameterDescriptor.addUpperBound(typeResolverNotCheckingBounds.resolveType(classDescriptor.getClassHeaderScope(), extendsBound));
} }
else {
typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound());
}
} }
// TODO : Bounds from with // TODO : Bounds from with
} }
@@ -133,7 +136,7 @@ public class ClassDescriptorResolver {
// TODO : assuming that the hierarchy is acyclic // TODO : assuming that the hierarchy is acyclic
Collection<? extends JetType> superclasses = delegationSpecifiers.isEmpty() Collection<? extends JetType> superclasses = delegationSpecifiers.isEmpty()
? Collections.singleton(JetStandardClasses.getAnyType()) ? Collections.singleton(JetStandardClasses.getAnyType())
: resolveDelegationSpecifiers(descriptor.getClassHeaderScope(), delegationSpecifiers); : resolveDelegationSpecifiers(descriptor.getClassHeaderScope(), delegationSpecifiers, typeResolverNotCheckingBounds);
((TypeConstructorImpl) descriptor.getTypeConstructor()).getSupertypes().addAll(superclasses); ((TypeConstructorImpl) descriptor.getTypeConstructor()).getSupertypes().addAll(superclasses);
} }
@@ -164,7 +167,7 @@ public class ClassDescriptorResolver {
// TODO : assuming that the hierarchy is acyclic // TODO : assuming that the hierarchy is acyclic
Collection<? extends JetType> superclasses = delegationSpecifiers.isEmpty() Collection<? extends JetType> superclasses = delegationSpecifiers.isEmpty()
? Collections.singleton(JetStandardClasses.getAnyType()) ? Collections.singleton(JetStandardClasses.getAnyType())
: resolveDelegationSpecifiers(parameterScope, delegationSpecifiers); : resolveDelegationSpecifiers(parameterScope, delegationSpecifiers, typeResolver);
// TODO : UGLY HACK // TODO : UGLY HACK
supertypes.addAll(superclasses); supertypes.addAll(superclasses);
@@ -325,7 +328,7 @@ public class ClassDescriptorResolver {
return typeParameterDescriptor; 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()) { if (delegationSpecifiers.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();
} }
@@ -333,7 +336,7 @@ public class ClassDescriptorResolver {
for (JetDelegationSpecifier delegationSpecifier : delegationSpecifiers) { for (JetDelegationSpecifier delegationSpecifier : delegationSpecifiers) {
JetTypeReference typeReference = delegationSpecifier.getTypeReference(); JetTypeReference typeReference = delegationSpecifier.getTypeReference();
if (typeReference != null) { if (typeReference != null) {
result.add(typeResolver.resolveType(extensibleScope, typeReference)); result.add(resolver.resolveType(extensibleScope, typeReference));
} }
else { else {
result.add(ErrorUtils.createErrorType("No type reference")); result.add(ErrorUtils.createErrorType("No type reference"));
@@ -489,19 +492,25 @@ public class ClassDescriptorResolver {
} }
@NotNull @NotNull
private JetType getType(@NotNull JetScope scope, @NotNull JetProperty property) { private JetType getType(@NotNull final JetScope scope, @NotNull JetProperty property) {
// TODO : receiver? // TODO : receiver?
JetTypeReference propertyTypeRef = property.getPropertyTypeRef(); JetTypeReference propertyTypeRef = property.getPropertyTypeRef();
JetType type; JetType type;
if (propertyTypeRef == null) { if (propertyTypeRef == null) {
JetExpression initializer = property.getInitializer(); final JetExpression initializer = property.getInitializer();
if (initializer == null) { if (initializer == null) {
trace.getErrorHandler().genericError(property.getNode(), "This property must either have a type annotation or be initialized"); trace.getErrorHandler().genericError(property.getNode(), "This property must either have a type annotation or be initialized");
type = ErrorUtils.createErrorType("No type, no body"); type = ErrorUtils.createErrorType("No type, no body");
} else { } else {
// TODO : ??? Fix-point here: what if we have something like "val a = foo {a.bar()}" // 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 { } else {
type = typeResolver.resolveType(scope, propertyTypeRef); type = typeResolver.resolveType(scope, propertyTypeRef);
@@ -590,6 +599,7 @@ public class ClassDescriptorResolver {
List<JetTypeReference> typeReferences = typeElement.getTypeArgumentsAsTypes(); List<JetTypeReference> typeReferences = typeElement.getTypeArgumentsAsTypes();
assert typeReferences.size() == arguments.size() : typeElement.getText(); assert typeReferences.size() == arguments.size() : typeElement.getText();
TypeSubstitutor substitutor = TypeSubstitutor.create(type);
for (int i = 0, projectionsSize = typeReferences.size(); i < projectionsSize; i++) { for (int i = 0, projectionsSize = typeReferences.size(); i < projectionsSize; i++) {
JetTypeReference argumentTypeReference = typeReferences.get(i); JetTypeReference argumentTypeReference = typeReferences.get(i);
@@ -599,14 +609,19 @@ public class ClassDescriptorResolver {
checkBounds(argumentTypeReference, typeArgument); checkBounds(argumentTypeReference, typeArgument);
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i); 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()) { for (JetType bound : typeParameterDescriptor.getUpperBounds()) {
if (!semanticServices.getTypeChecker().isSubtypeOf(typeArgument, bound)) { JetType substitutedBound = substitutor.safeSubstitute(bound, Variance.INVARIANT);
trace.getErrorHandler().genericError(argumentTypeReference.getNode(), "An upper bound " + bound + " is violated"); // TODO : Message 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 { public class TopDownAnalyzer {
private final Map<JetClass, MutableClassDescriptor> classes = Maps.newLinkedHashMap(); private final Map<JetClass, MutableClassDescriptor> classes = Maps.newLinkedHashMap();
private final Map<JetNamespace, WritableScope> namespaceScopes = new LinkedHashMap<JetNamespace, WritableScope>(); private final Map<JetNamespace, WritableScope> namespaceScopes = Maps.newHashMap();
private final Map<JetDeclaration, FunctionDescriptorImpl> functions = Maps.newLinkedHashMap(); 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<JetDeclaration, ConstructorDescriptor> constructors = Maps.newLinkedHashMap();
private final Map<JetProperty, PropertyDescriptor> properties = new LinkedHashMap<JetProperty, PropertyDescriptor>(); private final Map<JetProperty, PropertyDescriptor> properties = new LinkedHashMap<JetProperty, PropertyDescriptor>();
private final Map<JetDeclaration, JetScope> declaringScopes = Maps.newHashMap(); private final Map<JetDeclaration, JetScope> declaringScopes = Maps.newHashMap();
@@ -82,19 +84,24 @@ public class TopDownAnalyzer {
this(semanticServices, bindingTrace, JetControlFlowDataTraceFactory.EMPTY); this(semanticServices, bindingTrace, JetControlFlowDataTraceFactory.EMPTY);
} }
public void process(@NotNull JetScope outerScope, @NotNull JetDeclaration declaration) { // public void process(@NotNull JetScope outerScope, @NotNull JetDeclaration declaration) {
process(outerScope, Collections.singletonList(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 collectNamespacesAndClassifiers(outerScope, owner, declarations); // namespaceScopes, classes
createTypeConstructors(); // create type constructors for classes and generic parameters createTypeConstructors(); // create type constructors for classes and generic parameters
resolveTypesInClassHeaders(); // Generic bounds and types in supertype lists (no expressions or constructor resolution) resolveTypesInClassHeaders(); // Generic bounds and types in supertype lists (no expressions or constructor resolution)
checkGenericBoundsInClassHeaders(); // For the types resolved so far 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(); resolveExecutableCode();
// processBehaviorDeclarators(outerScope, declarations);
// readyToProcessExpressions = true;
// resolveBehaviorDeclarationBodies();
} }
private void collectNamespacesAndClassifiers( private void collectNamespacesAndClassifiers(
@@ -111,10 +118,10 @@ public class TopDownAnalyzer {
if (name == null) { if (name == null) {
name = "<no name provided>"; name = "<no name provided>";
} }
NamespaceDescriptor namespaceDescriptor = owner.getNamespace(name); NamespaceDescriptorImpl namespaceDescriptor = owner.getNamespace(name);
if (namespaceDescriptor == null) { if (namespaceDescriptor == null) {
namespaceDescriptor = new NamespaceDescriptor( namespaceDescriptor = new NamespaceDescriptorImpl(
owner, //declaringScope.getContainingDeclaration(), owner.getOriginal(), //declaringScope.getContainingDeclaration(),
Collections.<Annotation>emptyList(), // TODO Collections.<Annotation>emptyList(), // TODO
name name
); );
@@ -122,8 +129,9 @@ public class TopDownAnalyzer {
owner.addNamespace(namespaceDescriptor); owner.addNamespace(namespaceDescriptor);
trace.recordDeclarationResolution(namespace, 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); namespaceScopes.put(namespace, namespaceScope);
for (JetImportDirective importDirective : importDirectives) { for (JetImportDirective importDirective : importDirectives) {
@@ -143,23 +151,7 @@ public class TopDownAnalyzer {
} }
} }
final NamespaceDescriptor finalNamespaceDescriptor = namespaceDescriptor; collectNamespacesAndClassifiers(namespaceScope, namespaceDescriptor, namespace.getDeclarations());
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());
} }
@Override @Override
@@ -228,12 +220,53 @@ public class TopDownAnalyzer {
} }
private void resolveFunctionAndPropertyHeaders() { private void resolveFunctionAndPropertyHeaders(@NotNull List<JetDeclaration> declarations) {
throw new UnsupportedOperationException(); // TODO 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() { private void resolveExecutableCode() {
throw new UnsupportedOperationException(); // TODO readyToProcessExpressions = true;
resolveBehaviorDeclarationBodies();
} }
@NotNull @NotNull
@@ -263,9 +296,9 @@ public class TopDownAnalyzer {
if (name == null) { if (name == null) {
name = "<no name provided>"; name = "<no name provided>";
} }
NamespaceDescriptor namespaceDescriptor = declaringScope.getDeclaredNamespace(name); NamespaceDescriptorImpl namespaceDescriptor = (NamespaceDescriptorImpl) declaringScope.getDeclaredNamespace(name);
if (namespaceDescriptor == null) { if (namespaceDescriptor == null) {
namespaceDescriptor = new NamespaceDescriptor( namespaceDescriptor = new NamespaceDescriptorImpl(
declaringScope.getContainingDeclaration(), declaringScope.getContainingDeclaration(),
Collections.<Annotation>emptyList(), // TODO Collections.<Annotation>emptyList(), // TODO
name name
@@ -814,7 +847,7 @@ public class TopDownAnalyzer {
} }
private void resolveFunctionBodies() { private void resolveFunctionBodies() {
for (Map.Entry<JetDeclaration, FunctionDescriptorImpl> entry : functions.entrySet()) { for (Map.Entry<JetFunction, FunctionDescriptorImpl> entry : functions.entrySet()) {
JetDeclaration declaration = entry.getKey(); JetDeclaration declaration = entry.getKey();
FunctionDescriptor descriptor = entry.getValue(); FunctionDescriptor descriptor = entry.getValue();
@@ -92,17 +92,6 @@ public class TypeResolver {
trace.getErrorHandler().genericError(type.getTypeArgumentList().getNode(), errorMessage); trace.getErrorHandler().genericError(type.getTypeArgumentList().getNode(), errorMessage);
} }
} else { } 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( result[0] = new JetTypeImpl(
annotations, annotations,
typeConstructor, typeConstructor,
@@ -110,6 +99,18 @@ public class TypeResolver {
arguments, arguments,
classDescriptor.getMemberScope(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; package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.ErrorHandler; import org.jetbrains.jet.lang.ErrorHandler;
@@ -244,7 +245,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
@NotNull @NotNull
public Map<String, NamespaceDescriptor> getNamespaceDescriptors() { public Map<String, NamespaceDescriptor> getNamespaceDescriptors() {
if (namespaceDescriptors == null) { if (namespaceDescriptors == null) {
namespaceDescriptors = new HashMap<String, NamespaceDescriptor>(); namespaceDescriptors = Maps.newHashMap();
} }
return namespaceDescriptors; return namespaceDescriptors;
} }
@@ -189,23 +189,23 @@ public class JavaDescriptorResolver {
} }
private NamespaceDescriptor createJavaNamespaceDescriptor(PsiPackage psiPackage) { private NamespaceDescriptor createJavaNamespaceDescriptor(PsiPackage psiPackage) {
NamespaceDescriptor namespaceDescriptor = new NamespaceDescriptor( JavaNamespaceDescriptor namespaceDescriptor = new JavaNamespaceDescriptor(
JAVA_ROOT, JAVA_ROOT,
Collections.<Annotation>emptyList(), // TODO Collections.<Annotation>emptyList(), // TODO
psiPackage.getName() psiPackage.getName()
); );
namespaceDescriptor.initialize(new JavaPackageScope(psiPackage.getQualifiedName(), namespaceDescriptor, semanticServices)); namespaceDescriptor.setMemberScope(new JavaPackageScope(psiPackage.getQualifiedName(), namespaceDescriptor, semanticServices));
semanticServices.getTrace().recordDeclarationResolution(psiPackage, namespaceDescriptor); semanticServices.getTrace().recordDeclarationResolution(psiPackage, namespaceDescriptor);
return namespaceDescriptor; return namespaceDescriptor;
} }
private NamespaceDescriptor createJavaNamespaceDescriptor(@NotNull final PsiClass psiClass) { private NamespaceDescriptor createJavaNamespaceDescriptor(@NotNull final PsiClass psiClass) {
NamespaceDescriptor namespaceDescriptor = new NamespaceDescriptor( JavaNamespaceDescriptor namespaceDescriptor = new JavaNamespaceDescriptor(
JAVA_ROOT, JAVA_ROOT,
Collections.<Annotation>emptyList(), // TODO Collections.<Annotation>emptyList(), // TODO
psiClass.getName() psiClass.getName()
); );
namespaceDescriptor.initialize(new JavaClassMembersScope(namespaceDescriptor, psiClass, semanticServices, true)); namespaceDescriptor.setMemberScope(new JavaClassMembersScope(namespaceDescriptor, psiClass, semanticServices, true));
semanticServices.getTrace().recordDeclarationResolution(psiClass, namespaceDescriptor); semanticServices.getTrace().recordDeclarationResolution(psiClass, namespaceDescriptor);
return 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( private static final ClassDescriptor NOTHING_CLASS = new ClassDescriptorImpl(
STANDARD_CLASSES_NAMESPACE, 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.openapi.util.io.FileUtil;
import com.intellij.psi.PsiFileFactory; import com.intellij.psi.PsiFileFactory;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.ErrorHandler;
import org.jetbrains.jet.lang.JetFileType; import org.jetbrains.jet.lang.JetFileType;
import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.Annotation; import org.jetbrains.jet.lang.descriptors.Annotation;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -73,7 +72,11 @@ public class JetStandardLibrary {
JetSemanticServices bootstrappingSemanticServices = JetSemanticServices.createSemanticServices(this); JetSemanticServices bootstrappingSemanticServices = JetSemanticServices.createSemanticServices(this);
BindingTraceContext bindingTraceContext = new BindingTraceContext(); BindingTraceContext bindingTraceContext = new BindingTraceContext();
TopDownAnalyzer bootstrappingTDA = new TopDownAnalyzer(bootstrappingSemanticServices, 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.byteClass = (ClassDescriptor) libraryScope.getClassifier("Byte");
this.charClass = (ClassDescriptor) libraryScope.getClassifier("Char"); this.charClass = (ClassDescriptor) libraryScope.getClassifier("Char");
@@ -594,6 +594,7 @@ public class JetTypeInferrer {
@Nullable @Nullable
public JetType getType(@NotNull JetExpression expression) { public JetType getType(@NotNull JetExpression expression) {
assert result == null; assert result == null;
try {
expression.accept(this); expression.accept(this);
if (result != null) { if (result != null) {
trace.recordExpressionType(expression, result); trace.recordExpressionType(expression, result);
@@ -601,6 +602,11 @@ public class JetTypeInferrer {
markDominatedExpressionsAsUnreachable(expression); markDominatedExpressionsAsUnreachable(expression);
} }
} }
}
catch (ReenteringLazyValueComputationException e) {
trace.getErrorHandler().genericError(expression.getNode(), "Type inference has run into a recursive problem"); // TODO : message
result = null;
}
return result; 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 A
class B<T : A>() class B<T : A>()