JET-26 Check bounds in generic types: fixed substitution problems
This commit is contained in:
+11
-12
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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>()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user