Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #2127. Add tests for covariant-by-class parameters #2133

Merged
merged 3 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions Language/Classes/Instance_Methods/covariant_A03_t01.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) 2023, 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 For each parameter p of m where covariant is present, it is a
/// compile-time error if there exists a direct or indirect superinterface of C
/// which has an accessible method signature m′′ with the same name as m, such
/// that m′′ has a parameter p′′ that corresponds to p, unless the type of p is
/// a subtype or a supertype of the type of p′′
///
/// @description Checks that it is a compile-time error if there is a member
/// with a covariant-by-class parameter `p` and there is another member with the
/// same name but with the parameter which is a subtype of `p`
/// @author sgrekhov22@gmail.com

class A<T> {
void m(T t) {}
void set s(T t) {}
void operator +(T t) {}
}

class C extends A<num> {
void m(int a) {}
// ^
// [analyzer] unspecified
// [cfe] unspecified
void set s(int a) {}
// ^
// [analyzer] unspecified
// [cfe] unspecified

void operator +(int a) {}
// ^
// [analyzer] unspecified
// [cfe] unspecified
}

main() {
print(C);
}
30 changes: 30 additions & 0 deletions Language/Classes/Instance_Methods/covariant_A03_t02.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) 2023, 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 For each parameter p of m where covariant is present, it is a
/// compile-time error if there exists a direct or indirect superinterface of C
/// which has an accessible method signature m′′ with the same name as m, such
/// that m′′ has a parameter p′′ that corresponds to p, unless the type of p is
/// a subtype or a supertype of the type of p′′
///
/// @description Checks that it is not an error if there is a member with a
/// covariant-by-class parameter `p` and there is another member with the
/// same name but with the parameter which is a supertype of `p`
/// @author sgrekhov22@gmail.com

class A<T> {
void m(T t) {}
void set s(T t) {}
void operator +(T t) {}
}

class C extends A<num> {
void m(Object a) {}
void set s(Object? a) {}
void operator +(Object a) {}
}

main() {
print(C);
}
26 changes: 26 additions & 0 deletions Language/Classes/Instance_Methods/covariant_A04_t01.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) 2023, 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 For each parameter p of m where covariant is present, it is a
/// compile-time error if there exists a direct or indirect superinterface of C
/// which has an accessible method signature m′′ with the same name as m, such
/// that m′′ has a parameter p′′ that corresponds to p, unless the type of p is
/// a subtype or a supertype of the type of p′′
///
/// @description Checks static type of a torn-off method with a
/// covariant-by-class parameter
/// @author sgrekhov22@gmail.com

import "../../../Utils/static_type_helper.dart";

class A<T> {
void m1(T a) {}
void m2({required T a}) {}
}

main() {
A<num> a = A();
a.m1.expectStaticType<Exactly<void Function(num)>>();
a.m2.expectStaticType<Exactly<void Function({required num a})>>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2023, 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 Let o be an object, and let u be a fresh final variable bound to
/// o. The closurization of method f on object o is defined to be equivalent to:
/// • <X1 extends B′1, . . . , Xs extends B′s>
/// (T1 p1, . . . , Tn pn, {Tn+1 pn+1 = d1, . . . , Tn+k pn+k = dk}) =>
/// u.m<X1, . . . , Xs>(p1, . . . , pn, pn+1: pn+1, . . . , pn+k: pn+k);
/// where f is an instance method named m which has type parameter declarations
/// X1 extends B1, . . . , Xs extends Bs, required parameters p1, . . . , pn,
/// and named parameters pn+1, . . . , pn+k with defaults d1, . . . , dk.
///
/// • <X1 extends B′1, . . . , Xs extends B′s>
/// (T1 p1, . . . , Tn pn, [Tn+1 pn+1 = d1, . . . , Tn+k pn+k = dk]) =>
/// u.m<X1, . . . , Xs>(p1, . . . , pn+k);
/// where f is an instance method named m which has type parameter declarations
/// X1 extends B1, . . . , Xs extends Bs, required parameters p1, . . . , pn,
/// and optional positional parameters pn+1, . . . , pn+k with defaults
/// d1, . . . , dk.
/// ...
/// For each parameter pj , j ∈ 1..n + k, if pj is covariant then Tj is the
/// built-in class Object?.
///
/// @description Check that run-time type of covariant-by-declaration parameter
/// is `Object?`
/// @author sgrekhov22@gmail.com

import '../../../../Utils/expect.dart';

class A {
void m1(Object a) {}
void m2([num a = 0]) {}
void m3({Object a = 0}) {}
void m4({required num a}) {}
}

class C extends A {
void m1(covariant int a) {}
void m2([covariant int a = 1]) {}
void m3({covariant int a = 1}) {}
void m4({required covariant int a}) {}
}

main() {
C c = C();
Expect.isTrue(c.m1 is void Function(Object?));
Expect.isTrue(c.m2 is void Function([Object?]));
Expect.isTrue(c.m3 is void Function({Object? a}));
Expect.isTrue(c.m4 is void Function({required Object? a}));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) 2023, 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 Let o be an object, and let u be a fresh final variable bound to
/// o. The closurization of method f on object o is defined to be equivalent to:
/// • <X1 extends B′1, . . . , Xs extends B′s>
/// (T1 p1, . . . , Tn pn, {Tn+1 pn+1 = d1, . . . , Tn+k pn+k = dk}) =>
/// u.m<X1, . . . , Xs>(p1, . . . , pn, pn+1: pn+1, . . . , pn+k: pn+k);
/// where f is an instance method named m which has type parameter declarations
/// X1 extends B1, . . . , Xs extends Bs, required parameters p1, . . . , pn,
/// and named parameters pn+1, . . . , pn+k with defaults d1, . . . , dk.
///
/// • <X1 extends B′1, . . . , Xs extends B′s>
/// (T1 p1, . . . , Tn pn, [Tn+1 pn+1 = d1, . . . , Tn+k pn+k = dk]) =>
/// u.m<X1, . . . , Xs>(p1, . . . , pn+k);
/// where f is an instance method named m which has type parameter declarations
/// X1 extends B1, . . . , Xs extends Bs, required parameters p1, . . . , pn,
/// and optional positional parameters pn+1, . . . , pn+k with defaults
/// d1, . . . , dk.
/// ...
/// For each parameter pj , j ∈ 1..n + k, if pj is covariant then Tj is the
/// built-in class Object?.
///
/// @description Check that run-time type of covariant-by-class parameter is
/// `Object?`
/// @author sgrekhov22@gmail.com

import '../../../../Utils/expect.dart';

class C<T> {
void m1(T a) {}
void m2([T? a]) {}
void m3({T? a}) {}
void m4({required T a}) {}
}

main() {
C<int> c = C<int>();
Expect.isTrue(c.m1 is void Function(Object?));
Expect.isTrue(c.m2 is void Function([Object?]));
Expect.isTrue(c.m3 is void Function({Object? a}));
Expect.isTrue(c.m4 is void Function({required Object? a}));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) 2023, 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 Let o be an object, and let u be a fresh final variable bound to
/// o. The closurization of method f on object o is defined to be equivalent to:
/// • <X1 extends B′1, . . . , Xs extends B′s>
/// (T1 p1, . . . , Tn pn, {Tn+1 pn+1 = d1, . . . , Tn+k pn+k = dk}) =>
/// u.m<X1, . . . , Xs>(p1, . . . , pn, pn+1: pn+1, . . . , pn+k: pn+k);
/// where f is an instance method named m which has type parameter declarations
/// X1 extends B1, . . . , Xs extends Bs, required parameters p1, . . . , pn,
/// and named parameters pn+1, . . . , pn+k with defaults d1, . . . , dk.
///
/// • <X1 extends B′1, . . . , Xs extends B′s>
/// (T1 p1, . . . , Tn pn, [Tn+1 pn+1 = d1, . . . , Tn+k pn+k = dk]) =>
/// u.m<X1, . . . , Xs>(p1, . . . , pn+k);
/// where f is an instance method named m which has type parameter declarations
/// X1 extends B1, . . . , Xs extends Bs, required parameters p1, . . . , pn,
/// and optional positional parameters pn+1, . . . , pn+k with defaults
/// d1, . . . , dk.
/// ...
/// For each parameter pj , j ∈ 1..n + k, if pj is covariant then Tj is the
/// built-in class Object?.
///
/// @description Check that it is a run-time error if the run-time type of the
/// actual argument passed to a covariant-by-class parameter is not a subtype of
/// the declared type of that parameter
/// @author sgrekhov22@gmail.com

import '../../../../Utils/expect.dart';

class C<T> {
void m1(T a) {}
void m2([T? a]) {}
void m3({T? a}) {}
void m4({required T a}) {}
}

main() {
C<int> c = C<int>();
dynamic d1 = c.m1;
Expect.throws(() {
d1(Object());
});
d1(42);
dynamic d2 = c.m2;
Expect.throws(() {
d2(Object());
});
d2(42);
dynamic d3 = c.m3;
Expect.throws(() {
d3(a: Object());
});
d3(a: 42);
dynamic d4 = c.m4;
Expect.throws(() {
d4(a: Object());
});
d4(a: 42);
}