|
| 1 | +# Dart Constructor Tear-Offs Test Plan |
| 2 | + |
| 3 | +The Dart constructor tear-off feature contains multiple independent language changes. Each should be tested, as should their combination with each other and with other relevant language features. |
| 4 | + |
| 5 | +The features can be summarized as: |
| 6 | + |
| 7 | +* Named constructor tear-offs |
| 8 | + * Expressions of the for <code>*C*.*name*</code>. or <code>*C*\<*typeArgs*>.*name*</code>, with type arguments potentially being inferred, evaluate to functions. |
| 9 | + * Preserves identity as specified. |
| 10 | +* Unnamed constructor syntax alternative |
| 11 | + * Everywhere you can currently reference or declare an unnamed constructor, you can also refer to it or declare it as <code>*C*.new</code>. |
| 12 | + * The unnamed and `new`-named constructors are two ways to refer to the *same* thing. (Can't declare both). |
| 13 | +* Unnamed constructor tear-offs |
| 14 | + * Expressions of the for <code>*C*.new</code>. or <code>*C*\<*typeArgs*>.new</code>, with type arguments potentially being inferred, evaluate to functions. |
| 15 | + * Preserves identity as specified. |
| 16 | +* Explicit instantiated function tear-off |
| 17 | + * Expressions of the form <code>*f*\<*typeArgs*></code>, not followed by an argument list and where *f* denotes a generic function declaration or generic instance method, now does instantiated tear-off. |
| 18 | +* Explicit type literal instantiation |
| 19 | + * Expressions of the form <code>*T*\<*typeArgs*></code>, not followed by an argument list and where *T* denotes a type declaration (class, mixin or type alias), now evaluates to a `Type` object for the instantiated type. |
| 20 | + |
| 21 | +Each feature should be tested, both for correct and incorrect usage. Further, we should check that any new syntax is not allowed in places where it isn't defined. |
| 22 | + |
| 23 | +## Named constructor tear-off |
| 24 | + |
| 25 | +### Correct usage |
| 26 | + |
| 27 | +The possible constructors tear-offs |
| 28 | + |
| 29 | +* Check that constructors of non-generic classes can be torn off (`C.foo`). |
| 30 | +* Check that constructors of instantiated generic classes can be torn off (`G<int>.foo`). |
| 31 | +* Check that constructors of uninstantiated generic classes can be torn off, and that type inference infers the correct type arguments. |
| 32 | + * Instantiate to bounds if not context type, or not relevant context type (`var x = G.foo`). |
| 33 | + * Based on context type if relevant (`G<int> Function() f = G.foo1`). |
| 34 | + * Check that the inferred cannot be super-bounded or malbounded. |
| 35 | +* Check that the resulting function has the correct static type and runtime type. |
| 36 | + |
| 37 | +The possible constructor types (all combinations except "const factory non-redirecting" exist): |
| 38 | + |
| 39 | +* Constant or not |
| 40 | +* Factory or not |
| 41 | +* Redirecting or not |
| 42 | + |
| 43 | +The possible sources of tear-offs: |
| 44 | + |
| 45 | +* From a class declaring the constructor. |
| 46 | +* From a mixin-application which introduces a forwarding constructor. |
| 47 | +* Any of those through an alias which is: |
| 48 | + * Not generic. |
| 49 | + * A proper rename (static type may not match runtime type, static type is based on alias type argument bounds, runtime type is based on class type argument bounds). |
| 50 | + * Not a proper rename |
| 51 | + * Not same number of type arguments (fewer or more) |
| 52 | + * Not same order of type arguments |
| 53 | + |
| 54 | +#### Covered by tests |
| 55 | + |
| 56 | +* [tear_off_test][] |
| 57 | +* [aliased_constructor_tear_off_test][] |
| 58 | + |
| 59 | +### Incorrect usage |
| 60 | + |
| 61 | +* Attempting to tear-off non-constructors using new instantiated <Code>*C*\<*typeArgs*>.*name*</code> syntax. |
| 62 | + * (If <code>*name*</code> doesn't refer to a constructor, must then treat <code>*C*\<*typeArgs*></code> as type literal, and therefore only allow members of `Type`, which are also members of `Object` and therefore never valid as constructor names). |
| 63 | +* Incorrect number or type of explicit type arguments. |
| 64 | +* Unsatisfiable type parameters for inferred type arguments. |
| 65 | + |
| 66 | +#### Covered by tests |
| 67 | + |
| 68 | +* [tear_off_error_test][] |
| 69 | + |
| 70 | +## Unnamed constructor alternative syntax |
| 71 | + |
| 72 | +### Correct usage |
| 73 | + |
| 74 | +* The `.new` name can be used anywhere the plain constructor name can. |
| 75 | + * Declarations |
| 76 | + * Invocations |
| 77 | + * Generative constructor super-constructor invocation in initializer list |
| 78 | + * Redirecting generative constructor target |
| 79 | + * Redirecting factory constructor target |
| 80 | + * (Dartdoc?) |
| 81 | +* The two naming conventions can be used interchangeably, both refer to the same constructor |
| 82 | + |
| 83 | +#### Covered by tests |
| 84 | + |
| 85 | +* [unnamed_new_test][] |
| 86 | + |
| 87 | +## Incorrect usage |
| 88 | + |
| 89 | +* Can't use `.new` or `new` to declare non-constructors, nor to call methods. |
| 90 | +* The `new` name is not in *scope* (like constructor names generally aren't). |
| 91 | + |
| 92 | +#### Covered by tests |
| 93 | + |
| 94 | +* [unnamed_new_error_test][] |
| 95 | + |
| 96 | +## Unnamed/`new`-named constructor tearoffs |
| 97 | + |
| 98 | +* Same tests as for named constructor tearoffs. |
| 99 | + |
| 100 | +#### Covered by tests |
| 101 | + |
| 102 | +* [tear_off_test][] |
| 103 | +* [aliased_constructor_tear_off_test][] |
| 104 | +* [tear_off_error_test][] |
| 105 | + |
| 106 | +## Explicit instantiated function tear-off |
| 107 | + |
| 108 | +### Correct usage |
| 109 | + |
| 110 | +* Works for any static, top-level, local function declaration. |
| 111 | + * Also static functions accessed through a type alias. |
| 112 | + * Through import prefix. |
| 113 | +* Works for instance methods other than `call` methods of `Function`-typed objects. |
| 114 | +* Result has expected static and runtime type. |
| 115 | + |
| 116 | +#### Covered by tests |
| 117 | + |
| 118 | +* [explicit_instantiated_tearoff_test][] |
| 119 | + |
| 120 | +### Incorrect usage |
| 121 | + |
| 122 | +* Does not work for function values. |
| 123 | + * Including torn off methods and constructors. |
| 124 | +* Includes function-typed getters. |
| 125 | +* Does not work for `call` methods of function values. |
| 126 | +* Does not work for *constructors* (`class C<T> { C.name();}` does not allow `C.name<int>`). |
| 127 | +* Non-constant instantiation in constant context. |
| 128 | +* Type bounds must not be violated. |
| 129 | + |
| 130 | +#### Covered by tests |
| 131 | + |
| 132 | +* ? |
| 133 | + |
| 134 | +## Explicit instantiated type literal |
| 135 | + |
| 136 | +### Correct usage |
| 137 | + |
| 138 | +* Can instantiate any generic type (class, mixin, type alias). |
| 139 | +* Allows super-bounded types. |
| 140 | +* Result is `Type` object. |
| 141 | +* `Type` objects for same generic type are equal if created using equal type arguments. |
| 142 | +* Identical if passed equal and constant type arguments. |
| 143 | +* Through type aliases, equal/identical if expansion is equal. |
| 144 | + |
| 145 | +#### Covered by tests |
| 146 | + |
| 147 | +* [explicit_instantiated_type_literal_test][] |
| 148 | +* [aliased_type_literal_instantiation_test][] |
| 149 | + |
| 150 | +### Incorrect usage |
| 151 | + |
| 152 | +* Non-constant instantiation in constant context. |
| 153 | + * Even if type parameter of type alias is not used in result. |
| 154 | + |
| 155 | +* Cannot call static members on instantiated type literals. (That's a constructor reference, if anything). |
| 156 | + * <code>*C*\<*typeArgs*>.anything</code> does not create a type literal. |
| 157 | + * <code>*C*\<*typeArgs*>..anything</code> *probably does* (<code>*C*..toString()</code> works today, invokes `toString` of `Type` object). |
| 158 | + * <code>*C*\<*typeArgs*>?.anything</code> also works (possibly with a warning about the `?` being unnecessary). |
| 159 | + * Does not allow malbounded types. |
| 160 | + |
| 161 | +#### Covered by tests |
| 162 | + |
| 163 | +* [explicit_instantiated_type_literal_error_test][] |
| 164 | + |
| 165 | + |
| 166 | + |
| 167 | +[tear_off_test]: http://github.com/dart-lang/sdk/blob/master/tests/language/constructor/tear_off_test.dart |
| 168 | +[unnamed_new_error_test]: http://github.com/dart-lang/sdk/blob/master/tests/language/constructor/unnamed_new_error_test.dart |
| 169 | +[unnamed_new_test]: (http://github.com/dart-lang/sdk/blob/master/tests/language/constructor/unnamed_new_test.dart |
| 170 | +[explicit_instantiated_tearoff_test]: http://github.com/dart-lang/sdk/blob/master/tests/language/generic_methods/explicit_instantiated_tearoff_test.dart |
| 171 | +[explicit_instantiated_type_literal_error_test]: http://github.com/dart-lang/sdk/blob/master/tests/language/type_object/explicit_instantiated_type_literal_error_test.dart |
| 172 | +[explicit_instantiated_type_literal_test]: http://github.com/dart-lang/sdk/blob/master/tests/language/type_object/explicit_instantiated_type_literal_test.dart |
| 173 | +[aliased_constructor_tear_off_test]: http://github.com/dart-lang/sdk/blob/master/tests/language/typedef/aliased_constructor_tear_off_test.dart |
| 174 | +[aliased_type_literal_instantiation_test]: http://github.com/dart-lang/sdk/blob/master/tests/language/typedef/aliased_type_literal_instantiation_test.dart |
0 commit comments