// Copyright (c) 2016, 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.

// Check function subtyping of type arguments. These cases use typedefs as type
// arguments, and the typedefs have type parameters that are used more than
// once.

import 'package:expect/expect.dart';

typedef A F<A>(A arg1, A arg2);
typedef B G<A,B>(B arg1, B arg2);

typedef Set<A> FS<A>(Set<A> arg1, Set<A> arg2);

@NoInline() @AssumeDynamic() dyn(x) => x;

class CheckEnv<X, Y> {
  test(bool intX) {
    Expect.isTrue(<F<X>>[] is List<F>);
    Expect.isTrue(<F<X>>[] is List<F<X>>);
    Expect.isTrue(<F<X>>[] is List<G<Y,X>>);

    Expect.isTrue(dyn(<F<X>>[]) is List<F>);
    Expect.isTrue(dyn(<F<X>>[]) is List<F<X>>);
    Expect.isTrue(dyn(<F<X>>[]) is List<G<Y,X>>);

    Expect.isTrue(<F<X>>[] is! List<F<Y>>);
    Expect.isTrue(<F<X>>[] is! List<G<X,Y>>);

    Expect.isTrue(dyn(<F<X>>[]) is! List<F<Y>>);
    Expect.isTrue(dyn(<F<X>>[]) is! List<G<X,Y>>);

    Expect.isTrue(dyn(<FS<X>>[]) is List<FS>);
    Expect.isTrue(dyn(<FS<X>>[]) is List<FS<X>>);
    if (intX) {
      Expect.isTrue(dyn(<FS<X>>[]) is List<FS<int>>);
      Expect.isTrue(dyn(<FS<int>>[]) is List<FS<X>>);
      Expect.isTrue(dyn(<FS<Y>>[]) is! List<FS<int>>);
      Expect.isTrue(dyn(<FS<int>>[]) is! List<FS<Y>>);
    }
  }
}



main() {
  Expect.isTrue(<F<int>>[] is List<F<int>>);
  Expect.isTrue(dyn(<F<int>>[]) is List<F<int>>);
  Expect.isTrue(<F<int>>[] is List<G<bool,int>>);
  Expect.isTrue(dyn(<F<int>>[]) is List<G<bool,int>>);

  new CheckEnv<int,String>().test(true);
  new CheckEnv<String,int>().test(false);
}

Add language test with nested function typedef with two references to argument
Add language test with nested function typedef with two references to argument

R=sigmund@google.com

Review URL: https://codereview.chromium.org/2297783002 .
