blob: c184635a9545e7229624444a201d3f5ce85f4178 [file] [log] [blame]
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library least_upper_bound_test;
import 'package:expect/expect.dart';
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/dart_types.dart';
import 'package:compiler/src/elements/elements.dart' show Element, ClassElement;
import 'type_test_helper.dart';
void main() {
testInterface1();
testInterface2();
testGeneric();
testMixin();
testFunction();
testTypeVariable();
}
void testInterface1() {
asyncTest(() => TypeEnvironment.create(r"""
class A {} // A and B have equal depth.
class B {}
class I implements A, B {}
class J implements A, B {}
""").then((env) {
DartType Object_ = env['Object'];
DartType A = env['A'];
DartType B = env['B'];
DartType I = env['I'];
DartType J = env['J'];
checkLub(DartType a, DartType b, DartType expect) {
DartType lub = env.computeLeastUpperBound(a, b);
Expect.equals(
expect, lub, 'Unexpected lub($a,$b) = $lub, expected $expect.');
}
checkLub(Object_, Object_, Object_);
checkLub(Object_, A, Object_);
checkLub(Object_, B, Object_);
checkLub(Object_, I, Object_);
checkLub(Object_, J, Object_);
checkLub(A, Object_, Object_);
checkLub(A, A, A);
checkLub(A, B, Object_);
checkLub(A, I, A);
checkLub(A, J, A);
checkLub(B, Object_, Object_);
checkLub(B, A, Object_);
checkLub(B, B, B);
checkLub(B, I, B);
checkLub(B, J, B);
checkLub(I, Object_, Object_);
checkLub(I, A, A);
checkLub(I, B, B);
checkLub(I, I, I);
checkLub(I, J, Object_);
checkLub(J, Object_, Object_);
checkLub(J, A, A);
checkLub(J, B, B);
checkLub(J, I, Object_);
checkLub(J, J, J);
}));
}
void testInterface2() {
asyncTest(() => TypeEnvironment.create(r"""
class A {}
class B {}
class C extends B {} // This makes C have higher depth than A.
class I implements A, C {}
class J implements A, C {}
""").then((env) {
DartType Object_ = env['Object'];
DartType A = env['A'];
DartType B = env['B'];
DartType C = env['C'];
DartType I = env['I'];
DartType J = env['J'];
checkLub(DartType a, DartType b, DartType expectedLub) {
DartType lub = env.computeLeastUpperBound(a, b);
Expect.equals(expectedLub, lub,
'Unexpected lub($a,$b) = $lub, expected $expectedLub');
}
checkLub(Object_, Object_, Object_);
checkLub(Object_, A, Object_);
checkLub(Object_, B, Object_);
checkLub(Object_, C, Object_);
checkLub(Object_, I, Object_);
checkLub(Object_, J, Object_);
checkLub(A, Object_, Object_);
checkLub(A, A, A);
checkLub(A, B, Object_);
checkLub(A, C, Object_);
checkLub(A, I, A);
checkLub(A, J, A);
checkLub(B, Object_, Object_);
checkLub(B, A, Object_);
checkLub(B, B, B);
checkLub(B, C, B);
checkLub(B, I, B);
checkLub(B, J, B);
checkLub(C, Object_, Object_);
checkLub(C, A, Object_);
checkLub(C, B, B);
checkLub(C, C, C);
checkLub(C, I, C);
checkLub(C, J, C);
checkLub(I, Object_, Object_);
checkLub(I, A, A);
checkLub(I, B, B);
checkLub(I, C, C);
checkLub(I, I, I);
checkLub(I, J, C);
checkLub(J, Object_, Object_);
checkLub(J, A, A);
checkLub(J, B, B);
checkLub(J, C, C);
checkLub(J, I, C);
checkLub(J, J, J);
}));
}
void testGeneric() {
asyncTest(() => TypeEnvironment.create(r"""
class A {}
class B {}
class C extends B {}
class I<T> {}
""").then((env) {
DartType Object_ = env['Object'];
DartType A = env['A'];
DartType B = env['B'];
DartType C = env['C'];
ClassElement I = env.getElement('I');
DartType I_A = instantiate(I, [A]);
DartType I_B = instantiate(I, [B]);
DartType I_C = instantiate(I, [C]);
checkLub(DartType a, DartType b, DartType expectedLub) {
DartType lub = env.computeLeastUpperBound(a, b);
Expect.equals(expectedLub, lub,
'Unexpected lub($a,$b) = $lub, expected $expectedLub');
}
checkLub(Object_, Object_, Object_);
checkLub(Object_, A, Object_);
checkLub(Object_, B, Object_);
checkLub(Object_, C, Object_);
checkLub(Object_, I_A, Object_);
checkLub(Object_, I_B, Object_);
checkLub(Object_, I_C, Object_);
checkLub(A, Object_, Object_);
checkLub(A, A, A);
checkLub(A, B, Object_);
checkLub(A, C, Object_);
checkLub(A, I_A, Object_);
checkLub(A, I_B, Object_);
checkLub(A, I_C, Object_);
checkLub(B, Object_, Object_);
checkLub(B, A, Object_);
checkLub(B, B, B);
checkLub(B, C, B);
checkLub(B, I_A, Object_);
checkLub(B, I_B, Object_);
checkLub(B, I_C, Object_);
checkLub(C, Object_, Object_);
checkLub(C, A, Object_);
checkLub(C, B, B);
checkLub(C, C, C);
checkLub(C, I_A, Object_);
checkLub(C, I_B, Object_);
checkLub(C, I_C, Object_);
checkLub(I_A, Object_, Object_);
checkLub(I_A, A, Object_);
checkLub(I_A, B, Object_);
checkLub(I_A, C, Object_);
checkLub(I_A, I_A, I_A);
checkLub(I_A, I_B, Object_);
checkLub(I_A, I_C, Object_);
checkLub(I_B, Object_, Object_);
checkLub(I_B, A, Object_);
checkLub(I_B, B, Object_);
checkLub(I_B, C, Object_);
checkLub(I_B, I_A, Object_);
checkLub(I_B, I_B, I_B);
checkLub(I_B, I_C, Object_);
checkLub(I_C, Object_, Object_);
checkLub(I_C, A, Object_);
checkLub(I_C, B, Object_);
checkLub(I_C, C, Object_);
checkLub(I_C, I_A, Object_);
checkLub(I_C, I_B, Object_);
checkLub(I_C, I_C, I_C);
}));
}
void testMixin() {
asyncTest(() => TypeEnvironment.create(r"""
class A {}
class B {}
class C extends B {}
class D extends C {} // This makes D have higher depth than Object+A.
class I extends Object with A, B implements A, D {}
class I2 extends Object with A, B implements A, D {}
class J extends Object with B, A implements A, D {}
""").then((env) {
DartType Object_ = env['Object'];
DartType A = env['A'];
DartType B = env['B'];
DartType C = env['C'];
DartType D = env['D'];
DartType I = env['I'];
DartType I2 = env['I2'];
DartType J = env['J'];
checkLub(DartType a, DartType b, DartType expectedLub) {
DartType lub = env.computeLeastUpperBound(a, b);
Expect.equals(expectedLub, lub,
'Unexpected lub($a,$b) = $lub, expected $expectedLub');
}
checkLub(Object_, Object_, Object_);
checkLub(Object_, A, Object_);
checkLub(Object_, B, Object_);
checkLub(Object_, C, Object_);
checkLub(Object_, D, Object_);
checkLub(Object_, I, Object_);
checkLub(Object_, I2, Object_);
checkLub(Object_, J, Object_);
checkLub(A, Object_, Object_);
checkLub(A, A, A);
checkLub(A, B, Object_);
checkLub(A, C, Object_);
checkLub(A, D, Object_);
checkLub(A, I, A);
checkLub(A, I2, A);
checkLub(A, J, A);
checkLub(B, Object_, Object_);
checkLub(B, A, Object_);
checkLub(B, B, B);
checkLub(B, C, B);
checkLub(B, D, B);
checkLub(B, I, B);
checkLub(B, I2, B);
checkLub(B, J, B);
checkLub(C, Object_, Object_);
checkLub(C, A, Object_);
checkLub(C, B, B);
checkLub(C, C, C);
checkLub(C, D, C);
checkLub(C, I, C);
checkLub(C, I2, C);
checkLub(C, J, C);
checkLub(D, Object_, Object_);
checkLub(D, A, Object_);
checkLub(D, B, B);
checkLub(D, C, C);
checkLub(D, D, D);
checkLub(D, I, D);
checkLub(D, I2, D);
checkLub(D, J, D);
checkLub(I, Object_, Object_);
checkLub(I, A, A);
checkLub(I, B, B);
checkLub(I, C, C);
checkLub(I, D, D);
checkLub(I, I, I);
checkLub(I, I2, D);
checkLub(I, J, D);
checkLub(I2, Object_, Object_);
checkLub(I2, A, A);
checkLub(I2, B, B);
checkLub(I2, C, C);
checkLub(I2, D, D);
checkLub(I2, I, D);
checkLub(I2, I2, I2);
checkLub(I2, J, D);
checkLub(J, Object_, Object_);
checkLub(J, A, A);
checkLub(J, B, B);
checkLub(J, C, C);
checkLub(J, D, D);
checkLub(J, I, D);
checkLub(J, I2, D);
checkLub(J, J, J);
}));
}
void testFunction() {
asyncTest(() => TypeEnvironment.create(r"""
class A {}
class B {}
class C extends B {}
typedef dynamic__();
typedef void void__();
typedef A A__();
typedef B B__();
typedef C C__();
typedef void void__A_B(A a, B b);
typedef void void__A_C(A a, C b);
typedef void void__B_A(B a, A b);
typedef void void__B_C(B a, C b);
typedef void void___B([B a]);
typedef void void___B_C([B a, C b]);
typedef void void___C_C([C a, C b]);
typedef void void____B({B a});
typedef void void____B_C({B a, C b});
typedef void void____C_C({C a, C b});
""").then((env) {
DartType Object_ = env['Object'];
DartType Function_ = env['Function'];
DartType dynamic__ = env['dynamic__'];
DartType void__ = env['void__'];
DartType A__ = env['A__'];
DartType B__ = env['B__'];
DartType C__ = env['C__'];
DartType void__A_B = env['void__A_B'];
DartType void__A_C = env['void__A_C'];
DartType void__B_A = env['void__B_A'];
DartType void__B_C = env['void__B_C'];
DartType void___B = env['void___B'];
DartType void___B_C = env['void___B_C'];
DartType void___C_C = env['void___C_C'];
DartType void____B = env['void____B'];
DartType void____B_C = env['void____B_C'];
DartType void____C_C = env['void____C_C'];
// Types used only for checking results.
DartType void_ = env['void'];
DartType B = env['B'];
DartType C = env['C'];
FunctionType Object__ = env.functionType(Object_, []);
FunctionType void__Object_Object =
env.functionType(void_, [Object_, Object_]);
FunctionType void__Object_B = env.functionType(void_, [Object_, B]);
FunctionType void__Object_C = env.functionType(void_, [Object_, C]);
FunctionType void__B_Object = env.functionType(void_, [B, Object_]);
checkLub(DartType a, DartType b, DartType expectedLub) {
DartType lub = env.computeLeastUpperBound(a, b);
if (a != b) {
expectedLub = expectedLub.unaliased;
lub = lub.unaliased;
}
Expect.equals(
expectedLub,
lub,
'Unexpected lub(${a.unaliased},'
'${b.unaliased} = '
'${lub}, expected ${expectedLub}');
}
checkLub(Object_, Object_, Object_);
checkLub(Object_, Function_, Object_);
checkLub(Object_, dynamic__, Object_);
checkLub(Object_, void__, Object_);
checkLub(Object_, A__, Object_);
checkLub(Object_, B__, Object_);
checkLub(Object_, C__, Object_);
checkLub(Object_, void__A_B, Object_);
checkLub(Object_, void__A_C, Object_);
checkLub(Object_, void__B_A, Object_);
checkLub(Object_, void__B_C, Object_);
checkLub(Object_, void___B, Object_);
checkLub(Object_, void___B_C, Object_);
checkLub(Object_, void___C_C, Object_);
checkLub(Object_, void____B, Object_);
checkLub(Object_, void____B_C, Object_);
checkLub(Object_, void____C_C, Object_);
checkLub(Function_, Object_, Object_);
checkLub(Function_, Function_, Function_);
checkLub(Function_, dynamic__, Function_);
checkLub(Function_, void__, Function_);
checkLub(Function_, A__, Function_);
checkLub(Function_, B__, Function_);
checkLub(Function_, C__, Function_);
checkLub(Function_, void__A_B, Function_);
checkLub(Function_, void__A_C, Function_);
checkLub(Function_, void__B_A, Function_);
checkLub(Function_, void__B_C, Function_);
checkLub(Function_, void___B, Function_);
checkLub(Function_, void___B_C, Function_);
checkLub(Function_, void___C_C, Function_);
checkLub(Function_, void____B, Function_);
checkLub(Function_, void____B_C, Function_);
checkLub(Function_, void____C_C, Function_);
checkLub(dynamic__, Object_, Object_);
checkLub(dynamic__, Function_, Function_);
checkLub(dynamic__, dynamic__, dynamic__);
checkLub(dynamic__, void__, dynamic__);
checkLub(dynamic__, A__, dynamic__);
checkLub(dynamic__, B__, dynamic__);
checkLub(dynamic__, C__, dynamic__);
checkLub(dynamic__, void__A_B, Function_);
checkLub(dynamic__, void__A_C, Function_);
checkLub(dynamic__, void__B_A, Function_);
checkLub(dynamic__, void__B_C, Function_);
checkLub(dynamic__, void___B, dynamic__);
checkLub(dynamic__, void___B_C, dynamic__);
checkLub(dynamic__, void___C_C, dynamic__);
checkLub(dynamic__, void____B, dynamic__);
checkLub(dynamic__, void____B_C, dynamic__);
checkLub(dynamic__, void____C_C, dynamic__);
checkLub(void__, Object_, Object_);
checkLub(void__, Function_, Function_);
checkLub(void__, dynamic__, dynamic__);
checkLub(void__, void__, void__);
checkLub(void__, A__, void__);
checkLub(void__, B__, void__);
checkLub(void__, C__, void__);
checkLub(void__, void__A_B, Function_);
checkLub(void__, void__A_C, Function_);
checkLub(void__, void__B_A, Function_);
checkLub(void__, void__B_C, Function_);
checkLub(void__, void___B, void__);
checkLub(void__, void___B_C, void__);
checkLub(void__, void___C_C, void__);
checkLub(void__, void____B, void__);
checkLub(void__, void____B_C, void__);
checkLub(void__, void____C_C, void__);
checkLub(A__, Object_, Object_);
checkLub(A__, Function_, Function_);
checkLub(A__, dynamic__, dynamic__);
checkLub(A__, void__, void__);
checkLub(A__, A__, A__);
checkLub(A__, B__, Object__);
checkLub(A__, C__, Object__);
checkLub(A__, void__A_B, Function_);
checkLub(A__, void__A_C, Function_);
checkLub(A__, void__B_A, Function_);
checkLub(A__, void__B_C, Function_);
checkLub(A__, void___B, void__);
checkLub(A__, void___B_C, void__);
checkLub(A__, void___C_C, void__);
checkLub(A__, void____B, void__);
checkLub(A__, void____B_C, void__);
checkLub(A__, void____C_C, void__);
checkLub(B__, Object_, Object_);
checkLub(B__, Function_, Function_);
checkLub(B__, dynamic__, dynamic__);
checkLub(B__, void__, void__);
checkLub(B__, A__, Object__);
checkLub(B__, B__, B__);
checkLub(B__, C__, B__);
checkLub(B__, void__A_B, Function_);
checkLub(B__, void__A_C, Function_);
checkLub(B__, void__B_A, Function_);
checkLub(B__, void__B_C, Function_);
checkLub(B__, void___B, void__);
checkLub(B__, void___B_C, void__);
checkLub(B__, void___C_C, void__);
checkLub(B__, void____B, void__);
checkLub(B__, void____B_C, void__);
checkLub(B__, void____C_C, void__);
checkLub(C__, Object_, Object_);
checkLub(C__, Function_, Function_);
checkLub(C__, dynamic__, dynamic__);
checkLub(C__, void__, void__);
checkLub(C__, A__, Object__);
checkLub(C__, B__, B__);
checkLub(C__, C__, C__);
checkLub(C__, void__A_B, Function_);
checkLub(C__, void__A_C, Function_);
checkLub(C__, void__B_A, Function_);
checkLub(C__, void__B_C, Function_);
checkLub(C__, void___B, void__);
checkLub(C__, void___B_C, void__);
checkLub(C__, void___C_C, void__);
checkLub(C__, void____B, void__);
checkLub(C__, void____B_C, void__);
checkLub(C__, void____C_C, void__);
checkLub(void__A_B, Object_, Object_);
checkLub(void__A_B, Function_, Function_);
checkLub(void__A_B, dynamic__, Function_);
checkLub(void__A_B, void__, Function_);
checkLub(void__A_B, A__, Function_);
checkLub(void__A_B, B__, Function_);
checkLub(void__A_B, C__, Function_);
checkLub(void__A_B, void__A_B, void__A_B);
checkLub(void__A_B, void__A_C, void__A_B);
checkLub(void__A_B, void__B_A, void__Object_Object);
checkLub(void__A_B, void__B_C, void__Object_B);
checkLub(void__A_B, void___B, Function_);
checkLub(void__A_B, void___B_C, Function_);
checkLub(void__A_B, void___C_C, Function_);
checkLub(void__A_B, void____B, Function_);
checkLub(void__A_B, void____B_C, Function_);
checkLub(void__A_B, void____C_C, Function_);
checkLub(void__A_C, Object_, Object_);
checkLub(void__A_C, Function_, Function_);
checkLub(void__A_C, dynamic__, Function_);
checkLub(void__A_C, void__, Function_);
checkLub(void__A_C, A__, Function_);
checkLub(void__A_C, B__, Function_);
checkLub(void__A_C, C__, Function_);
checkLub(void__A_C, void__A_B, void__A_B);
checkLub(void__A_C, void__A_C, void__A_C);
checkLub(void__A_C, void__B_A, void__Object_Object);
checkLub(void__A_C, void__B_C, void__Object_C);
checkLub(void__A_C, void___B, Function_);
checkLub(void__A_C, void___B_C, Function_);
checkLub(void__A_C, void___C_C, Function_);
checkLub(void__A_C, void____B, Function_);
checkLub(void__A_C, void____B_C, Function_);
checkLub(void__A_C, void____C_C, Function_);
checkLub(void__B_A, Object_, Object_);
checkLub(void__B_A, Function_, Function_);
checkLub(void__B_A, dynamic__, Function_);
checkLub(void__B_A, void__, Function_);
checkLub(void__B_A, A__, Function_);
checkLub(void__B_A, B__, Function_);
checkLub(void__B_A, C__, Function_);
checkLub(void__B_A, void__A_B, void__Object_Object);
checkLub(void__B_A, void__A_C, void__Object_Object);
checkLub(void__B_A, void__B_A, void__B_A);
checkLub(void__B_A, void__B_C, void__B_Object);
checkLub(void__B_A, void___B, Function_);
checkLub(void__B_A, void___B_C, Function_);
checkLub(void__B_A, void___C_C, Function_);
checkLub(void__B_A, void____B, Function_);
checkLub(void__B_A, void____B_C, Function_);
checkLub(void__B_A, void____C_C, Function_);
checkLub(void__B_C, Object_, Object_);
checkLub(void__B_C, Function_, Function_);
checkLub(void__B_C, dynamic__, Function_);
checkLub(void__B_C, void__, Function_);
checkLub(void__B_C, A__, Function_);
checkLub(void__B_C, B__, Function_);
checkLub(void__B_C, C__, Function_);
checkLub(void__B_C, void__A_B, void__Object_B);
checkLub(void__B_C, void__A_C, void__Object_C);
checkLub(void__B_C, void__B_A, void__B_Object);
checkLub(void__B_C, void__B_C, void__B_C);
checkLub(void__B_C, void___B, Function_);
checkLub(void__B_C, void___B_C, Function_);
checkLub(void__B_C, void___C_C, Function_);
checkLub(void__B_C, void____B, Function_);
checkLub(void__B_C, void____B_C, Function_);
checkLub(void__B_C, void____C_C, Function_);
checkLub(void___B, Object_, Object_);
checkLub(void___B, Function_, Function_);
checkLub(void___B, dynamic__, dynamic__);
checkLub(void___B, void__, void__);
checkLub(void___B, A__, void__);
checkLub(void___B, B__, void__);
checkLub(void___B, C__, void__);
checkLub(void___B, void__A_B, Function_);
checkLub(void___B, void__A_C, Function_);
checkLub(void___B, void__B_A, Function_);
checkLub(void___B, void__B_C, Function_);
checkLub(void___B, void___B, void___B);
checkLub(void___B, void___B_C, void___B);
checkLub(void___B, void___C_C, void___B);
checkLub(void___B, void____B, void__);
checkLub(void___B, void____B_C, void__);
checkLub(void___B, void____C_C, void__);
checkLub(void___B_C, Object_, Object_);
checkLub(void___B_C, Function_, Function_);
checkLub(void___B_C, dynamic__, dynamic__);
checkLub(void___B_C, void__, void__);
checkLub(void___B_C, A__, void__);
checkLub(void___B_C, B__, void__);
checkLub(void___B_C, C__, void__);
checkLub(void___B_C, void__A_B, Function_);
checkLub(void___B_C, void__A_C, Function_);
checkLub(void___B_C, void__B_A, Function_);
checkLub(void___B_C, void__B_C, Function_);
checkLub(void___B_C, void___B, void___B);
checkLub(void___B_C, void___B_C, void___B_C);
checkLub(void___B_C, void___C_C, void___B_C);
checkLub(void___B_C, void____B, void__);
checkLub(void___B_C, void____B_C, void__);
checkLub(void___B_C, void____C_C, void__);
checkLub(void___C_C, Object_, Object_);
checkLub(void___C_C, Function_, Function_);
checkLub(void___C_C, dynamic__, dynamic__);
checkLub(void___C_C, void__, void__);
checkLub(void___C_C, A__, void__);
checkLub(void___C_C, B__, void__);
checkLub(void___C_C, C__, void__);
checkLub(void___C_C, void__A_B, Function_);
checkLub(void___C_C, void__A_C, Function_);
checkLub(void___C_C, void__B_A, Function_);
checkLub(void___C_C, void__B_C, Function_);
checkLub(void___C_C, void___B, void___B);
checkLub(void___C_C, void___B_C, void___B_C);
checkLub(void___C_C, void___C_C, void___C_C);
checkLub(void___C_C, void____B, void__);
checkLub(void___C_C, void____B_C, void__);
checkLub(void___C_C, void____C_C, void__);
checkLub(void____B, Object_, Object_);
checkLub(void____B, Function_, Function_);
checkLub(void____B, dynamic__, dynamic__);
checkLub(void____B, void__, void__);
checkLub(void____B, A__, void__);
checkLub(void____B, B__, void__);
checkLub(void____B, C__, void__);
checkLub(void____B, void__A_B, Function_);
checkLub(void____B, void__A_C, Function_);
checkLub(void____B, void__B_A, Function_);
checkLub(void____B, void__B_C, Function_);
checkLub(void____B, void___B, void__);
checkLub(void____B, void___B_C, void__);
checkLub(void____B, void___C_C, void__);
checkLub(void____B, void____B, void____B);
checkLub(void____B, void____B_C, void____B);
checkLub(void____B, void____C_C, void____B);
checkLub(void____B_C, Object_, Object_);
checkLub(void____B_C, Function_, Function_);
checkLub(void____B_C, dynamic__, dynamic__);
checkLub(void____B_C, void__, void__);
checkLub(void____B_C, A__, void__);
checkLub(void____B_C, B__, void__);
checkLub(void____B_C, C__, void__);
checkLub(void____B_C, void__A_B, Function_);
checkLub(void____B_C, void__A_C, Function_);
checkLub(void____B_C, void__B_A, Function_);
checkLub(void____B_C, void__B_C, Function_);
checkLub(void____B_C, void___B, void__);
checkLub(void____B_C, void___B_C, void__);
checkLub(void____B_C, void___C_C, void__);
checkLub(void____B_C, void____B, void____B);
checkLub(void____B_C, void____B_C, void____B_C);
checkLub(void____B_C, void____C_C, void____B_C);
checkLub(void____C_C, Object_, Object_);
checkLub(void____C_C, Function_, Function_);
checkLub(void____C_C, dynamic__, dynamic__);
checkLub(void____C_C, void__, void__);
checkLub(void____C_C, A__, void__);
checkLub(void____C_C, B__, void__);
checkLub(void____C_C, C__, void__);
checkLub(void____C_C, void__A_B, Function_);
checkLub(void____C_C, void__A_C, Function_);
checkLub(void____C_C, void__B_A, Function_);
checkLub(void____C_C, void__B_C, Function_);
checkLub(void____C_C, void___B, void__);
checkLub(void____C_C, void___B_C, void__);
checkLub(void____C_C, void___C_C, void__);
checkLub(void____C_C, void____B, void____B);
checkLub(void____C_C, void____B_C, void____B_C);
checkLub(void____C_C, void____C_C, void____C_C);
}));
}
void testTypeVariable() {
asyncTest(() => TypeEnvironment.create(r"""
class A {}
class B {}
class C extends B {}
class I<S extends A,
T extends B,
U extends C,
V extends T,
W extends V,
X extends T> {}
""").then((env) {
// A B
// | / \
// S T C
// / \ \
// V X U
// /
// W
DartType Object_ = env['Object'];
DartType A = env['A'];
DartType B = env['B'];
DartType C = env['C'];
ClassElement I = env.getElement('I');
DartType S = I.typeVariables[0];
DartType T = I.typeVariables[1];
DartType U = I.typeVariables[2];
DartType V = I.typeVariables[3];
DartType W = I.typeVariables[4];
DartType X = I.typeVariables[5];
checkLub(DartType a, DartType b, DartType expectedLub) {
DartType lub = env.computeLeastUpperBound(a, b);
Expect.equals(expectedLub, lub,
'Unexpected lub($a,$b) = $lub, expected $expectedLub');
}
checkLub(Object_, Object_, Object_);
checkLub(Object_, A, Object_);
checkLub(Object_, B, Object_);
checkLub(Object_, C, Object_);
checkLub(Object_, S, Object_);
checkLub(Object_, T, Object_);
checkLub(Object_, U, Object_);
checkLub(Object_, V, Object_);
checkLub(Object_, W, Object_);
checkLub(Object_, X, Object_);
checkLub(A, Object_, Object_);
checkLub(A, A, A);
checkLub(A, B, Object_);
checkLub(A, C, Object_);
checkLub(A, S, A);
checkLub(A, T, Object_);
checkLub(A, U, Object_);
checkLub(A, V, Object_);
checkLub(A, W, Object_);
checkLub(A, X, Object_);
checkLub(B, Object_, Object_);
checkLub(B, A, Object_);
checkLub(B, B, B);
checkLub(B, C, B);
checkLub(B, S, Object_);
checkLub(B, T, B);
checkLub(B, U, B);
checkLub(B, V, B);
checkLub(B, W, B);
checkLub(B, X, B);
checkLub(C, Object_, Object_);
checkLub(C, A, Object_);
checkLub(C, B, B);
checkLub(C, C, C);
checkLub(C, S, Object_);
checkLub(C, T, B);
checkLub(C, U, C);
checkLub(C, V, B);
checkLub(C, W, B);
checkLub(C, X, B);
checkLub(S, Object_, Object_);
checkLub(S, A, A);
checkLub(S, B, Object_);
checkLub(S, C, Object_);
checkLub(S, S, S);
checkLub(S, T, Object_);
checkLub(S, U, Object_);
checkLub(S, V, Object_);
checkLub(S, W, Object_);
checkLub(S, X, Object_);
checkLub(T, Object_, Object_);
checkLub(T, A, Object_);
checkLub(T, B, B);
checkLub(T, C, B);
checkLub(T, S, Object_);
checkLub(T, T, T);
checkLub(T, U, B);
checkLub(T, V, T);
checkLub(T, W, T);
checkLub(T, X, T);
checkLub(U, Object_, Object_);
checkLub(U, A, Object_);
checkLub(U, B, B);
checkLub(U, C, C);
checkLub(U, S, Object_);
checkLub(U, T, B);
checkLub(U, U, U);
checkLub(U, V, B);
checkLub(U, W, B);
checkLub(U, X, B);
checkLub(V, Object_, Object_);
checkLub(V, A, Object_);
checkLub(V, B, B);
checkLub(V, C, B);
checkLub(V, S, Object_);
checkLub(V, T, T);
checkLub(V, U, B);
checkLub(V, V, V);
checkLub(V, W, V);
checkLub(V, X, T);
checkLub(W, Object_, Object_);
checkLub(W, A, Object_);
checkLub(W, B, B);
checkLub(W, C, B);
checkLub(W, S, Object_);
checkLub(W, T, T);
checkLub(W, U, B);
checkLub(W, V, V);
checkLub(W, W, W);
checkLub(W, X, T);
checkLub(X, Object_, Object_);
checkLub(X, A, Object_);
checkLub(X, B, B);
checkLub(X, C, B);
checkLub(X, S, Object_);
checkLub(X, T, T);
checkLub(X, U, B);
checkLub(X, V, T);
checkLub(X, W, T);
checkLub(X, X, X);
}));
}