| // 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. |
| |
| // This test checks that the greatest lower bound between two types is |
| // calculated correctly, in case one of them is a FutureOr. |
| |
| import 'dart:async'; |
| |
| class Foo {} |
| |
| // ----------------------------------------------------------------------------- |
| |
| // Tests rule GLB(FutureOr<A>, B) == GLB(A, B). |
| void func1<T extends Foo>(T t) { |
| // Here and in the test cases below 'context' provides the typing context via |
| // the type of its parameter. The context is imposed onto the return type of |
| // 'expr' that is a type-parameter type. It leads to evaluation of GLB of the |
| // typing context and the bound of the type parameter. The computed GLB is |
| // inserted as both the type argument and the return type of 'expr' by the |
| // type inference. |
| void context(FutureOr<T> x) {} |
| S expr<S extends Foo>() => /*Null*/ null; |
| |
| // Type of the expression is GLB(FutureOr<T>, Foo) = T. |
| /*invoke: void*/ context(/*invoke: T*/ expr/*<T>*/()); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| // Tests rule GLB(FutureOr<A>, Future<B>) == Future<GLB(A, B)>. |
| void func2<T extends Foo>() { |
| void context(FutureOr<T> x) {} |
| S expr<S extends Future<Foo>>() => /*Null*/ null; |
| |
| // Type of the expression is GLB(FutureOr<T>, Future<Foo>) = Future<T>. |
| /*invoke: void*/ context(/*invoke: Future<T>*/ expr/*<Future<T>>*/()); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| // Tests rule GLB(A, FutureOr<B>) == GLB(B, A). |
| void func3<T extends Foo>() { |
| void context(T x) {} |
| S expr<S extends FutureOr<Foo>>() => /*Null*/ null; |
| |
| // Type of the expression is GLB(T, FutureOr<Foo>) = T. |
| /*invoke: void*/ context(/*invoke: T*/ expr/*<T>*/()); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| // Tests rule GLB(Future<A>, FutureOr<B>) == Future<GLB(B, A)>. |
| void func4<T extends Foo>() { |
| void context(Future<T> x) {} |
| S expr<S extends FutureOr<Foo>>() => /*Null*/ null; |
| |
| // Type of the expression is GLB(Future<T>, FutureOr<Foo>) = Future<T>. |
| /*invoke: void*/ context(/*invoke: Future<T>*/ expr/*<Future<T>>*/()); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| // Tests rule GLB(FutureOr<A>, FutureOr<B>) == FutureOr<GLB(A, B)> in the |
| // non-trivial case when neither A <: B, nor B <: A. |
| void func5<T extends Foo>() { |
| void context(FutureOr<FutureOr<T>> x) {} |
| S expr<S extends FutureOr<Future<Foo>>>() => /*Null*/ null; |
| |
| // Type of the expression is GLB(FutureOr<FutureOr<T>>, FutureOr<Future<Foo>>) |
| // = FutureOr<Future<T>>. |
| /*invoke: void*/ context( |
| /*invoke: FutureOr<Future<T>>*/ expr/*<FutureOr<Future<T>>>*/()); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| |
| main() {} |