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

// SharedOptions=--enable-experiment=constructor-tearoffs

import "package:expect/expect.dart";

import "../static_type_helper.dart";

// Tests that generic methods can be torn off with explicit instantiation.

R toplevel<R, T>(T value, [T? other]) => value as R;

class C {
  static R staticMethod<R, T>(T value, [T? other]) => value as R;
  R instanceMethod<R, T>(T value, [T? other]) => value as R;

  void tearOffsOnThis() {
    const staticTearOff = staticMethod<int, String>;
    staticMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
    instanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
    this.instanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();

    Expect.identical(staticMethod<int, String>, staticTearOff);

    Expect.equals(
        instanceMethod<int, String>, this.instanceMethod<int, String>);
  }
}

mixin M on C {
  static R staticMethod<R, T>(T value, [T? other]) => value as R;
  R mixinInstanceMethod<R, T>(T value, [T? other]) => value as R;

  void mixinTearOffsOnThis() {
    const staticTearOff = staticMethod<int, String>;
    staticMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
    mixinInstanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
    this.mixinInstanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();

    Expect.identical(staticMethod<int, String>, staticTearOff);

    Expect.equals(
        mixinInstanceMethod<int, String>,
        this.mixinInstanceMethod<int, String>);
  }
}

extension E on C {
  static R staticMethod<R, T>(T value, [T? other]) => value as R;
  R extInstanceMethod<R, T>(T value, [T? other]) => value as R;

  void extensionTearOffsOnThis() {
    const staticTearOff = staticMethod<int, String>;
    staticMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
    extInstanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
    this.extInstanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();

    Expect.identical(staticMethod<int, String>, staticTearOff);

    Expect.equals(
        extInstanceMethod<int, String>, this.extInstanceMethod<int, String>);
  }
}

class D extends C with M {
  void tearOffsOnSuper() {
    super.instanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
    Expect.equals(
        super.instanceMethod<int, String>, super.instanceMethod<int, String>);
  }
}

void main() {
  var o = D();
  R local<R, T>(T value, [T? other]) => value as R;

  // Check that some tear-offs are constant.
  const topTearOff = toplevel<int, String>;
  const staticTearOff = C.staticMethod<int, String>;
  const mixinStaticTearOff = M.staticMethod<int, String>;
  const extensionStaticTearOff = E.staticMethod<int, String>;

  // Check that the tear-offs have the correct static type.

  toplevel<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
  C
      .staticMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
  M
      .staticMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
  E
      .staticMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
  o
      .instanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
  o
      .mixinInstanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
  o
      .extInstanceMethod<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();
  local<int, String>
      .expectStaticType<Exactly<int Function(String, [String?])>>();

  // Check that the tear-offs are canonicalized where possible.
  Expect.identical(toplevel<int, String>, topTearOff);
  Expect.identical(C.staticMethod<int, String>, staticTearOff);
  Expect.identical(M.staticMethod<int, String>, mixinStaticTearOff);
  Expect.identical(E.staticMethod<int, String>, extensionStaticTearOff);

  // Instantiated local methods may or may not be equal.
  // (Specification makes no promise about equality.).

  // But not for instance method tear-off.
  // Specification requires equality.
  Expect.equals(
      o.instanceMethod<int, String>, o.instanceMethod<int, String>);
  Expect.equals(
      o.mixinInstanceMethod<int, String>, o.mixinInstanceMethod<int, String>);
  Expect.equals(
      o.extInstanceMethod<int, String>, o.extInstanceMethod<int, String>);

  // And not canonicalized where they shouldn't (different types).
  Expect.notEquals(toplevel<int, String>, toplevel<num, String>);
  Expect.notEquals(
      C.staticMethod<int, String>, C.staticMethod<num, String>);
  Expect.notEquals(local<int, String>, local<num, String>);
  Expect.notEquals(
      o.instanceMethod<int, String>, o.instanceMethod<num, String>);

  (<T>() {
    // Not canonicalized if any type is non-constant.
    // Toplevel, static and instance members are still equal
    // if types are "the same".
    // (Current implementations do not implement that).
    Expect.equals(toplevel<T, String>, toplevel<T, String>);
    Expect.equals(C.staticMethod<T, String>, C.staticMethod<T, String>);
    Expect.equals(M.staticMethod<T, String>, M.staticMethod<T, String>);
    Expect.equals(E.staticMethod<T, String>, E.staticMethod<T, String>);
    Expect.notEquals(local<T, String>, local<T, String>);
    Expect.equals(toplevel<int, T>, toplevel<int, T>);
    Expect.equals(C.staticMethod<int, T>, C.staticMethod<int, T>);
    Expect.equals(M.staticMethod<int, T>, M.staticMethod<int, T>);
    Expect.equals(E.staticMethod<int, T>, E.staticMethod<int, T>);
    Expect.notEquals(local<int, T>, local<int, T>);
  }<int>());

  o.tearOffsOnThis();
  o.tearOffsOnSuper();
  o.mixinTearOffsOnThis();
  o.extensionTearOffsOnThis();
}
