Resolve for 'for' and 'while', 'do..while' pending
This commit is contained in:
@@ -159,8 +159,8 @@ class Float : Number, Comparable<Float> {
|
||||
|
||||
fun rangeTo(other : Double) : Range<Double>
|
||||
fun rangeTo(other : Float) : Range<Float>
|
||||
fun rangeTo(other : Long) : Range<Float>
|
||||
fun rangeTo(other : Int) : Range<Float>
|
||||
fun rangeTo(other : Long) : Range<Double>
|
||||
fun rangeTo(other : Int) : Range<Double>
|
||||
fun rangeTo(other : Short) : Range<Float>
|
||||
fun rangeTo(other : Byte) : Range<Float>
|
||||
fun rangeTo(other : Char) : Range<Float>
|
||||
@@ -221,7 +221,7 @@ class Long : Number, Comparable<Long> {
|
||||
fun mod(other : Char) : Long
|
||||
|
||||
fun rangeTo(other : Double) : Range<Double>
|
||||
fun rangeTo(other : Float) : Range<Float>
|
||||
fun rangeTo(other : Float) : Range<Double>
|
||||
fun rangeTo(other : Long) : IntRange<Long>
|
||||
fun rangeTo(other : Int) : IntRange<Long>
|
||||
fun rangeTo(other : Short) : IntRange<Long>
|
||||
@@ -284,7 +284,7 @@ class Int : Number, Comparable<Int> {
|
||||
fun mod(other : Char) : Int
|
||||
|
||||
fun rangeTo(other : Double) : Range<Double>
|
||||
fun rangeTo(other : Float) : Range<Float>
|
||||
fun rangeTo(other : Float) : Range<Double>
|
||||
fun rangeTo(other : Long) : IntRange<Long>
|
||||
fun rangeTo(other : Int) : IntRange<Int>
|
||||
fun rangeTo(other : Short) : IntRange<Int>
|
||||
@@ -350,9 +350,9 @@ class Char : Number, Comparable<Char> {
|
||||
fun rangeTo(other : Float) : Range<Float>
|
||||
fun rangeTo(other : Long) : IntRange<Long>
|
||||
fun rangeTo(other : Int) : IntRange<Int>
|
||||
fun rangeTo(other : Short) : IntRange<Int>
|
||||
fun rangeTo(other : Byte) : IntRange<Int>
|
||||
fun rangeTo(other : Char) : IntRange<Int>
|
||||
fun rangeTo(other : Short) : IntRange<Short>
|
||||
fun rangeTo(other : Byte) : IntRange<Byte>
|
||||
fun rangeTo(other : Char) : IntRange<Char>
|
||||
|
||||
fun inc() : Char
|
||||
fun dec() : Char
|
||||
@@ -413,8 +413,8 @@ class Short : Number, Comparable<Char> {
|
||||
fun rangeTo(other : Float) : Range<Float>
|
||||
fun rangeTo(other : Long) : IntRange<Long>
|
||||
fun rangeTo(other : Int) : IntRange<Int>
|
||||
fun rangeTo(other : Short) : IntRange<Int>
|
||||
fun rangeTo(other : Byte) : IntRange<Int>
|
||||
fun rangeTo(other : Short) : IntRange<Short>
|
||||
fun rangeTo(other : Byte) : IntRange<Short>
|
||||
fun rangeTo(other : Char) : IntRange<Int>
|
||||
|
||||
fun inc() : Short
|
||||
@@ -476,8 +476,8 @@ class Byte : Number, Comparable<Char> {
|
||||
fun rangeTo(other : Float) : Range<Float>
|
||||
fun rangeTo(other : Long) : IntRange<Long>
|
||||
fun rangeTo(other : Int) : IntRange<Int>
|
||||
fun rangeTo(other : Short) : IntRange<Int>
|
||||
fun rangeTo(other : Byte) : IntRange<Int>
|
||||
fun rangeTo(other : Short) : IntRange<Short>
|
||||
fun rangeTo(other : Byte) : IntRange<Byte>
|
||||
fun rangeTo(other : Char) : IntRange<Int>
|
||||
|
||||
fun inc() : Byte
|
||||
|
||||
@@ -7,7 +7,10 @@ import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -57,6 +60,7 @@ public class ClassDescriptorResolver {
|
||||
|
||||
WritableScope parameterScope = descriptor.getUnsubstitutedMemberScope();
|
||||
|
||||
|
||||
// This call has side-effects on the parameterScope (fills it in)
|
||||
List<TypeParameterDescriptor> typeParameters
|
||||
= resolveTypeParameters(descriptor, parameterScope, classElement.getTypeParameters());
|
||||
@@ -86,6 +90,7 @@ public class ClassDescriptorResolver {
|
||||
|
||||
// TODO : importing may be a bad idea
|
||||
for (JetType supertype : superclasses) {
|
||||
assert supertype != null : classElement.getName();
|
||||
parameterScope.importScope(supertype.getMemberScope());
|
||||
}
|
||||
|
||||
@@ -224,7 +229,7 @@ public class ClassDescriptorResolver {
|
||||
typeParameter.getVariance(),
|
||||
typeParameter.getName(),
|
||||
extendsBound == null
|
||||
? Collections.<JetType>singleton(JetStandardClasses.getAnyType())
|
||||
? Collections.<JetType>singleton(JetStandardClasses.getDefaultBound())
|
||||
: Collections.singleton(typeResolver.resolveType(extensibleScope, extendsBound))
|
||||
);
|
||||
extensibleScope.addTypeParameterDescriptor(typeParameterDescriptor);
|
||||
@@ -250,11 +255,23 @@ public class ClassDescriptorResolver {
|
||||
|
||||
@NotNull
|
||||
public PropertyDescriptor resolvePropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope scope, @NotNull JetParameter parameter) {
|
||||
JetTypeReference typeReference = parameter.getTypeReference();
|
||||
JetType type;
|
||||
if (typeReference != null) {
|
||||
type = typeResolver.resolveType(scope, typeReference);
|
||||
}
|
||||
else {
|
||||
type = ErrorType.createErrorType("Annotation is absent");
|
||||
}
|
||||
return resolvePropertyDescriptor(containingDeclaration, parameter, type);
|
||||
}
|
||||
|
||||
public PropertyDescriptor resolvePropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetParameter parameter, @NotNull JetType type) {
|
||||
return new PropertyDescriptorImpl(
|
||||
containingDeclaration,
|
||||
AttributeResolver.INSTANCE.resolveAttributes(parameter.getModifierList()),
|
||||
parameter.getName(),
|
||||
typeResolver.resolveType(scope, parameter.getTypeReference()));
|
||||
type);
|
||||
}
|
||||
|
||||
public PropertyDescriptor resolvePropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope scope, JetProperty property) {
|
||||
|
||||
@@ -37,6 +37,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
||||
return new SubstitutingScope(unsubstitutedMemberScope, substitutionContext);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public WritableScope getUnsubstitutedMemberScope() {
|
||||
return unsubstitutedMemberScope;
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ public class JetStandardClasses {
|
||||
}
|
||||
}, JetScope.EMPTY
|
||||
);
|
||||
private static final JetType NOTHING_TYPE = new JetTypeImpl(getNothing());
|
||||
|
||||
private static final JetType NOTHING_TYPE = new JetTypeImpl(getNothing());
|
||||
private static final JetType NULLABLE_NOTHING_TYPE = new JetTypeImpl(
|
||||
Collections.<Attribute>emptyList(),
|
||||
getNothing().getTypeConstructor(),
|
||||
@@ -65,8 +65,8 @@ public class JetStandardClasses {
|
||||
Collections.<JetType>emptySet(),
|
||||
JetScope.EMPTY
|
||||
);
|
||||
private static final JetType ANY_TYPE = new JetTypeImpl(ANY.getTypeConstructor(), JetScope.EMPTY);
|
||||
|
||||
private static final JetType ANY_TYPE = new JetTypeImpl(ANY.getTypeConstructor(), JetScope.EMPTY);
|
||||
private static final JetType NULLABLE_ANY_TYPE = TypeUtils.makeNullable(ANY_TYPE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -76,8 +76,8 @@ public class JetStandardClasses {
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static final int TUPLE_COUNT = 22;
|
||||
private static final ClassDescriptor[] TUPLE = new ClassDescriptor[TUPLE_COUNT];
|
||||
|
||||
private static final ClassDescriptor[] TUPLE = new ClassDescriptor[TUPLE_COUNT];
|
||||
static {
|
||||
for (int i = 0; i < TUPLE_COUNT; i++) {
|
||||
List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>();
|
||||
@@ -102,8 +102,8 @@ public class JetStandardClasses {
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static final int FUNCTION_COUNT = 22;
|
||||
private static final ClassDescriptor[] FUNCTION = new ClassDescriptor[FUNCTION_COUNT];
|
||||
|
||||
private static final ClassDescriptor[] FUNCTION = new ClassDescriptor[FUNCTION_COUNT];
|
||||
private static final ClassDescriptor[] RECEIVER_FUNCTION = new ClassDescriptor[FUNCTION_COUNT];
|
||||
|
||||
static {
|
||||
@@ -191,8 +191,15 @@ public class JetStandardClasses {
|
||||
}
|
||||
}
|
||||
|
||||
private static final JetType DEFAULT_BOUND = getNullableAnyType();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@NotNull
|
||||
public static JetType getDefaultBound() {
|
||||
return DEFAULT_BOUND;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassDescriptor getAny() {
|
||||
return ANY;
|
||||
|
||||
@@ -49,6 +49,7 @@ public class JetStandardLibrary {
|
||||
private final ClassDescriptor booleanClass;
|
||||
private final ClassDescriptor stringClass;
|
||||
private final ClassDescriptor arrayClass;
|
||||
private final ClassDescriptor iterableClass;
|
||||
|
||||
private final JetType byteType;
|
||||
private final JetType charType;
|
||||
@@ -86,6 +87,7 @@ public class JetStandardLibrary {
|
||||
this.booleanClass = libraryScope.getClass("Boolean");
|
||||
this.stringClass = libraryScope.getClass("String");
|
||||
this.arrayClass = libraryScope.getClass("Array");
|
||||
this.iterableClass = libraryScope.getClass("Iterable");
|
||||
|
||||
this.byteType = new JetTypeImpl(getByte());
|
||||
this.charType = new JetTypeImpl(getChar());
|
||||
@@ -155,6 +157,11 @@ public class JetStandardLibrary {
|
||||
return arrayClass;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ClassDescriptor getIterable() {
|
||||
return iterableClass;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetType getIntType() {
|
||||
return intType;
|
||||
@@ -217,4 +224,16 @@ public class JetStandardLibrary {
|
||||
getArray().getMemberScope(types)
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetType getIterableType(@NotNull JetType argument) {
|
||||
List<TypeProjection> types = Collections.singletonList(new TypeProjection(Variance.INVARIANT, argument));
|
||||
return new JetTypeImpl(
|
||||
Collections.<Attribute>emptyList(),
|
||||
getIterable().getTypeConstructor(),
|
||||
false,
|
||||
types,
|
||||
getIterable().getMemberScope(types)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,11 +177,14 @@ public class JetTypeChecker {
|
||||
}
|
||||
|
||||
if (ins != null) {
|
||||
Variance projectionKind = variance == Variance.IN_VARIANCE ? Variance.INVARIANT : Variance.IN_VARIANCE;
|
||||
JetType intersection = TypeUtils.intersect(this, ins);
|
||||
if (intersection == null) {
|
||||
if (outs != null) {
|
||||
return new TypeProjection(Variance.OUT_VARIANCE, commonSupertype(outs));
|
||||
}
|
||||
return new TypeProjection(Variance.OUT_VARIANCE, commonSupertype(parameterDescriptor.getUpperBounds()));
|
||||
}
|
||||
Variance projectionKind = variance == Variance.IN_VARIANCE ? Variance.INVARIANT : Variance.IN_VARIANCE;
|
||||
return new TypeProjection(projectionKind, intersection);
|
||||
} else if (outs != null) {
|
||||
Variance projectionKind = variance == Variance.OUT_VARIANCE ? Variance.INVARIANT : Variance.OUT_VARIANCE;
|
||||
|
||||
@@ -165,7 +165,7 @@ public class JetTypeInferrer {
|
||||
@Override
|
||||
public void visitExpression(JetExpression expression) {
|
||||
// <e> create a dummy domain for the type of e
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
throw new UnsupportedOperationException(expression.getText()); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -436,55 +436,6 @@ public class JetTypeInferrer {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIfExpression(JetIfExpression expression) {
|
||||
// TODO : check condition type
|
||||
JetExpression condition = expression.getCondition();
|
||||
if (condition != null) {
|
||||
JetType conditionType = getType(scope, condition, false);
|
||||
|
||||
if (conditionType != null && !isBoolean(conditionType)) {
|
||||
semanticServices.getErrorHandler().genericError(condition.getNode(), "Condition must be of type Boolean, but was of type " + conditionType);
|
||||
}
|
||||
}
|
||||
// TODO : change types according to is and nullability checks
|
||||
JetExpression elseBranch = expression.getElse();
|
||||
if (elseBranch == null) {
|
||||
// TODO : type-check the branch
|
||||
result = JetStandardClasses.getUnitType();
|
||||
} else {
|
||||
JetType thenType = getType(scope, expression.getThen(), true);
|
||||
JetType elseType = getType(scope, elseBranch, true);
|
||||
result = semanticServices.getTypeChecker().commonSupertype(Arrays.asList(thenType, elseType));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitWhenExpression(JetWhenExpression expression) {
|
||||
// TODO :change scope according to the bound value in the when header
|
||||
List<JetType> expressions = new ArrayList<JetType>();
|
||||
collectAllReturnTypes(expression, scope, expressions);
|
||||
result = semanticServices.getTypeChecker().commonSupertype(expressions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTryExpression(JetTryExpression expression) {
|
||||
JetExpression tryBlock = expression.getTryBlock();
|
||||
List<JetCatchClause> catchClauses = expression.getCatchClauses();
|
||||
JetFinallySection finallyBlock = expression.getFinallyBlock();
|
||||
List<JetType> types = new ArrayList<JetType>();
|
||||
if (finallyBlock == null) {
|
||||
for (JetCatchClause catchClause : catchClauses) {
|
||||
// TODO: change scope here
|
||||
types.add(getType(scope, catchClause.getCatchBody(), true));
|
||||
}
|
||||
} else {
|
||||
types.add(getType(scope, finallyBlock.getFinalExpression(), true));
|
||||
}
|
||||
types.add(getType(scope, tryBlock, true));
|
||||
result = semanticServices.getTypeChecker().commonSupertype(types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTupleExpression(JetTupleExpression expression) {
|
||||
List<JetExpression> entries = expression.getEntries();
|
||||
@@ -525,7 +476,125 @@ public class JetTypeInferrer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLoopExpression(JetLoopExpression expression) {
|
||||
public void visitWhenExpression(JetWhenExpression expression) {
|
||||
// TODO :change scope according to the bound value in the when header
|
||||
List<JetType> expressions = new ArrayList<JetType>();
|
||||
collectAllReturnTypes(expression, scope, expressions);
|
||||
result = semanticServices.getTypeChecker().commonSupertype(expressions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTryExpression(JetTryExpression expression) {
|
||||
JetExpression tryBlock = expression.getTryBlock();
|
||||
List<JetCatchClause> catchClauses = expression.getCatchClauses();
|
||||
JetFinallySection finallyBlock = expression.getFinallyBlock();
|
||||
List<JetType> types = new ArrayList<JetType>();
|
||||
if (finallyBlock == null) {
|
||||
for (JetCatchClause catchClause : catchClauses) {
|
||||
// TODO: change scope here
|
||||
types.add(getType(scope, catchClause.getCatchBody(), true));
|
||||
}
|
||||
} else {
|
||||
types.add(getType(scope, finallyBlock.getFinalExpression(), true));
|
||||
}
|
||||
types.add(getType(scope, tryBlock, true));
|
||||
result = semanticServices.getTypeChecker().commonSupertype(types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIfExpression(JetIfExpression expression) {
|
||||
checkCondition(scope, expression.getCondition());
|
||||
|
||||
// TODO : change types according to is and nullability checks
|
||||
JetExpression elseBranch = expression.getElse();
|
||||
if (elseBranch == null) {
|
||||
// TODO : type-check the branch
|
||||
result = JetStandardClasses.getUnitType();
|
||||
} else {
|
||||
JetType thenType = getType(scope, expression.getThen(), true);
|
||||
JetType elseType = getType(scope, elseBranch, true);
|
||||
result = semanticServices.getTypeChecker().commonSupertype(Arrays.asList(thenType, elseType));
|
||||
}
|
||||
}
|
||||
|
||||
private void checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition) {
|
||||
if (condition != null) {
|
||||
JetType conditionType = getType(scope, condition, false);
|
||||
|
||||
if (conditionType != null && !isBoolean(conditionType)) {
|
||||
semanticServices.getErrorHandler().genericError(condition.getNode(), "Condition must be of type Boolean, but was of type " + conditionType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitWhileExpression(JetWhileExpression expression) {
|
||||
checkCondition(scope, expression.getCondition());
|
||||
JetExpression body = expression.getBody();
|
||||
if (body != null) {
|
||||
getType(scope, body, true);
|
||||
}
|
||||
result = JetStandardClasses.getUnitType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDoWhileExpression(JetDoWhileExpression expression) {
|
||||
JetExpression body = expression.getBody();
|
||||
JetScope conditionScope = scope; // TODO
|
||||
if (body != null) {
|
||||
getType(scope, body, true);
|
||||
}
|
||||
checkCondition(conditionScope, expression.getCondition());
|
||||
result = JetStandardClasses.getUnitType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitForExpression(JetForExpression expression) {
|
||||
JetParameter loopParameter = expression.getLoopParameter();
|
||||
JetExpression loopRange = expression.getLoopRange();
|
||||
JetType loopRangeType = getType(scope, loopRange, false);
|
||||
JetType expectedParameterType = null;
|
||||
if (loopRangeType != null) {
|
||||
if (!semanticServices.getTypeChecker().isSubtypeOf(loopRangeType, semanticServices.getStandardLibrary().getIterableType(JetStandardClasses.getNullableAnyType()))) {
|
||||
semanticServices.getErrorHandler().genericError(loopRange.getNode(), "Expecting an Iterable, but found " + loopRangeType);
|
||||
}
|
||||
else {
|
||||
TypeProjection typeProjection = loopRangeType.getArguments().get(0);
|
||||
if (!typeProjection.getProjectionKind().allowsOutPosition()) {
|
||||
expectedParameterType = JetStandardClasses.getDefaultBound();
|
||||
}
|
||||
else {
|
||||
expectedParameterType = typeProjection.getType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WritableScope loopScope = semanticServices.createWritableScope(scope, scope.getContainingDeclaration());
|
||||
|
||||
JetTypeReference typeReference = loopParameter.getTypeReference();
|
||||
PropertyDescriptor propertyDescriptor;
|
||||
if (typeReference != null) {
|
||||
propertyDescriptor = semanticServices.getClassDescriptorResolver(trace).resolvePropertyDescriptor(scope.getContainingDeclaration(), scope, loopParameter);
|
||||
JetType actualParameterType = propertyDescriptor.getType();
|
||||
if (expectedParameterType != null &&
|
||||
!semanticServices.getTypeChecker().isSubtypeOf(expectedParameterType, actualParameterType)) {
|
||||
semanticServices.getErrorHandler().genericError(typeReference.getNode(), "The loop iterates over values of type " + expectedParameterType + " but the parameter is declared to be " + actualParameterType);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (expectedParameterType == null) {
|
||||
expectedParameterType = ErrorType.createErrorType("Error");
|
||||
}
|
||||
propertyDescriptor = semanticServices.getClassDescriptorResolver(trace).resolvePropertyDescriptor(scope.getContainingDeclaration(), loopParameter, expectedParameterType);
|
||||
}
|
||||
loopScope.addPropertyDescriptor(propertyDescriptor);
|
||||
trace.recordDeclarationResolution(loopParameter, propertyDescriptor);
|
||||
|
||||
JetExpression body = expression.getBody();
|
||||
if (body != null) {
|
||||
getType(loopScope, body, true); // TODO
|
||||
}
|
||||
|
||||
result = JetStandardClasses.getUnitType();
|
||||
}
|
||||
|
||||
@@ -844,6 +913,9 @@ public class JetTypeInferrer {
|
||||
private JetType getTypeForBinaryCall(JetScope scope, JetExpression left, JetSimpleNameExpression operationSign, @NotNull JetExpression right, String name, boolean reportUnresolved) {
|
||||
JetType leftType = safeGetType(scope, left, false);
|
||||
JetType rightType = safeGetType(scope, right, false);
|
||||
if (ErrorType.isErrorType(leftType)) {
|
||||
return null;
|
||||
}
|
||||
FunctionDescriptor functionDescriptor = lookupFunction(scope, operationSign, name, leftType, Collections.singletonList(rightType), reportUnresolved);
|
||||
if (functionDescriptor != null) {
|
||||
return functionDescriptor.getUnsubstitutedReturnType();
|
||||
|
||||
@@ -17,3 +17,18 @@
|
||||
|
||||
val x : `C.B`B
|
||||
}
|
||||
|
||||
fun test() : Unit {
|
||||
for (~i~i in 1..2) {
|
||||
`i`i`:std::Int`
|
||||
}
|
||||
for (val ~j~j in 1..2) {
|
||||
`j`j`:std::Int`
|
||||
}
|
||||
for (val ~k~k : Int in 1..2) {
|
||||
`k`k`:std::Int`
|
||||
}
|
||||
for (~l~l : Int in 1..2) {
|
||||
`l`l`:std::Int`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +141,8 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
assertCommonSupertype("Derived_T<Int>", "DDerived_T<Int>", "Derived_T<Int>");
|
||||
assertCommonSupertype("Derived_T<Int>", "DDerived_T<Int>", "DDerived1_T<Int>");
|
||||
|
||||
assertCommonSupertype("Base_T<out Any>", "Base_T<Int>", "Base_T<Boolean>");
|
||||
assertCommonSupertype("Comparable<*>", "Comparable<Int>", "Comparable<Boolean>");
|
||||
assertCommonSupertype("Base_T<out Comparable<*>>", "Base_T<Int>", "Base_T<Boolean>");
|
||||
assertCommonSupertype("Base_T<in Int>", "Base_T<Int>", "Base_T<in Int>");
|
||||
assertCommonSupertype("Base_T<in Int>", "Derived_T<Int>", "Base_T<in Int>");
|
||||
assertCommonSupertype("Base_T<in Int>", "Derived_T<in Int>", "Base_T<Int>");
|
||||
|
||||
Reference in New Issue
Block a user