// TODO(multitest): This was automatically migrated from a multitest and may
// contain strange or dead code.

// @dart = 2.9

// Copyright (c) 2017, 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 verifies that for a local async function, the following three
// types are all appropriately matched:
// - The static return type
// - The return type of reified runtime type of a tearoff of the function or
//   method
// - The reified type of the future returned by the function or method
//
// Specific attention is paid to the following conditions:
// - The static return type is determined by type inference
// - The static return type is `dynamic`
// - The function or method immediately returns a value or future with a
//   different type (possibly using `=>` syntax)

import 'dart:async';

import 'package:expect/expect.dart';

class A {}

class B extends A {}

class B2 extends A {}

Future quick() async {}

Future<B> futureB() => new Future<B>.value(new B());

void checkDynamic(dynamic tearoff) {
  Expect.isTrue(tearoff is dynamic Function());
  Expect.isFalse(tearoff is Future<dynamic> Function());
  dynamic f = tearoff();
  Expect.isTrue(f is Future<dynamic>);
  Expect.isFalse(f is Future<A>);
}

void checkFutureObject(dynamic tearoff) {
  Expect.isTrue(tearoff is Future<Object> Function());
  Expect.isFalse(tearoff is Future<A> Function());
  dynamic f = tearoff();
  Expect.isTrue(f is Future<Object>);
  Expect.isFalse(f is Future<A>);
}

void checkFutureA(dynamic tearoff) {
  Expect.isTrue(tearoff is Future<A> Function());
  Expect.isFalse(tearoff is Future<B> Function());
  dynamic f = tearoff();
  Expect.isTrue(f is Future<A>);
  Expect.isFalse(f is Future<B>);
}

main() {
  f_inferred_futureObject() async {
    await quick();
    if (false) {
      return 0;
    } else {
      return new A();
    }
  }

  f_inferred_A() async {
    await quick();
    if (false) {
      return new A();
    } else {
      return new B();
    }
  }

  dynamic f_dynamic() async {
    await quick();
    return new B();
  }

  Future<A> f_A() async {
    await quick();
    return new B();
  }

  Future<A> f_immediateReturn_B() async {
    return new B();
  }

  Future<A> f_immediateReturn_FutureB() async {
    return futureB();
  }

  Future<A> f_expressionSyntax_B() async => new B();

  Future<A> f_expressionSyntax_FutureB() async => futureB();

  // Not executed
  void checkStaticTypes() {
    // Check that f_inferred_futureObject's static return type is
    // `Future<Object>`, by verifying that its return value can be assigned to
    // `Future<int>` but not `int`.
    Future<int> v1 = f_inferred_futureObject();


    // Check that f_inferred_A's static return type is `Future<A>`, by verifying
    // that its return value can be assigned to `Future<B2>` but not
    // `Future<int>`.
    Future<B2> v3 = f_inferred_A();

  }

  checkFutureObject(f_inferred_futureObject);
  checkFutureA(f_inferred_A);
  checkDynamic(f_dynamic);
  checkFutureA(f_A);
  checkFutureA(f_immediateReturn_B);
  checkFutureA(f_immediateReturn_FutureB);
  checkFutureA(f_expressionSyntax_B);
  checkFutureA(f_expressionSyntax_FutureB);
}
