Scope filtering according to type projections supported
This commit is contained in:
Generated
+1
@@ -3,6 +3,7 @@
|
||||
<words>
|
||||
<w>inferrer</w>
|
||||
<w>nullable</w>
|
||||
<w>substitutor</w>
|
||||
<w>subtyping</w>
|
||||
<w>supertype</w>
|
||||
<w>supertypes</w>
|
||||
|
||||
@@ -7,10 +7,7 @@ import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -222,7 +219,7 @@ public class ClassDescriptorResolver {
|
||||
}
|
||||
|
||||
public List<TypeParameterDescriptor> resolveTypeParameters(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, List<JetTypeParameter> typeParameters) {
|
||||
// TODO : When-clause
|
||||
// TODO : Where-clause
|
||||
List<TypeParameterDescriptor> result = new ArrayList<TypeParameterDescriptor>();
|
||||
for (JetTypeParameter typeParameter : typeParameters) {
|
||||
result.add(resolveTypeParameter(containingDescriptor, extensibleScope, typeParameter));
|
||||
@@ -231,15 +228,18 @@ public class ClassDescriptorResolver {
|
||||
}
|
||||
|
||||
private TypeParameterDescriptor resolveTypeParameter(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, JetTypeParameter typeParameter) {
|
||||
// TODO: other bounds from where-clause
|
||||
JetTypeReference extendsBound = typeParameter.getExtendsBound();
|
||||
JetType bound = extendsBound == null
|
||||
? JetStandardClasses.getDefaultBound()
|
||||
: typeResolver.resolveType(extensibleScope, extendsBound);
|
||||
TypeParameterDescriptor typeParameterDescriptor = new TypeParameterDescriptor(
|
||||
containingDescriptor,
|
||||
AttributeResolver.INSTANCE.resolveAttributes(typeParameter.getModifierList()),
|
||||
typeParameter.getVariance(),
|
||||
typeParameter.getName(),
|
||||
extendsBound == null
|
||||
? Collections.<JetType>singleton(JetStandardClasses.getDefaultBound())
|
||||
: Collections.singleton(typeResolver.resolveType(extensibleScope, extendsBound))
|
||||
Collections.singleton(bound),
|
||||
bound
|
||||
);
|
||||
extensibleScope.addTypeParameterDescriptor(typeParameterDescriptor);
|
||||
trace.recordDeclarationResolution(typeParameter, typeParameterDescriptor);
|
||||
|
||||
@@ -38,6 +38,12 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
|
||||
return new SubstitutingScope(memberScope, substitutionContext);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType getDefaultType() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionGroup getConstructors(List<TypeProjection> typeArguments) {
|
||||
|
||||
@@ -35,10 +35,16 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
||||
@Override
|
||||
public JetScope getMemberScope(List<TypeProjection> typeArguments) {
|
||||
List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters();
|
||||
Map<TypeConstructor,TypeProjection> substitutionContext = TypeSubstitutor.INSTANCE.buildSubstitutionContext(typeParameters, typeArguments);
|
||||
Map<TypeConstructor,TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(typeParameters, typeArguments);
|
||||
return new SubstitutingScope(unsubstitutedMemberScope, substitutionContext);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType getDefaultType() {
|
||||
return TypeUtils.makeUnsubstitutedType(this, unsubstitutedMemberScope);
|
||||
}
|
||||
|
||||
public void addConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
|
||||
assert constructorDescriptor.getContainingDeclaration() == this;
|
||||
constructors.addFunction(constructorDescriptor);
|
||||
@@ -49,11 +55,12 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
||||
public FunctionGroup getConstructors(List<TypeProjection> typeArguments) {
|
||||
// TODO : Duplicates ClassDescriptorImpl
|
||||
assert typeArguments.size() == getTypeConstructor().getParameters().size();
|
||||
|
||||
if (typeArguments.size() == 0) {
|
||||
return constructors;
|
||||
}
|
||||
Map<TypeConstructor, TypeProjection> substitutionContext = TypeSubstitutor.INSTANCE.buildSubstitutionContext(getTypeConstructor().getParameters(), typeArguments);
|
||||
return new LazySubstitutingFunctionGroup(substitutionContext, constructors);
|
||||
Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(getTypeConstructor().getParameters(), typeArguments);
|
||||
return new LazySubstitutingFunctionGroup(substitutionContext, constructors, TypeSubstitutor.INSTANCE_FOR_CONSTRUCTORS);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.jetbrains.jet.lang.types.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -148,8 +147,8 @@ public class TypeResolver {
|
||||
JetProjectionKind projectionKind = argumentElement.getProjectionKind();
|
||||
JetType type;
|
||||
if (projectionKind == JetProjectionKind.STAR) {
|
||||
Set<JetType> upperBounds = constructor.getParameters().get(i).getUpperBounds();
|
||||
arguments.add(new TypeProjection(Variance.OUT_VARIANCE, TypeUtils.intersect(semanticServices.getTypeChecker(), upperBounds)));
|
||||
TypeParameterDescriptor parameterDescriptor = constructor.getParameters().get(i);
|
||||
arguments.add(TypeUtils.makeStarProjection(parameterDescriptor));
|
||||
}
|
||||
else {
|
||||
// TODO : handle the Foo<in *> case
|
||||
|
||||
@@ -59,7 +59,9 @@ public class WritableFunctionGroup implements FunctionGroup {
|
||||
if (functionDescriptor.getTypeParameters().size() == typeArgCount) {
|
||||
if (FunctionDescriptorUtil.getMinimumArity(functionDescriptor) <= valueArgCount &&
|
||||
valueArgCount <= FunctionDescriptorUtil.getMaximumArity(functionDescriptor)) {
|
||||
result.add(FunctionDescriptorUtil.substituteFunctionDescriptor(typeArguments, functionDescriptor));
|
||||
FunctionDescriptor substitutedFunctionDescriptor = FunctionDescriptorUtil.substituteFunctionDescriptor(typeArguments, functionDescriptor);
|
||||
assert substitutedFunctionDescriptor != null;
|
||||
result.add(substitutedFunctionDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,4 +21,10 @@ public interface ClassDescriptor extends DeclarationDescriptor {
|
||||
@Override
|
||||
@NotNull
|
||||
DeclarationDescriptor getContainingDeclaration();
|
||||
|
||||
/**
|
||||
* @return type A<T> for the class A<T>
|
||||
*/
|
||||
@NotNull
|
||||
JetType getDefaultType();
|
||||
}
|
||||
|
||||
@@ -24,13 +24,6 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
|
||||
super(containingDeclaration, attributes, name);
|
||||
}
|
||||
|
||||
// public ClassDescriptorImpl(@NotNull DeclarationDescriptor containingDeclaration, String name, JetScope memberDeclarations) {
|
||||
// this(containingDeclaration, Collections.<Attribute>emptyList(), name);
|
||||
// this.initialize(Collections.<Attribute>emptyList(), true,
|
||||
// name, Collections.<TypeParameterDescriptor>emptyList(),
|
||||
// Collections.<Type>singleton(JetStandardClasses.getAnyType()), memberDeclarations);
|
||||
// }
|
||||
//
|
||||
public final ClassDescriptorImpl initialize(boolean sealed,
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||
@NotNull Collection<? extends JetType> superclasses,
|
||||
@@ -55,10 +48,16 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
|
||||
if (typeConstructor.getParameters().isEmpty()) {
|
||||
return memberDeclarations;
|
||||
}
|
||||
Map<TypeConstructor, TypeProjection> substitutionContext = TypeSubstitutor.INSTANCE.buildSubstitutionContext(typeConstructor.getParameters(), typeArguments);
|
||||
Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(typeConstructor.getParameters(), typeArguments);
|
||||
return new SubstitutingScope(memberDeclarations, substitutionContext);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType getDefaultType() {
|
||||
return TypeUtils.makeUnsubstitutedType(this, memberDeclarations);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionGroup getConstructors(List<TypeProjection> typeArguments) {
|
||||
@@ -66,8 +65,8 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
|
||||
if (typeArguments.size() == 0) {
|
||||
return constructors;
|
||||
}
|
||||
Map<TypeConstructor, TypeProjection> substitutionContext = TypeSubstitutor.INSTANCE.buildSubstitutionContext(getTypeConstructor().getParameters(), typeArguments);
|
||||
return new LazySubstitutingFunctionGroup(substitutionContext, constructors);
|
||||
Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(getTypeConstructor().getParameters(), typeArguments);
|
||||
return new LazySubstitutingFunctionGroup(substitutionContext, constructors, TypeSubstitutor.INSTANCE_FOR_CONSTRUCTORS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -64,6 +64,6 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType getUnsubstitutedReturnType() {
|
||||
return TypeUtils.makeUnsubstitutedType(getContainingDeclaration());
|
||||
return getContainingDeclaration().getDefaultType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,6 +179,10 @@ public class ErrorType {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return constructor.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private ErrorType() {}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -37,29 +38,9 @@ public class FunctionDescriptorUtil {
|
||||
return unsubstitutedValueParameters.size();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<ValueParameterDescriptor> getSubstitutedValueParameters(FunctionDescriptor substitutedDescriptor, @NotNull FunctionDescriptor functionDescriptor, @NotNull List<JetType> typeArguments) {
|
||||
// TODO : Review, maybe duplicates LazySubstitutingFunctionDescriptor
|
||||
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
|
||||
Map<TypeConstructor, TypeProjection> context = createSubstitutionContext(functionDescriptor, typeArguments);
|
||||
List<ValueParameterDescriptor> unsubstitutedValueParameters = functionDescriptor.getUnsubstitutedValueParameters();
|
||||
for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
|
||||
ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i);
|
||||
// TODO : Lazy?
|
||||
result.add(new ValueParameterDescriptorImpl(
|
||||
substitutedDescriptor,
|
||||
i,
|
||||
unsubstitutedValueParameter.getAttributes(),
|
||||
unsubstitutedValueParameter.getName(),
|
||||
TypeSubstitutor.INSTANCE.substitute(context, unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE),
|
||||
unsubstitutedValueParameter.hasDefaultValue(),
|
||||
unsubstitutedValueParameter.isVararg()
|
||||
));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Map<TypeConstructor, TypeProjection> createSubstitutionContext(@NotNull FunctionDescriptor functionDescriptor, List<JetType> typeArguments) {
|
||||
if (functionDescriptor.getTypeParameters().isEmpty()) return Collections.emptyMap();
|
||||
|
||||
Map<TypeConstructor, TypeProjection> result = new HashMap<TypeConstructor, TypeProjection>();
|
||||
|
||||
int typeArgumentsSize = typeArguments.size();
|
||||
@@ -73,26 +54,64 @@ public class FunctionDescriptorUtil {
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetType getSubstitutedReturnType(@NotNull FunctionDescriptor functionDescriptor, @NotNull List<JetType> typeArguments) {
|
||||
// TODO : Review, maybe duplicates LazySubstitutingFunctionDescriptor
|
||||
return TypeSubstitutor.INSTANCE.substitute(createSubstitutionContext(functionDescriptor, typeArguments), functionDescriptor.getUnsubstitutedReturnType(), Variance.OUT_VARIANCE);
|
||||
@Nullable
|
||||
private static List<ValueParameterDescriptor> getSubstitutedValueParameters(FunctionDescriptor substitutedDescriptor, @NotNull FunctionDescriptor functionDescriptor, Map<TypeConstructor, TypeProjection> substitutionContext, TypeSubstitutor typeSubstitutor) {
|
||||
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
|
||||
List<ValueParameterDescriptor> unsubstitutedValueParameters = functionDescriptor.getUnsubstitutedValueParameters();
|
||||
for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
|
||||
ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i);
|
||||
// TODO : Lazy?
|
||||
JetType substitutedType = typeSubstitutor.substitute(substitutionContext, unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE);
|
||||
if (substitutedType == null) return null;
|
||||
result.add(new ValueParameterDescriptorImpl(
|
||||
substitutedDescriptor,
|
||||
i,
|
||||
unsubstitutedValueParameter.getAttributes(),
|
||||
unsubstitutedValueParameter.getName(),
|
||||
substitutedType,
|
||||
unsubstitutedValueParameter.hasDefaultValue(),
|
||||
unsubstitutedValueParameter.isVararg()
|
||||
));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
private static JetType getSubstitutedReturnType(@NotNull FunctionDescriptor functionDescriptor, Map<TypeConstructor, TypeProjection> substitutionContext, TypeSubstitutor typeSubstitutor) {
|
||||
return typeSubstitutor.substitute(substitutionContext, functionDescriptor.getUnsubstitutedReturnType(), Variance.OUT_VARIANCE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static FunctionDescriptor substituteFunctionDescriptor(@NotNull List<JetType> typeArguments, @NotNull FunctionDescriptor functionDescriptor) {
|
||||
if (functionDescriptor.getTypeParameters().isEmpty()) {
|
||||
Map<TypeConstructor, TypeProjection> substitutionContext = createSubstitutionContext(functionDescriptor, typeArguments);
|
||||
return substituteFunctionDescriptor(functionDescriptor, substitutionContext, TypeSubstitutor.INSTANCE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static FunctionDescriptor substituteFunctionDescriptor(FunctionDescriptor functionDescriptor, Map<TypeConstructor, TypeProjection> substitutionContext, TypeSubstitutor typeSubstitutor) {
|
||||
if (substitutionContext.isEmpty()) {
|
||||
return functionDescriptor;
|
||||
}
|
||||
FunctionDescriptorImpl substitutedDescriptor = new FunctionDescriptorImpl(
|
||||
functionDescriptor,
|
||||
// TODO : substitute
|
||||
// TODO : safeSubstitute
|
||||
functionDescriptor.getAttributes(),
|
||||
functionDescriptor.getName());
|
||||
|
||||
List<ValueParameterDescriptor> substitutedValueParameters = getSubstitutedValueParameters(substitutedDescriptor, functionDescriptor, substitutionContext, typeSubstitutor);
|
||||
if (substitutedValueParameters == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JetType substitutedReturnType = getSubstitutedReturnType(functionDescriptor, substitutionContext, typeSubstitutor);
|
||||
if (substitutedReturnType == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
substitutedDescriptor.initialize(
|
||||
Collections.<TypeParameterDescriptor>emptyList(), // TODO : questionable
|
||||
getSubstitutedValueParameters(substitutedDescriptor, functionDescriptor, typeArguments),
|
||||
getSubstitutedReturnType(functionDescriptor, typeArguments)
|
||||
substitutedValueParameters,
|
||||
substitutedReturnType
|
||||
);
|
||||
return substitutedDescriptor;
|
||||
}
|
||||
|
||||
@@ -94,8 +94,7 @@ public class JetStandardClasses {
|
||||
parameters.add(new TypeParameterDescriptor(
|
||||
classDescriptor,
|
||||
Collections.<Attribute>emptyList(),
|
||||
Variance.OUT_VARIANCE, "T" + j,
|
||||
Collections.singleton(getNullableAnyType())));
|
||||
Variance.OUT_VARIANCE, "T" + j));
|
||||
}
|
||||
TUPLE[i] = classDescriptor.initialize(
|
||||
true,
|
||||
@@ -132,8 +131,7 @@ public class JetStandardClasses {
|
||||
parameters.add(0, new TypeParameterDescriptor(
|
||||
receiverFunction,
|
||||
Collections.<Attribute>emptyList(),
|
||||
Variance.IN_VARIANCE, "T",
|
||||
Collections.singleton(getNullableAnyType())));
|
||||
Variance.IN_VARIANCE, "T"));
|
||||
RECEIVER_FUNCTION[i] = receiverFunction.initialize(
|
||||
false,
|
||||
parameters,
|
||||
@@ -147,14 +145,12 @@ public class JetStandardClasses {
|
||||
parameters.add(new TypeParameterDescriptor(
|
||||
function,
|
||||
Collections.<Attribute>emptyList(),
|
||||
Variance.IN_VARIANCE, "P" + j,
|
||||
Collections.singleton(getNullableAnyType())));
|
||||
Variance.IN_VARIANCE, "P" + j));
|
||||
}
|
||||
parameters.add(new TypeParameterDescriptor(
|
||||
function,
|
||||
Collections.<Attribute>emptyList(),
|
||||
Variance.OUT_VARIANCE, "R",
|
||||
Collections.singleton(getNullableAnyType())));
|
||||
Variance.OUT_VARIANCE, "R"));
|
||||
return parameters;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ public class JetTypeChecker {
|
||||
}
|
||||
commonSupertypes = computeCommonRawSupertypes(merge);
|
||||
}
|
||||
assert !commonSupertypes.isEmpty();
|
||||
assert !commonSupertypes.isEmpty() : commonSupertypes;
|
||||
Map.Entry<TypeConstructor, Set<JetType>> entry = commonSupertypes.entrySet().iterator().next();
|
||||
JetType result = computeSupertypeProjections(entry.getKey(), entry.getValue());
|
||||
|
||||
@@ -274,13 +274,13 @@ public class JetTypeChecker {
|
||||
return;
|
||||
}
|
||||
handler.beforeChildren(current);
|
||||
Map<TypeConstructor, TypeProjection> substitutionContext = TypeSubstitutor.INSTANCE.buildSubstitutionContext(current);
|
||||
Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(current);
|
||||
for (JetType supertype : current.getConstructor().getSupertypes()) {
|
||||
TypeConstructor supertypeConstructor = supertype.getConstructor();
|
||||
if (visited.contains(supertypeConstructor)) {
|
||||
continue;
|
||||
}
|
||||
JetType substitutedSupertype = TypeSubstitutor.INSTANCE.substitute(substitutionContext, supertype, Variance.INVARIANT);
|
||||
JetType substitutedSupertype = TypeSubstitutor.INSTANCE.safeSubstitute(substitutionContext, supertype, Variance.INVARIANT);
|
||||
dfs(substitutedSupertype, visited, handler);
|
||||
}
|
||||
handler.afterChildren(current);
|
||||
@@ -331,7 +331,7 @@ public class JetTypeChecker {
|
||||
for (JetType immediateSupertype : constructor.getSupertypes()) {
|
||||
JetType correspondingSupertype = findCorrespondingSupertype(immediateSupertype, supertype);
|
||||
if (correspondingSupertype != null) {
|
||||
return TypeSubstitutor.INSTANCE.substitute(subtype, correspondingSupertype, Variance.INVARIANT);
|
||||
return TypeSubstitutor.INSTANCE.safeSubstitute(subtype, correspondingSupertype, Variance.INVARIANT);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -339,7 +339,7 @@ public class JetTypeChecker {
|
||||
|
||||
private boolean checkSubtypeForTheSameConstructor(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
TypeConstructor constructor = subtype.getConstructor();
|
||||
assert constructor.equals(supertype.getConstructor());
|
||||
assert constructor.equals(supertype.getConstructor()) : constructor + " is not " + supertype.getConstructor();
|
||||
|
||||
List<TypeProjection> subArguments = subtype.getArguments();
|
||||
List<TypeProjection> superArguments = supertype.getArguments();
|
||||
|
||||
@@ -499,10 +499,10 @@ public class JetTypeInferrer {
|
||||
JetUserType typeElement = (JetUserType) superTypeQualifier.getTypeElement();
|
||||
ClassDescriptor superclass = typeResolver.resolveClass(scope, typeElement);
|
||||
Collection<? extends JetType> supertypes = thisType.getConstructor().getSupertypes();
|
||||
Map<TypeConstructor, TypeProjection> substitutionContext = TypeSubstitutor.INSTANCE.buildSubstitutionContext(thisType);
|
||||
Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(thisType);
|
||||
for (JetType declaredSupertype : supertypes) {
|
||||
if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) {
|
||||
result = TypeSubstitutor.INSTANCE.substitute(substitutionContext, declaredSupertype, Variance.INVARIANT);
|
||||
result = TypeSubstitutor.INSTANCE.safeSubstitute(substitutionContext, declaredSupertype, Variance.INVARIANT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public class LazySubstitutedPropertyDescriptorImpl implements PropertyDescriptor
|
||||
@Override
|
||||
public JetType getType() {
|
||||
if (propertyType == null) {
|
||||
propertyType = TypeSubstitutor.INSTANCE.substitute(substitutionContext, propertyDescriptor.getType(), Variance.OUT_VARIANCE);
|
||||
propertyType = TypeSubstitutor.INSTANCE.safeSubstitute(substitutionContext, propertyDescriptor.getType(), Variance.OUT_VARIANCE);
|
||||
}
|
||||
return propertyType;
|
||||
}
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class LazySubstitutingFunctionDescriptor implements FunctionDescriptor {
|
||||
private final Map<TypeConstructor, TypeProjection> substitutionContext;
|
||||
private final FunctionDescriptor functionDescriptor;
|
||||
|
||||
public LazySubstitutingFunctionDescriptor(Map<TypeConstructor, TypeProjection> substitutionContext, FunctionDescriptor functionDescriptor) {
|
||||
this.substitutionContext = substitutionContext;
|
||||
this.functionDescriptor = functionDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<TypeParameterDescriptor> getTypeParameters() {
|
||||
List<TypeParameterDescriptor> result = new ArrayList<TypeParameterDescriptor>();
|
||||
for (TypeParameterDescriptor parameterDescriptor : functionDescriptor.getTypeParameters()) {
|
||||
// TODO : lazy?
|
||||
result.add(new TypeParameterDescriptor(
|
||||
this,
|
||||
parameterDescriptor.getAttributes(),
|
||||
parameterDescriptor.getVariance(),
|
||||
parameterDescriptor.getName(),
|
||||
TypeSubstitutor.INSTANCE.substituteInSet(substitutionContext, parameterDescriptor.getUpperBounds(), Variance.INVARIANT)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<ValueParameterDescriptor> getUnsubstitutedValueParameters() {
|
||||
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
|
||||
List<ValueParameterDescriptor> unsubstitutedValueParameters = functionDescriptor.getUnsubstitutedValueParameters();
|
||||
for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
|
||||
ValueParameterDescriptor parameterDescriptor = unsubstitutedValueParameters.get(i);
|
||||
result.add(new ValueParameterDescriptorImpl(
|
||||
this,
|
||||
i,
|
||||
parameterDescriptor.getAttributes(),
|
||||
parameterDescriptor.getName(),
|
||||
TypeSubstitutor.INSTANCE.substitute(substitutionContext, parameterDescriptor.getType(), Variance.IN_VARIANCE),
|
||||
parameterDescriptor.hasDefaultValue(),
|
||||
parameterDescriptor.isVararg()
|
||||
));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType getUnsubstitutedReturnType() {
|
||||
return TypeSubstitutor.INSTANCE.substitute(substitutionContext, functionDescriptor.getUnsubstitutedReturnType(), Variance.OUT_VARIANCE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionDescriptor getOriginal() {
|
||||
return functionDescriptor.getOriginal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Attribute> getAttributes() {
|
||||
// TODO : Substitute?
|
||||
return functionDescriptor.getAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return functionDescriptor.getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DeclarationDescriptor getContainingDeclaration() {
|
||||
return functionDescriptor.getContainingDeclaration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitFunctionDescriptor(this, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
|
||||
accept(visitor, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.resolve.OverloadResolutionResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -14,10 +15,16 @@ import java.util.Map;
|
||||
public class LazySubstitutingFunctionGroup implements FunctionGroup {
|
||||
private final Map<TypeConstructor, TypeProjection> substitutionContext;
|
||||
private final FunctionGroup functionGroup;
|
||||
private final TypeSubstitutor typeSubstitutor;
|
||||
|
||||
public LazySubstitutingFunctionGroup(Map<TypeConstructor, TypeProjection> substitutionContext, FunctionGroup functionGroup) {
|
||||
public LazySubstitutingFunctionGroup(Map<TypeConstructor, TypeProjection> substitutionContext, FunctionGroup functionGroup, TypeSubstitutor typeSubstitutor) {
|
||||
this.substitutionContext = substitutionContext;
|
||||
this.functionGroup = functionGroup;
|
||||
this.typeSubstitutor = typeSubstitutor;
|
||||
}
|
||||
|
||||
public LazySubstitutingFunctionGroup(Map<TypeConstructor, TypeProjection> substitutionContext, FunctionGroup functionGroup) {
|
||||
this(substitutionContext, functionGroup, TypeSubstitutor.INSTANCE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -34,15 +41,27 @@ public class LazySubstitutingFunctionGroup implements FunctionGroup {
|
||||
|
||||
Collection<FunctionDescriptor> result = new ArrayList<FunctionDescriptor>();
|
||||
for (FunctionDescriptor function : resolutionResult.getFunctionDescriptors()) {
|
||||
if (substitutionContext.isEmpty()) {
|
||||
result.add(function);
|
||||
} else {
|
||||
result.add(new LazySubstitutingFunctionDescriptor(substitutionContext, function));
|
||||
FunctionDescriptor functionDescriptor = substitute(substitutionContext, function, typeSubstitutor);
|
||||
if (functionDescriptor != null) {
|
||||
result.add(functionDescriptor);
|
||||
}
|
||||
}
|
||||
return resolutionResult.newContents(result);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FunctionDescriptor substitute(
|
||||
@NotNull Map<TypeConstructor, TypeProjection> substitutionContext,
|
||||
@NotNull FunctionDescriptor functionDescriptor, TypeSubstitutor typeSubstitutor) {
|
||||
if (substitutionContext.isEmpty()) return functionDescriptor;
|
||||
|
||||
FunctionDescriptor substituted = FunctionDescriptorUtil.substituteFunctionDescriptor(functionDescriptor, substitutionContext, typeSubstitutor);
|
||||
if (substituted == null) {
|
||||
return null;
|
||||
}
|
||||
return substituted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return functionGroup.isEmpty();
|
||||
|
||||
@@ -13,8 +13,15 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl {
|
||||
private final Variance variance;
|
||||
private final Set<JetType> upperBounds;
|
||||
private final TypeConstructor typeConstructor;
|
||||
private final JetType boundsAsType;
|
||||
|
||||
public TypeParameterDescriptor(@NotNull DeclarationDescriptor containingDeclaration, List<Attribute> attributes, Variance variance, String name, Set<JetType> upperBounds) {
|
||||
public TypeParameterDescriptor(
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@NotNull List<Attribute> attributes,
|
||||
@NotNull Variance variance,
|
||||
@NotNull String name,
|
||||
@NotNull Set<JetType> upperBounds,
|
||||
@NotNull JetType boundsAsType) {
|
||||
super(containingDeclaration, attributes, name);
|
||||
this.variance = variance;
|
||||
this.upperBounds = upperBounds;
|
||||
@@ -26,10 +33,21 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl {
|
||||
"&" + name,
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
upperBounds);
|
||||
this.boundsAsType = boundsAsType;
|
||||
}
|
||||
|
||||
public TypeParameterDescriptor(@NotNull DeclarationDescriptor containingDeclaration, List<Attribute> attributes, Variance variance, String name) {
|
||||
this(containingDeclaration, attributes, variance, name, Collections.singleton(JetStandardClasses.getNullableAnyType()));
|
||||
public TypeParameterDescriptor(
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@NotNull List<Attribute> attributes,
|
||||
@NotNull Variance variance,
|
||||
@NotNull String name) {
|
||||
this(
|
||||
containingDeclaration,
|
||||
attributes,
|
||||
variance,
|
||||
name,
|
||||
Collections.singleton(JetStandardClasses.getNullableAnyType()),
|
||||
JetStandardClasses.getNullableAnyType());
|
||||
}
|
||||
|
||||
public Variance getVariance() {
|
||||
@@ -49,6 +67,11 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl {
|
||||
return typeConstructor.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetType getBoundsAsType() {
|
||||
return boundsAsType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||
return visitor.visitTypeParameterDescriptor(this, data);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.resolve.SubstitutingScope;
|
||||
|
||||
import java.util.*;
|
||||
@@ -9,75 +10,135 @@ import java.util.*;
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TypeSubstitutor {
|
||||
|
||||
public static final class SubstitutionException extends Exception {
|
||||
public SubstitutionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static final TypeSubstitutor INSTANCE = new TypeSubstitutor();
|
||||
|
||||
public static final TypeSubstitutor INSTANCE_FOR_CONSTRUCTORS = new TypeSubstitutor() {
|
||||
@Override
|
||||
protected boolean errorCondition(Variance ve, Variance p1) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
private TypeSubstitutor() {}
|
||||
|
||||
public JetType substitute(@NotNull JetType context, @NotNull JetType subject, @NotNull Variance howThisTypeIsUsed) {
|
||||
return substitute(buildSubstitutionContext(context), subject, howThisTypeIsUsed);
|
||||
public JetType safeSubstitute(@NotNull JetType context, @NotNull JetType subject, @NotNull Variance howThisTypeIsUsed) {
|
||||
return safeSubstitute(TypeUtils.buildSubstitutionContext(context), subject, howThisTypeIsUsed);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetType safeSubstitute(@NotNull Map<TypeConstructor, TypeProjection> substitutionContext, @NotNull JetType type, @NotNull Variance howThisTypeIsUsed) {
|
||||
try {
|
||||
return unsafeSubstitute(substitutionContext, type, howThisTypeIsUsed);
|
||||
} catch (SubstitutionException e) {
|
||||
return ErrorType.createErrorType(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetType substitute(@NotNull Map<TypeConstructor, TypeProjection> substitutionContext, @NotNull JetType type, @NotNull Variance howThisTypeIsUsed) {
|
||||
TypeProjection value = substitutionContext.get(type.getConstructor());
|
||||
try {
|
||||
return unsafeSubstitute(substitutionContext, type, howThisTypeIsUsed);
|
||||
} catch (SubstitutionException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JetType unsafeSubstitute(@NotNull Map<TypeConstructor, TypeProjection> substitutionContext, @NotNull JetType type, @NotNull Variance howThisTypeIsUsed) throws SubstitutionException {
|
||||
TypeConstructor constructor = type.getConstructor();
|
||||
TypeProjection value = substitutionContext.get(constructor);
|
||||
if (value != null) {
|
||||
Variance projectionKind = value.getProjectionKind();
|
||||
if (howThisTypeIsUsed.allowsInPosition() && !projectionKind.allowsInPosition()
|
||||
|| howThisTypeIsUsed.allowsOutPosition() && !projectionKind.allowsOutPosition()) {
|
||||
return ErrorType.createWrongVarianceErrorType(value);
|
||||
assert constructor.getDeclarationDescriptor() instanceof TypeParameterDescriptor;
|
||||
|
||||
if (errorCondition(howThisTypeIsUsed, value.getProjectionKind())) {
|
||||
throw new SubstitutionException("!!" + value.toString());
|
||||
}
|
||||
return value.getType();
|
||||
}
|
||||
|
||||
return specializeType(type, substitutionContext);
|
||||
return specializeType(type, substitutionContext, howThisTypeIsUsed);
|
||||
}
|
||||
|
||||
private JetType specializeType(JetType subjectType, Map<TypeConstructor, TypeProjection> substitutionContext) {
|
||||
private JetType specializeType(JetType subjectType, Map<TypeConstructor, TypeProjection> substitutionContext, Variance callSiteVariance) throws SubstitutionException {
|
||||
List<TypeProjection> newArguments = new ArrayList<TypeProjection>();
|
||||
List<TypeProjection> arguments = subjectType.getArguments();
|
||||
for (int i = 0, argumentsSize = arguments.size(); i < argumentsSize; i++) {
|
||||
TypeProjection argument = arguments.get(i);
|
||||
TypeParameterDescriptor parameterDescriptor = subjectType.getConstructor().getParameters().get(i);
|
||||
newArguments.add(substituteInProjection(
|
||||
substitutionContext,
|
||||
argument,
|
||||
parameterDescriptor,
|
||||
callSiteVariance));
|
||||
}
|
||||
return new JetTypeImpl(
|
||||
subjectType.getAttributes(),
|
||||
subjectType.getConstructor(),
|
||||
subjectType.isNullable(),
|
||||
substituteInArguments(substitutionContext, subjectType),
|
||||
newArguments,
|
||||
new SubstitutingScope(subjectType.getMemberScope(), substitutionContext));
|
||||
}
|
||||
|
||||
private List<TypeProjection> substituteInArguments(Map<TypeConstructor, TypeProjection> substitutionContext, JetType subjectType) {
|
||||
List<TypeProjection> newArguments = new ArrayList<TypeProjection>();
|
||||
for (TypeProjection argument : subjectType.getArguments()) {
|
||||
newArguments.add(substituteInProjection(substitutionContext, argument));
|
||||
@NotNull
|
||||
private TypeProjection substituteInProjection(
|
||||
@NotNull Map<TypeConstructor, TypeProjection> substitutionContext,
|
||||
@NotNull TypeProjection p0_E,
|
||||
@NotNull TypeParameterDescriptor d_T, // variance of the parameter this projection is substituted for
|
||||
@NotNull Variance v) throws SubstitutionException {
|
||||
JetType E = p0_E.getType();
|
||||
Variance p0 = p0_E.getProjectionKind();
|
||||
Variance d = d_T.getVariance();
|
||||
|
||||
Variance p01 = (p0 == Variance.INVARIANT) ? d : p0;
|
||||
Variance ve = v.superpose(p01);
|
||||
|
||||
TypeProjection p1_A = substitutionContext.get(E.getConstructor());
|
||||
if (p1_A != null) {
|
||||
assert E.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor;
|
||||
|
||||
JetType A = p1_A.getType();
|
||||
Variance p1 = p1_A.getProjectionKind();
|
||||
|
||||
if (!allows(d, p0)) {
|
||||
return TypeUtils.makeStarProjection(d_T);
|
||||
}
|
||||
|
||||
if (errorCondition(ve, p1)) {
|
||||
throw new SubstitutionException(""); // TODO : error message
|
||||
}
|
||||
|
||||
return new TypeProjection(p0 == Variance.INVARIANT ? p1 : p0, specializeType(A, substitutionContext, ve));
|
||||
}
|
||||
return newArguments;
|
||||
return new TypeProjection(
|
||||
p0,
|
||||
specializeType(E, substitutionContext, ve));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private TypeProjection substituteInProjection(Map<TypeConstructor, TypeProjection> substitutionContext, TypeProjection subject) {
|
||||
JetType subjectType = subject.getType();
|
||||
TypeProjection value = substitutionContext.get(subjectType.getConstructor());
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
return new TypeProjection(subject.getProjectionKind(), specializeType(subjectType, substitutionContext));
|
||||
protected boolean errorCondition(Variance ve, Variance p1) {
|
||||
return !allows(ve, p1);
|
||||
}
|
||||
|
||||
public Set<JetType> substituteInSet(Map<TypeConstructor, TypeProjection> substitutionContext, Set<JetType> types, Variance howTheseTypesWillBeUsed) {
|
||||
Set<JetType> result = new HashSet<JetType>();
|
||||
for (JetType type : types) {
|
||||
result.add(substitute(substitutionContext, type, howTheseTypesWillBeUsed));
|
||||
result.add(safeSubstitute(substitutionContext, type, howTheseTypesWillBeUsed));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Map<TypeConstructor, TypeProjection> buildSubstitutionContext(JetType context) {
|
||||
return buildSubstitutionContext(context.getConstructor().getParameters(), context.getArguments());
|
||||
}
|
||||
|
||||
public Map<TypeConstructor, TypeProjection> buildSubstitutionContext(List<TypeParameterDescriptor> parameters, List<TypeProjection> contextArguments) {
|
||||
Map<TypeConstructor, TypeProjection> parameterValues = new HashMap<TypeConstructor, TypeProjection>();
|
||||
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
||||
TypeParameterDescriptor parameter = parameters.get(i);
|
||||
TypeProjection value = contextArguments.get(i);
|
||||
parameterValues.put(parameter.getTypeConstructor(), value);
|
||||
private boolean allows(Variance declarationSiteVariance, Variance callSiteVariance) {
|
||||
switch (declarationSiteVariance) {
|
||||
case INVARIANT: return true;
|
||||
case IN_VARIANCE: return callSiteVariance != Variance.OUT_VARIANCE;
|
||||
case OUT_VARIANCE: return callSiteVariance != Variance.IN_VARIANCE;
|
||||
}
|
||||
return parameterValues;
|
||||
throw new IllegalStateException(declarationSiteVariance.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,14 +147,14 @@ public class TypeUtils {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetType makeUnsubstitutedType(ClassDescriptor classDescriptor) {
|
||||
public static JetType makeUnsubstitutedType(ClassDescriptor classDescriptor, JetScope unsubstitutedMemberScope) {
|
||||
List<TypeProjection> arguments = getArguments(classDescriptor);
|
||||
return new JetTypeImpl(
|
||||
Collections.<Attribute>emptyList(),
|
||||
classDescriptor.getTypeConstructor(),
|
||||
false,
|
||||
arguments,
|
||||
classDescriptor.getMemberScope(arguments)
|
||||
unsubstitutedMemberScope
|
||||
);
|
||||
}
|
||||
|
||||
@@ -166,4 +166,25 @@ public class TypeUtils {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Map<TypeConstructor, TypeProjection> buildSubstitutionContext(@NotNull JetType context) {
|
||||
return buildSubstitutionContext(context.getConstructor().getParameters(), context.getArguments());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Map<TypeConstructor, TypeProjection> buildSubstitutionContext(@NotNull List<TypeParameterDescriptor> parameters, @NotNull List<TypeProjection> contextArguments) {
|
||||
Map<TypeConstructor, TypeProjection> parameterValues = new HashMap<TypeConstructor, TypeProjection>();
|
||||
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
||||
TypeParameterDescriptor parameter = parameters.get(i);
|
||||
TypeProjection value = contextArguments.get(i);
|
||||
parameterValues.put(parameter.getTypeConstructor(), value);
|
||||
}
|
||||
return parameterValues;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static TypeProjection makeStarProjection(@NotNull TypeParameterDescriptor parameterDescriptor) {
|
||||
return new TypeProjection(Variance.OUT_VARIANCE, parameterDescriptor.getBoundsAsType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,18 +4,20 @@ package org.jetbrains.jet.lang.types;
|
||||
* @author max
|
||||
*/
|
||||
public enum Variance {
|
||||
INVARIANT("", true, true),
|
||||
IN_VARIANCE("in", true, false),
|
||||
OUT_VARIANCE("out", false, true);
|
||||
INVARIANT("", true, true, 0),
|
||||
IN_VARIANCE("in", true, false, -1),
|
||||
OUT_VARIANCE("out", false, true, +1);
|
||||
|
||||
private final String label;
|
||||
private final boolean allowsInPosition;
|
||||
private final boolean allowsOutPosition;
|
||||
private final int superpositionFactor;
|
||||
|
||||
Variance(String label, boolean allowsInPosition, boolean allowsOutPosition) {
|
||||
Variance(String label, boolean allowsInPosition, boolean allowsOutPosition, int superpositionFactor) {
|
||||
this.label = label;
|
||||
this.allowsInPosition = allowsInPosition;
|
||||
this.allowsOutPosition = allowsOutPosition;
|
||||
this.superpositionFactor = superpositionFactor;
|
||||
}
|
||||
|
||||
public boolean allowsInPosition() {
|
||||
@@ -26,6 +28,16 @@ public enum Variance {
|
||||
return allowsOutPosition;
|
||||
}
|
||||
|
||||
public Variance superpose(Variance other) {
|
||||
int r = this.superpositionFactor * other.superpositionFactor;
|
||||
switch (r) {
|
||||
case 0: return INVARIANT;
|
||||
case -1: return IN_VARIANCE;
|
||||
case +1: return OUT_VARIANCE;
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return label;
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
class In<in T> {
|
||||
~In.f:T->Unit~fun f(t : T) : Unit {}
|
||||
~In.f:Int->Int~fun f(t : Int) : Int {}
|
||||
~In.f1~fun f1(t : T) : Unit {}
|
||||
}
|
||||
|
||||
class Out<out T> {
|
||||
~Out.f~fun f() : T {}
|
||||
~Out.f(a)~fun f(a : Int) : Int {a}
|
||||
}
|
||||
|
||||
class Inv<T> {
|
||||
~Inv.f~fun f(t : T) : T {t}
|
||||
~Inv.inf~fun inf(t : T) : Unit {}
|
||||
~Inv.outf~fun outf() : T {}
|
||||
}
|
||||
|
||||
fun testInOut() {
|
||||
new In<String>().`In.f:T->Unit`f("1");
|
||||
new In<in String>().`In.f:T->Unit`f("1");
|
||||
new In<out String>().`!`f("1")
|
||||
new In<*>().`!`f("1");
|
||||
|
||||
new In<String>().`In.f:Int->Int`f(1);
|
||||
new In<in String>().`In.f:Int->Int`f(1);
|
||||
new In<out String>().`In.f:Int->Int`f(1)
|
||||
new In<out String>().`!`f1(1)
|
||||
new In<*>().`In.f:Int->Int`f(1);
|
||||
|
||||
new Out<Int>().`Out.f(a)`f(1)
|
||||
new Out<out Int>().`Out.f(a)`f(1)
|
||||
new Out<in Int>().`Out.f(a)`f(1)
|
||||
new Out<*>().`Out.f(a)`f(1)
|
||||
|
||||
new Out<Int>().`Out.f`f()
|
||||
new Out<out Int>().`Out.f`f()
|
||||
new Out<in Int>().`!`f()
|
||||
new Out<*>().`Out.f`f()
|
||||
|
||||
new Inv<Int>().`Inv.f`f(1)
|
||||
new Inv<in Int>().`!`f(1)
|
||||
new Inv<out Int>().`!`f(1)
|
||||
new Inv<*>().`!`f(1)
|
||||
|
||||
new Inv<Int>().`Inv.inf`inf(1)
|
||||
new Inv<in Int>().`Inv.inf`inf(1)
|
||||
new Inv<out Int>().`!`inf(1)
|
||||
new Inv<*>().`!`inf(1)
|
||||
|
||||
new Inv<Int>().`Inv.outf`outf()
|
||||
new Inv<in Int>().`!`outf()
|
||||
new Inv<out Int>().`Inv.outf`outf()
|
||||
new Inv<*>().`Inv.outf`outf()
|
||||
|
||||
new Inv<Int>().`Inv.outf`outf(1)
|
||||
}
|
||||
@@ -142,4 +142,8 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
|
||||
doTest("/resolve/ResolveOfInfixExpressions.jet", true, true);
|
||||
}
|
||||
|
||||
public void testProjections() throws Exception {
|
||||
doTest("/resolve/Projections.jet", true, true);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user