blob: b437f65016a75b10d856c0865aa0edd74cf436ae [file] [log] [blame]
// 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.
/// @assertion We allow explicit instantiation of tear-offs and type literals, by allowing type arguments where we would otherwise do implicit instantiation of tear-offs, or after type literals. Examples:
///
/// typedef ListList<T> = List<List<T>>;
/// T top<T>(T value) => value;
/// class C {
/// static T stat<T>(T value) => value;
/// T inst<T>(T value) => value;
/// void method() {
/// var f1 = stat<int>;
/// var f1TypeName = stat<int>.runtimeType.toString();
/// var f2 = inst<int>;
/// var f2TypeName = inst<int>.runtimeType.toString();
/// var f3 = this.inst<int>;
/// var f3TypeName = this.inst<int>.runtimeType.toString();
/// }
/// }
/// mixin M on C {
/// static T mstat<T>(T value) => value;
/// T minst<T>(T value) => value;
/// void mmethod() {
/// var f1 = mstat<int>;
/// var f1TypeName = mstat<int>.runtimeType.toString();
/// var f2 = minst<int>;
/// var f2TypeName = minst<int>.runtimeType.toString();
/// var f3 = this.minst<int>;
/// var f3TypeName = this.minst<int>.runtimeType.toString();
/// }
/// }
/// extension Ext on C {
/// static T estat<T>(T value) => value;
/// T einst<T>(T value) => value;
/// void emethod() {
/// var f1 = estat<int>; // works like (int $) => Ext.estat<int>($)
/// var f1TypeName = estat<int>.runtimeType.toString();
/// var f2 = einst<int>; // works like (int $) => Ext(this).einst<int>($)
/// var f2TypeName = einst<int>.runtimeType.toString();
/// var f3 = this.einst<int>; // works like (int $) => Ext(this).einst<int>($)
/// var f3TypeName = this.einst<int>.runtimeType.toString();
/// }
/// }
/// class D extends C with M {
/// void method() {
/// var f4 = super.inst<int>; // works like (int $) => super.inst<int>($)
/// var f4TypeName = super.inst<int>.runtimeType.toString();
/// }
/// }
/// void main() {
/// // Type literals.
/// var t1 = List<int>; // Type object for `List<int>`.
/// var t2 = ListList<int>; // Type object for `List<List<int>>`.
///
/// // Instantiated function tear-offs.
/// T local<T>(T value) => value;
///
/// const f1 = top<int>; // int Function(int), works like (int $) => top<int>($);
/// const f2 = C.stat<int>; // int Function(int), works like (int $) => C.stat<int>($);
/// var f3 = local<int>; // int Function(int), works like (int $) => local<int>($);
/// var d = D();
/// var f4 = d.inst<int>; // int Function(int), works like (int $) => c.inst<int>($);
/// var f5 = d.minst<int>; // int Function(int), works like (int $) => c.minst<int>($);
/// var f6 = d.einst<int>; // int Function(int), works like (int $) => Ext(c).einst<int>($);
///
/// var typeName = List<int>.toString();
/// var functionTypeName = local<int>.runtimeType.toString();
/// }
///
/// @description Checks an example from the specification
/// @author sgrekhov@unipro.ru
// SharedOptions=--enable-experiment=constructor-tearoffs
import "../../Utils/expect.dart";
typedef ListList<T> = List<List<T>>;
T top<T>(T value) => value;
typedef int Func(int i);
class C {
static T stat<T>(T value) => value;
T inst<T>(T value) => value;
}
Type typeOf<X>() => X;
void main() {
// Type literals.
var t1 = List<int>; // Type object for `List<int>`.
Expect.isTrue(t1 is Type);
Expect.isFalse(t1 is Function);
Expect.runtimeIsType<Type>(t1);
Expect.runtimeIsNotType<Function>(t1);
Expect.isTrue(typeOf<List<int>>() == t1);
var t2 = ListList<int>; // Type object for `List<List<int>>`.
Expect.isTrue(t2 is Type);
Expect.isFalse(t2 is Function);
Expect.runtimeIsType<Type>(t2);
Expect.runtimeIsNotType<Function>(t2);
Expect.isTrue(typeOf<List<List<int>>>() == t2);
// Instantiated function tear-offs.
T local<T>(T value) => value;
const f1 = top<int>; // int Function(int), works like (int $) => top<int>($);
Expect.isTrue(f1 is Func);
Expect.runtimeIsType<Func>(f1);
const f2 = C.stat<int>; // int Function(int), works like (int $) => C.stat<int>($);
Expect.isTrue(f2 is Func);
Expect.runtimeIsType<Func>(f2);
var f3 = local<int>; // int Function(int), works like (int $) => local<int>($);
Expect.isTrue(f3 is Func);
Expect.runtimeIsType<Func>(f3);
var typeName = (List<int>).toString();
Expect.equals("List<int>", typeName);
var functionTypeName = local<int>.runtimeType.toString();
Expect.equals("(int) => int", functionTypeName);
}