blob: 28a2f6213a5d6994607743d9cb56786c410d9a76 [file] [log] [blame]
// Copyright (c) 2019, 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.
// Testing that i2b and checks for correct super-boundedness are applied
// to type arguments, taking the variance of type parameters into account.
// Standard type comparison support.
typedef F<X> = void Function<Y extends X>();
F<X> toF<X>(X x) => null;
// Material specific to this test.
typedef Fcov<X> = X Function();
typedef Fcon<X> = Function(X);
typedef Finv<X> = X Function(X);
class Acov<X extends Fcov<Y>, Y> {}
class Acon<X extends Fcon<Y>, Y> {}
class Ainv<X extends Finv<Y>, Y> {}
typedef FcovBound<X extends num> = X Function();
typedef FconBound<X extends num> = Function(X);
typedef FinvBound<X extends num> = X Function(X);
class AcovBound<X extends FcovBound<Y>, Y extends num> {}
class AconBound<X extends FconBound<Y>, Y extends num> {}
class AinvBound<X extends FinvBound<Y>, Y extends num> {}
class A<X> {}
typedef FcovCyclicBound<X extends A<X>> = X Function();
typedef FconCyclicBound<X extends A<X>> = Function(X);
typedef FinvCyclicBound<X extends A<X>> = X Function(X);
class AcovCyclicBound<X extends FcovCyclicBound<Y>, Y extends A<Y>> {}
class AconCyclicBound<X extends FconCyclicBound<Y>, Y extends A<Y>> {}
class AinvCyclicBound<X extends FinvCyclicBound<Y>, Y extends A<Y>> {}
typedef FcovCyclicCoBound<X extends Function(X)> = X Function();
typedef FconCyclicCoBound<X extends Function(X)> = Function(X);
typedef FinvCyclicCoBound<X extends Function(X)> = X Function(X);
class AcovCyclicCoBound<X extends FcovCyclicCoBound<Y>, Y extends Function(Y)> {
}
class AconCyclicCoBound<X extends FconCyclicCoBound<Y>, Y extends Function(Y)> {
}
class AinvCyclicCoBound<X extends FinvCyclicCoBound<Y>, Y extends Function(Y)> {
}
class B<X> {}
void testTypeAliasAsTypeArgument() {
// I2b: Use bounds (Fcov<Y>, dynamic), then replace covariant occurrence
// (of `Y` in `Acov<Fcov<Y>, _>`) by `Y`s value `dynamic`. Resulting type
// `Acov<Fcov<dynamic>, dynamic>` is regular-bounded.
Acov source1;
var fsource1 = toF(source1);
F<Acov<Fcov<dynamic>, dynamic>> target1 = fsource1;
// I2b: Use bounds (Fcon<Y>, dynamic), then replace contravariant occurrence
// (of `Y` in `Acon<Fcon<Y>, _>`) by `Null`. Resulting type
// is super-bounded: Acon<Fcon<Object>, Null> is regular-bounded.
Acon source2;
var fsource2 = toF(source2);
F<Acon<Fcon<Null>, dynamic>> target2 = fsource2;
// I2b: Use bounds (Finv<Y>, dynamic) then replace invariant occurrence
// (of `Y` in `Ainv<Finv<Y>, _>`) by `Y`s value `dynamic`. Resulting type
// `Ainv<Finv<dynamic>, dynamic>` is regular-bounded.
Ainv source3;
var fsource3 = toF(source3);
F<Ainv<Finv<dynamic>, dynamic>> target3 = fsource3;
// I2b: Use bounds (FcovBound<Y>, num), then replace covariant occurrence
// (of `Y` in `AcovBound<FcovBound<Y>, _>`) by `Y`s value `num`.
// Resulting type `AcovBound<FcovBound<num>, num>` is regular-bounded.
AcovBound source4;
var fsource4 = toF(source4);
F<AcovBound<FcovBound<num>, num>> target4 = fsource4;
// I2b: Use bounds (FconBound<Y>, num), then replace contravariant occurrence
// of `Y` in `AconBound<FconBound<Y>, _>` by `Null`. Resulting type is
// super-bounded: AconBound<FconBound<Object>, num> is regular-bounded.
AconBound source5;
var fsource5 = toF(source5);
F<AconBound<FconBound<Null>, num>> target5 = fsource5;
// I2b: Use bounds (FinvBound<Y>, num), then replace invariant occurrence
// of `Y` in `AinvBound<FinvBound<Y>, _>` by `Y`s value `num`. Resulting
// type `AinvBound<FinvBound<num>, num>` is regular-bounded.
AinvBound source6;
var fsource6 = toF(source6);
F<AinvBound<FinvBound<num>, num>> target6 = fsource6;
// I2b: Use bounds (FcovCyclicBound<Y>, A<Y>), then break cycle {Y} by
// replacing covariant occurrence of `Y` in `AcovCyclicBound<_, A<Y>>`
// by `dynamic`; then replace covariant occurrence of `Y` in
// `AcovCyclicBound<FcovCyclicBound<Y>, _>` by `Y`s value `A<dynamic>`.
// Resulting type `AcovCyclicBound<FcovCyclicBound<A<dynamic>>, A<dynamic>>>`
// is regular-bounded.
AcovCyclicBound source7;
var fsource7 = toF(source7);
F<AcovCyclicBound<FcovCyclicBound<A<dynamic>>, A<dynamic>>> target7 =
fsource7;
// I2b: Use bounds (FconCyclicBound<Y>, A<Y>), then break cycle {Y} by
// replacing covariant occurrence of `Y` in `AconCyclicBound<_, A<Y>>`
// by `dynamic`; then replace contravariant occurrence of `Y` in
// `AconCyclicBound<FconCyclicBound<Y>, _>` by `Null`.
// Resulting type `AconCyclicBound<FconCyclicBound<Null>, A<dynamic>>>` is
// super-bounded because `AconCyclicBound<FconCyclicBound<Object>, A<Null>>>`
// is regular-bounded.
AconCyclicBound source8;
var fsource8 = toF(source8);
F<AconCyclicBound<FconCyclicBound<Null>, A<dynamic>>> target8 = fsource8;
// I2b: Use bounds (FinvCyclicBound<Y>, A<Y>), then break cycle {Y} by
// replacing covariant occurrence of `Y` in `AinvCyclicBound<_, A<Y>>`
// by `dynamic`; then replace invariant occurrence of `Y` in
// `AinvCyclicBound<FinvCyclicBound<Y>, _>` by `Y`s value `A<dynamic>`.
// Resulting type `AinvCyclicBound<FinvCyclicBound<A<dynamic>>, A<dynamic>>>`
// looks regular-bounded, but contains `FinvCyclicBound<A<dynamic>>` which
// is not well-bounded.
AinvCyclicBound source9; //# 01: compile-time error
// var fsource9 = toF(source9);
// F<AinvCyclicBound<FinvCyclicBound<A<dynamic>>, A<dynamic>>> target9 =
// fsource9;
// I2b: Use bounds (FcovCyclicCoBound<Y>, Function(Y)), then break cycle {Y}
// by replacing contravariant occurrence of `Y` in
// `AcovCyclicCoBound<_, Function(Y)>` by `Null`; then replace covariant
// occurrence of `Y` in `AcovCyclicCoBound<FcovCyclicCoBound<Y>, _>` by `Y`s
// value `Function(Null)`. Resulting type
// `AcovCyclicCoBound<FcovCyclicCoBound<Function(Null)>, Function(Null)>`
// is regular-bounded, with subterm `FcovCyclicCoBound<Function(Null)>` which
// is super-bounded because `FcovCyclicCoBound<Function(Object)>` is
// regular-bounded.
AcovCyclicCoBound source10;
var fsource10 = toF(source10);
F<AcovCyclicCoBound<FcovCyclicCoBound<Function(Null)>, Function(Null)>>
target10 = fsource10;
// I2b: Use bounds (FconCyclicCoBound<Y>, Function(Y)), then break cycle {Y}
// by replacing contravariant occurrence of `Y` in
// `AconCyclicCoBound<_, Function(Y)>` by `Null`; then replace contravariant
// occurrence of `Y` in `AconCyclicCoBound<FconCyclicCoBound<Y>, _>` by
// `Null`. Resulting type
// `AconCyclicCoBound<FconCyclicCoBound<Null>, Function(Null)>` is
// super-bounded because
// `AconCyclicCoBound<FconCyclicCoBound<Object>, Function(Object)>` is
// regular-bounded.
AconCyclicCoBound source11;
var fsource11 = toF(source11);
F<AconCyclicCoBound<FconCyclicCoBound<Null>, Function(Null)>> target11 =
fsource11;
// I2b: Use bounds (FinvCyclicCoBound<Y>, Function(Y)), then break cycle {Y}
// by replacing contravariant occurrence of `Y` in
// `AinvCyclicCoBound<_, Function(Y)>` by `Null`; then replace invariant
// occurrence of `Y` in `AinvCyclicCoBound<FinvCyclicCoBound<Y>, _>` by `Y`s
// value `Function(Null)`.
// Resulting type
// `AinvCyclicCoBound<FinvCyclicCoBound<Function(Null)>, Function(Null)>>`
// looks regular-bounded, but contains `FinvCyclicCoBound<Function(Null)>`
// which is not well-bounded.
AinvCyclicCoBound source12; //# 02: compile-time error
// var fsource12 = toF(source12);
// F<AinvCyclicCoBound<FinvCyclicCoBound<Function(Null)>, Function(Null)>>
// target12 = fsource12;
}
void testNested() {
// Everything gets the same treatment when the cases from `testTopLevel`
// are duplicated at the nested level in a covariant position.
B<Acov> source1;
var fsource1 = toF(source1);
F<B<Acov<Fcov<dynamic>, dynamic>>> target1 = fsource1;
B<Acon> source2;
var fsource2 = toF(source2);
F<B<Acon<Fcon<Null>, dynamic>>> target2 = fsource2;
B<Ainv> source3;
var fsource3 = toF(source3);
F<B<Ainv<Finv<dynamic>, dynamic>>> target3 = fsource3;
B<AcovBound> source4;
var fsource4 = toF(source4);
F<B<AcovBound<FcovBound<num>, num>>> target4 = fsource4;
B<AconBound> source5;
var fsource5 = toF(source5);
F<B<AconBound<FconBound<Null>, num>>> target5 = fsource5;
B<AinvBound> source6;
var fsource6 = toF(source6);
F<B<AinvBound<FinvBound<num>, num>>> target6 = fsource6;
B<AcovCyclicBound> source7;
var fsource7 = toF(source7);
F<B<AcovCyclicBound<FcovCyclicBound<A<dynamic>>, A<dynamic>>>> target7 =
fsource7;
B<AconCyclicBound> source8;
var fsource8 = toF(source8);
F<B<AconCyclicBound<FconCyclicBound<Null>, A<dynamic>>>> target8 = fsource8;
B<AinvCyclicBound> source9; //# 03: compile-time error
// var fsource9 = toF(source9);
// F<B<AinvCyclicBound<FinvCyclicBound<A<dynamic>>, A<dynamic>>>> target9 =
// fsource9;
B<AcovCyclicCoBound> source10;
var fsource10 = toF(source10);
F<B<AcovCyclicCoBound<FcovCyclicCoBound<Function(Null)>, Function(Null)>>>
target10 = fsource10;
B<AconCyclicCoBound> source11;
var fsource11 = toF(source11);
F<B<AconCyclicCoBound<FconCyclicCoBound<Null>, Function(Null)>>> target11 =
fsource11;
B<AinvCyclicCoBound> source12; //# 04: compile-time error
// var fsource12 = toF(source12);
// F<B<AinvCyclicCoBound<FinvCyclicCoBound<Function(Null)>, Function(Null)>>>
// target12 = fsource12;
}
main() {
testTypeAliasAsTypeArgument();
testNested();
}