Skip to content

Commit

Permalink
dart-lang#2350. Add/update factory constructor tests. Part 4
Browse files Browse the repository at this point in the history
  • Loading branch information
sgrekhov committed Nov 13, 2023
1 parent 36f6ee9 commit 830714d
Show file tree
Hide file tree
Showing 14 changed files with 447 additions and 36 deletions.
48 changes: 48 additions & 0 deletions Language/Classes/Constructors/Factories/function_type_t06.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// 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 Assume that C<X1 extends B1 . . . , Xm extends Bm> is the name
/// and formal type parameters of the enclosing class, const? is const or empty,
/// N is C or C.id0 for some identifier id0, and id is an identifier, then
/// consider a declaration of a redirecting factory constructor k of one of the
/// forms
/// const? factory
/// N(T1 x1 . . . , Tn xn, [Tn+1 xn+1=d1, . . . , Tn+k xn+k=dk]) = R;
/// const? factory
/// N(T1 x1 . . . , Tn xn, {Tn+1 xn+1=d1, . . . , Tn+k xn+k=dk}) = R;
/// where R is of one of the forms T<S1 . . . , Sp> or T<S1 . . . , Sp>.id.
/// ...
/// The redirectee constructor for this declaration is the constructor k′
/// denoted by R.
/// ...
/// It is a compile error if the function type of k' is not a subtype of the
/// type of k.
///
/// @description Checks that it is a compile-time error is if a factory
/// constructor redirects to a null
/// @author sgrekhov22@gmail.com
// SharedOptions=--enable-experiment=inline-class

class F {
factory F(x) = null;
// ^^^^
// [analyzer] unspecified
// [cfe] unspecified
}

enum E {
e1, e2;
const E();

factory E.f() = null;
// ^^^^
// [analyzer] unspecified
// [cfe] unspecified
}

main() {
print(F);
print(E);
}
52 changes: 52 additions & 0 deletions Language/Classes/Constructors/Factories/parameter_type_t01.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// 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 the dynamic semantics, assume that k is a redirecting factory
/// constructor and k′ is the redirectee of k
///
/// It is a dynamic type error if an actual argument passed in an invocation of
/// k is not a subtype of the actual type of the corresponding formal parameter
/// in the declaration of k.
///
/// @description Checks that it is a dynamic type error if an actual argument
/// type of a redirecting factory constructor call is not a subtype of the
/// actual type of its corresponding formal parameter.
/// @author sgrekhov22@gmail.com
import "../../../../Utils/expect.dart";

class F {
factory F(num x) = C;
factory F.foo(num x, [num y]) = C.foo;
factory F.bar(num x, {num z}) = C.bar;
}

class C implements F {
num x, y = 1, z = 2;

C(this.x);
C.foo(this.x, [this.y = 1]);
C.bar(this.x, {this.z = 2});
}

enum E {
e1, e2;
const E();

factory E.g1(num x) => E.e1;
factory E.g2(num x, [num y = 1]) => E.e1;
factory E.g3(num x, {num z = 2}) => E.e1;
factory E.f1(num x) = E.g1;
factory E.f2(num x, [num y]) = E.g2;
factory E.f3(num x, {num z}) = E.g3;
}

main() {
Expect.throws(() {F(Object() as dynamic);});
Expect.throws(() {F.foo(42, Object() as dynamic);});
Expect.throws(() {F.bar(3.14, z: Object() as dynamic);});
Expect.throws(() {E.f1(Object() as dynamic);});
Expect.throws(() {E.f2(42, Object() as dynamic);});
Expect.throws(() {E.f3(3.14, z: Object() as dynamic);});
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@
// 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 Calling a redirecting factory constructor k causes the
/// constructor k' denoted by type (respectively, type.identifier) to be called
/// with the actual arguments passed to k, and returns the result of k' as the
/// result of k. The resulting constructor call is governed by the same rules
/// as an instance creation expression using new.
/// @assertion For the dynamic semantics, assume that k is a redirecting factory
/// constructor and k′ is the redirectee of k
/// ...
/// When the redirectee k′ is a generative constructor, let o be a
/// fresh instance of the class that contains k′. Execution of k then amounts to
/// execution of k′ to initialize o, governed by the same rules as an instance
/// creation expression. If k′ completed normally then the execution of k
/// completes normally returning o, otherwise k completes by throwing the
/// exception and stack trace thrown by k′.
///
/// @description Checks that a call to redirecting factory constructor indeed
/// results in a call to referenced constructor with the same actual arguments.
/// @author ilya
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@
// 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 Calling a redirecting factory constructor k causes the
/// constructor k' denoted by type (respectively, type.identifier) to be called
/// with the actual arguments passed to k, and returns the result of k' as the
/// result of k. The resulting constructor call is governed by the same rules
/// as an instance creation expression using new.
/// @assertion For the dynamic semantics, assume that k is a redirecting factory
/// constructor and k′ is the redirectee of k
/// ...
/// When the redirectee k′ is a generative constructor, let o be a
/// fresh instance of the class that contains k′. Execution of k then amounts to
/// execution of k′ to initialize o, governed by the same rules as an instance
/// creation expression. If k′ completed normally then the execution of k
/// completes normally returning o, otherwise k completes by throwing the
/// exception and stack trace thrown by k′.
///
/// @description Checks that compile error occurs when referenced type is not
/// defined or refers to non class or non constructor.
/// @author ilya

function() {}
var variable;

Expand Down Expand Up @@ -39,4 +43,5 @@ class D {
}

main() {
print(F);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@
// 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 Calling a redirecting factory constructor k causes the
/// constructor k' denoted by type (respectively, type.identifier) to be called
/// with the actual arguments passed to k, and returns the result of k' as the
/// result of k. The resulting constructor call is governed by the same rules
/// as an instance creation expression using new.
/// @assertion For the dynamic semantics, assume that k is a redirecting factory
/// constructor and k′ is the redirectee of k
/// ...
/// When the redirectee k′ is a generative constructor, let o be a
/// fresh instance of the class that contains k′. Execution of k then amounts to
/// execution of k′ to initialize o, governed by the same rules as an instance
/// creation expression. If k′ completed normally then the execution of k
/// completes normally returning o, otherwise k completes by throwing the
/// exception and stack trace thrown by k′.
///
/// @description Checks that a call to redirecting factory constructor indeed
/// results in a call to referenced constructor with the same actual arguments.
/// Test type aliases
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
/// @assertion A redirecting factory constructor specifies a call to a
/// constructor of another class that is to be used whenever the redirecting
/// constructor is called.
/// redirectingFactoryConstructorSignature:
/// const? factory identifier (‘.’ identifier)? formalParameterList
/// ‘=’ typeName (‘.’ identifier)?
/// ;
/// ⟨redirectingFactoryConstructorSignature⟩ ::=
/// const? factory ⟨constructorName⟩ ⟨formalParameterList⟩ ‘=’
/// ⟨constructorDesignation⟩
/// ⟨constructorDesignation⟩ ::= ⟨typeIdentifier⟩
/// | ⟨qualifiedName⟩
/// | ⟨typeName⟩ ⟨typeArguments⟩ (‘.’ ⟨identifier⟩)?
///
/// @description Checks that correct declarations of redirecting factory
/// constructors do not cause errors.
/// @author kaigorodov
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
/// @assertion A redirecting factory constructor specifies a call to a
/// constructor of another class that is to be used whenever the redirecting
/// constructor is called.
/// redirectingFactoryConstructorSignature:
/// const? factory identifier (‘.’ identifier)? formalParameterList
/// ‘=’ typeName (‘.’ identifier)?
/// ;
/// ⟨redirectingFactoryConstructorSignature⟩ ::=
/// const? factory ⟨constructorName⟩ ⟨formalParameterList⟩ ‘=’
/// ⟨constructorDesignation⟩
/// ⟨constructorDesignation⟩ ::= ⟨typeIdentifier⟩
/// | ⟨qualifiedName⟩
/// | ⟨typeName⟩ ⟨typeArguments⟩ (‘.’ ⟨identifier⟩)?
///
/// @description Checks that formal parameters list of redirecting factory
/// constructor can not be omitted
/// @author ilya

class A {
A() {}
factory A.foo = C;
Expand All @@ -25,6 +27,18 @@ class A {
class C extends A {
}

enum E {
e1, e2;
const E();

factory E.f1() => E.e1;
factory E.f2 = E.f1;
// ^
// [analyzer] unspecified
// [cfe] unspecified
}

main() {
new A.foo();
print(A);
print(E);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
/// @assertion A redirecting factory constructor specifies a call to a
/// constructor of another class that is to be used whenever the redirecting
/// constructor is called.
/// redirectingFactoryConstructorSignature:
/// const? factory identifier (‘.’ identifier)? formalParameterList
/// ‘=’ typeName (‘.’ identifier)?
/// ;
/// ⟨redirectingFactoryConstructorSignature⟩ ::=
/// const? factory ⟨constructorName⟩ ⟨formalParameterList⟩ ‘=’
/// ⟨constructorDesignation⟩
/// ⟨constructorDesignation⟩ ::= ⟨typeIdentifier⟩
/// | ⟨qualifiedName⟩
/// | ⟨typeName⟩ ⟨typeArguments⟩ (‘.’ ⟨identifier⟩)?
///
/// @description Checks that parameters list can not occur after another class
/// constructor name
/// @author ilya

class A {
A() {}
factory A.foo() = C();
Expand All @@ -27,6 +29,18 @@ class C extends A {
// [analyzer] unspecified
}

enum E {
e1, e2;
const E();

factory E.f1() => E.e1;
factory E.f2() = E.f1();
// ^^^^^
// [analyzer] unspecified
// [cfe] unspecified
}

main() {
new A.foo();
print(A);
print(E);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
/// @assertion A redirecting factory constructor specifies a call to a
/// constructor of another class that is to be used whenever the redirecting
/// constructor is called.
/// redirectingFactoryConstructorSignature:
/// const? factory identifier (‘.’ identifier)? formalParameterList
/// ‘=’ typeName (‘.’ identifier)?
/// ;
/// ⟨redirectingFactoryConstructorSignature⟩ ::=
/// const? factory ⟨constructorName⟩ ⟨formalParameterList⟩ ‘=’
/// ⟨constructorDesignation⟩
/// ⟨constructorDesignation⟩ ::= ⟨typeIdentifier⟩
/// | ⟨qualifiedName⟩
/// | ⟨typeName⟩ ⟨typeArguments⟩ (‘.’ ⟨identifier⟩)?
///
/// @description Checks that correct declarations of redirecting factory
/// constructors do not cause errors. Test type aliases
/// @author sgrekhov@unipro.ru
Expand All @@ -35,7 +38,17 @@ class D extends CAlias {
}
typedef DAlias = D;

enum E {
e1, e2;
const E();

factory E.f1() => E.e1;
factory E.f2() = EAlias.f1;
}
typedef EAlias = E;

main() {
A a = new A.foo();
Expect.equals(2, a.m());
Expect.identical(E.e1, E.f2());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// 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 A redirecting factory constructor specifies a call to a
/// constructor of another class that is to be used whenever the redirecting
/// constructor is called.
/// ⟨redirectingFactoryConstructorSignature⟩ ::=
/// const? factory ⟨constructorName⟩ ⟨formalParameterList⟩ ‘=’
/// ⟨constructorDesignation⟩
/// ⟨constructorDesignation⟩ ::= ⟨typeIdentifier⟩
/// | ⟨qualifiedName⟩
/// | ⟨typeName⟩ ⟨typeArguments⟩ (‘.’ ⟨identifier⟩)?
///
/// @description Checks that it is a compile-time error if any parameter of the
/// factory constructor has modifier `covariant`
/// @author sgrekhov22@gmail.com
/// @issue 54030
class F {
factory F(covariant num x) = C;
// ^^^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified
factory F.f1(num x, [covariant num y]) = C.f1;
// ^^^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified
factory F.f2(num x, {covariant num z}) = C.f2;
// ^^^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified
factory F.f3(num x, {required covariant num z}) = C.f3;
// ^^^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified
}

class C implements F {
num x, y = 1, z = 2;

C(this.x);
C.f1(this.x, [this.y = 1]);
C.f2(this.x, {this.z = 2});
C.f3(this.x, {required this.z});
}

enum E {
e1, e2;
const E();

factory E.g1(num x) => E.e1;
factory E.g2(num x, [num y = 1]) => E.e1;
factory E.g3(num x, {num z = 2}) => E.e1;
factory E.g4(num x, {num z = 2}) => E.e1;
factory E.f1(covariant num x) = E.g1;
// ^^^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified
factory E.f2(num x, [covariant num y]) = E.g2;
// ^^^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified
factory E.f3(num x, {covariant num z}) = E.g3;
// ^^^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified
factory E.f4(num x, {required covariant num z}) = E.g3;
// ^^^^^^^^^
// [analyzer] unspecified
// [cfe] unspecified
}

main() {
print(C);
print(E);
}
Loading

0 comments on commit 830714d

Please sign in to comment.