├── .gitignore ├── LICENSE ├── README.md └── proposal.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Don’t commit the following directories created by pub. 2 | build/ 3 | packages/ 4 | .buildlog 5 | 6 | # Or the files created by dart2js. 7 | *.dart.js 8 | *.dart.precompiled.js 9 | *.js_ 10 | *.js.deps 11 | *.js.map 12 | 13 | # Include when developing application packages. 14 | pubspec.lock 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # metaclasses 2 | Proposal for metaclasses in Dart 3 | -------------------------------------------------------------------------------- /proposal.md: -------------------------------------------------------------------------------- 1 | # Metaclasses in Dart 2 | 3 | 4 | ## Contact information 5 | 6 | 1. **Gilad Bracha.** 7 | 8 | 2. **gbracha@google.com.** 9 | 10 | 3. **https://github.com/gbracha/metaclasses** 11 | 12 | ## Summary 13 | 14 | Currently all classes in Dart have the same (meta)class: `Type`. `Type` has very limited capabilities. It was designed to serve as a key for the mirror system and very little else. As anticipated in the original design document, requests keep coming in for more features. I think it is time we started to address these. 15 | 16 | I propose that the type object for a class *C* have implicitly defined instance methods corresponding to the static methods (including getters and setters) and constructors of *C*. 17 | For each static method *sm*, an instance method of the same name, with the same signature, is defined, which simply forwards the call to the static method *sm*. For each named constructor *k*, an instance method of the same name, with the same signature, is defined. This method returns the result of calling the constructor via **new**. 18 | 19 | Since the named constructors, static methods and instance methods cannot conflict, there is no risk of these synthetic methods conflicting with the existing instance methods of `Type`, which are all inherited from `Object`, or with each other. The anonymous constructor should be represented by a method called `new`; since **new** is a reserved word, no conflicts arise here either. 20 | 21 | The above implies that every `Type` object is an instance of its own metaclass and that metaclasses do not mirror the inheritance hierarchy. Each metaclass is a direct subclass of `Type`. 22 | 23 | Since each instantiation of a generic has its own `Type` object, each one also has its own metaclass. 24 | 25 | Every class *C* induces two types. The *instance type*, referred to by the name *C*, is the type that already exists in Dart. This proposal introduces the notion of a *class type*. The class type is written *C.class* (again, since **class** is a reserved word, there is no conflict with existing members). The members of *C.class* have the the above defined methods of the metaclass of *C*. *C.class* is an interface type as usual in Dart, and can be implemented but not extended. 26 | 27 | Note: one can now do constructor tear-offs using the normal tear-off mechanism. There is the overhead of indirection, which presumably will be inlined away if it matters. Likewise, if we have type variables, one can write *T.new()* instead of the illegal **new** *T()*. 28 | 29 | 30 | ## Motivation 31 | 32 | People need to abstract over the operation of creating an instance of a class. In principle, this is quite straightforward, as all one needs to do is to define a closure for this purpose and pass it around. And yet users find this to be annoying or challenging. 33 | 34 | See for example 35 | 36 | https://code.google.com/p/dart/issues/detail?id=10659 37 | 38 | We have also heard similar requests from internal customers at Google. 39 | 40 | The restrictions on the the use of `Type` values confuse people. It is very intuitive to be able to pass classes as parameters and use them as classes. A related point is the chronic desire to write `new T()` where *T* is a type parameter to a generic. See 41 | 42 | https://code.google.com/p/dart/issues/detail?id=3633 43 | 44 | 45 | The current state of affairs leads to an ugly wart, where parentheses can change the meaning of an expression. Compare: 46 | 47 | `C.staticMethod()` as opposed to `(C).staticMethod()`. The former is a static method call, while the latter is an instance method call an instance of `Type`. Consequently, it fails. This sort of situation is confusing to users; understanding the difference is subtle. 48 | 49 | ###Pros 50 | 51 | * Simple 52 | 53 | * Eliminates some scenarios where users might otherwise need to use reflection. 54 | 55 | * Provides a more elegant solution than constructor tear-offs. 56 | 57 | * No syntax changes are needed. 58 | 59 | * Addresses perceived needs, as evidenced by submitted bugs. 60 | 61 | 62 | 63 | 64 | 65 | ###Cons 66 | 67 | * This does double the number of class objects in runtime as each declared class introduces its own metaclass. Perhaps these can be generated lazily. 68 | 69 | * People may choose to use `C.new` instead of `new C()`, even when the latter is legal. In other words, there would be two ways of doing the same thing, which is regrettable. 70 | Also, some may object on grounds of style. This could be mitigated by defining *new e(args)* as *e.new(args)*. I would prefer not to go that route, but it may have some merit in that the obvious, naive thing just works. 71 | 72 | * Does not allow the use const constructors to create constant objects. 73 | 74 | * Does not give an easy way to refer to parameterized types as expressions, e.g., `Type t = List;`. That is a separate issue. 75 | 76 | * May have negative impact on tree-shaking, leading to increased size of applications deployed via Javascript. Initial studies indicate this effect is minor. 77 | 78 | 79 | ## Examples 80 | 81 | See the bugs. 82 | ``` 83 | class A { 84 | } 85 | 86 | class B { 87 | T GetBySmth() { 88 | return T.new(); // could even be new T() if we went that far 89 | } 90 | } 91 | 92 | void main() { 93 | var b = new B(); 94 | var x = b.GetBySmth(); 95 | assert(x is B); 96 | } 97 | ``` 98 | 99 | Now, in the case where we want to be type safe we could write 100 | 101 | ``` 102 | class B { 103 | T GetBySmth() { 104 | return T.new(); // could even be new T() if we went that far 105 | } 106 | } 107 | 108 | ``` 109 | 110 | However, this is still less useful than it might seem, since even if *C* is a subtype of *A*, *C.class* is not a subtype of *A.class*. It should not be, since neither statics nor constructors are inherited. So to be more generally useful, one would need to define the desired interface that we need to use, say 111 | 112 | ``` 113 | abstract class HasNullaryAnonymousConstructor { 114 | static HasNullaryAnonymousConstructor(); 115 | } 116 | ``` 117 | 118 | and then we'd need to somehow state that *A.class* implements *HasAnonymousConstructor*. Our options are to add some sort of implements clause for the class, such as 119 | 120 | ``` 121 | class A class implements HasAnonymousConstructor { 122 | } 123 | 124 | ``` 125 | 126 | or we could go with a structural approach instead. We could use this in 127 | 128 | ``` 129 | class B { 130 | T GetBySmth() { 131 | return T.new(); // could even be new T() if we went that far 132 | } 133 | } 134 | 135 | ``` 136 | 137 | 138 | 139 | 140 | ## Proposal 141 | 142 | The basic proposal is described above. 143 | 144 | ## Deliverables 145 | 146 | 147 | ### Language specification changes 148 | 149 | Commentary on the specification is given in *italics*. Rationale is in **bold**. Deleted sections are ~~struck out~~. 150 | 151 | The specification already states that `Type` objects have members corresponding to the static members of a type. However, access to them is disallowed. The necessary spec changes are mainly about removing these restrictions, and introducing the concept of a metaclass type. In addition, the spec neglected to incorporate members that correspond to constructors, so the following text must be added to section 10.6, **Constructors**: 152 | 153 | The declaration of a constructor named *m* in class *C* has the effect of adding an instance method with the same name and signature to the `Type` object for class *C* that, when run, returns the result of evaluating `new C.m` with the same arguments the instance method was called with. 154 | 155 | *Because each generic instantiation has its own metaclass, type arguments are already included in `C`.* 156 | 157 | The declaration of an anonymous constructorin class *C* has the effect of adding an instance method with the same name and signature to the `Type` object for class *C* that, when run, returns the result of evaluating `new C` with the same arguments the instance method was called with. 158 | 159 | 160 | I propose to add a dedicated subsection, 10.11, to the section on classes. 161 | 162 | #### 10.11 Metaclasses 163 | 164 | At runtime, every class is associated with its own metaclass. 165 | 166 | ** Each class *C* has a metaclass, because the `Type` object representing *C* has specific behavior corresponding to its constructors and static getters (10.2), setters (10.3), and methods (10.7).** 167 | 168 | *Here we speak of classes as runtime objects, distinct from class declarations. The distinction matters with respect to generics, where a single declaration introduces an entire family of runtime classes. It is helpful to recall that every object has a particular class at runtime; this class might in fact be an instantiation of a generic class declaration, e.g., `List;` in any event, each such class has its own unique metaclass.* 169 | 170 | Let *C* be a class: 171 | 172 | The metaclass of *C* has a single instance, the unique instance of `Type` associated with *C*. The type of *C* may be referred to as *C.class*, where *C* is a type literal. 173 | 174 | All metaclasses are direct subclasses of class `Type`. 175 | 176 | *In particular, the metaclass of class `Type`, `Type.class`, is a direct subclass of `Type`.* 177 | 178 | It is a compile time error to extend a metaclass. All metaclasses are instances of class `Metaclass`. 179 | 180 | *`Metaclass` itself is a class, and as such it is an instance of `Metaclass.class` which is in turn an instance of `Metaclass`.* 181 | 182 | **This circularity resolves what would otherwise be an infinite regress.** 183 | 184 | #####10.11.1 Metaclass Superinterfaces 185 | 186 | TBD 187 | 188 | 189 | #### 14 Generics 190 | 191 | A class declaration (10) or type alias (19.3.1) *G* may be *generic*, that is, *G* may have formal type parameters declared. A generic declaration induces a family of declarations, one for each set of actual type parameters provided in the program. 192 | 193 | ``` 194 | typeParameter: 195 | metadata identifier (extends type)? (class extends type)? 196 | ; 197 | 198 | typeParameters: 199 | ‘<’ typeParameter (‘,’ typeParameter)* ‘>’ ; 200 | ``` 201 | 202 | A type parameter *T* may be suffixed with an **extends** clause that specifies the upper bound for *T*. If no **extends** clause is present, the upper bound is `Object`. 203 | 204 | A type parameter *T* may be suffixed with an **extends class** clause that specifies the upper bound for *T.class*. If no **extends class** clause is present, the upper bound is `Type`. 205 | 206 | It is a static type warning if a type parameter is a supertype of its upper bound. It is a static type warning if a type parameter's class is a supertype of its upper bound. The bounds of type variables are a form of type annotation and have no effect on execution in production mode. 207 | 208 | **Rest of section 14 is unchanged.** 209 | 210 | In addition, the restrictions disallowing access to metaclass members must be removed from sections 16.17.1, 16.18, 16.19 211 | 212 | #### 16.17.1 Ordinary Invocation 213 | 214 | An ordinary method invocation *i* has the form *o.m(a1,...,an,xn+1 : an+1,...,xn+k : an+k*. 215 | 216 | Evaluation of an ordinary method invocation *i* of the form *o.m(a1,...,an,xn+1 : an+1,...,xn+k : an+k)* 217 | proceeds as follows: 218 | 219 | First, the expression *o* is evaluated to a value *vo*. Next, the argument list *(a1, . . . , an, xn+1 : an+1, . . . , xn+k : an+k)* is evaluated yielding actual argument objects *o1,...,on+k*. Let *f* be the result of looking up (16.15.1) method *m* in *vo* with respect to the current library *L*. 220 | 221 | Let *p1 . . . ph* be the required parameters of *f*, let *p1 . . . pm* be the positional parameters of *f* and let *ph+1, . . . , ph+l* be the optional parameters declared by *f*. 222 | 223 | *We have an argument list consisting of *n* positional arguments and *k* named arguments. We have a function with *h* required parameters and *l* optional parameters. The number of positional arguments must be at least as large as the number of required parameters, and no larger than the number of positional parameters. All named arguments must have a corresponding named parameter.* 224 | 225 | If *n < h*, or *n > m*, the method lookup has failed. Furthermore, each *xi, n + 1 ≤ i ≤ n + k*, must have a corresponding named parameter in the set *{pm+1,...,ph+l}* or the method lookup also fails.~~ If *vo* is an instance of `Type` but *o* is not a constant type literal, then if *m* is a method that forwards (9.1) to a static method, method lookup fails.~~ Otherwise method lookup has succeeded. 226 | 227 | If the method lookup succeeded, the body of *f* is executed with respect to the bindings that resulted from the evaluation of the argument list, and with this bound to *vo*. The value of *i* is the value returned after *f* is executed. 228 | 229 | If the method lookup has failed, then let *g* be the result of looking up getter (16.15.2) *m* in *vo* with respect to *L*.~~ If *vo* is an instance of `Type` but *o* is not a constant type literal, then if *g* is a getter that forwards to a static getter, getter lookup fails.~~ If the getter lookup succeeded, let *vg* be the value of the getter invocation *o.m*. Then the value of *i* is the result of invoking the static method `Function.apply()` with arguments *v.g, [o1, . . . , on], {xn+1 : on+1, . . . , xn+k : on+k}*. 230 | 231 | If getter lookup has also failed, then a new instance *im* of the predefined class `Invocation` is created, such that : 232 | 233 | * *im.isMethod* evaluates to `true`. 234 | 235 | * *im.memberName* evaluates to `’m’`. 236 | 237 | * *im.positionalArguments* evaluates to an immutable list with the same values as *[o1,...,on]*. 238 | 239 | * *im.namedArguments* evaluates to an immutable map with the same keys and values as *{xn+1 : on+1, . . . , xn+k : on+k}*. 240 | 241 | Then the method `noSuchMethod()` is looked up in *vo* and invoked with argument *im*, and the result of this invocation is the result of evaluating *i*. However, if the implementation found cannot be invoked with a single positional argument, the implementation of `noSuchMethod()` in class `Object` is invoked on *vo* with argument *im′*, where *im′* is an instance of `Invocation` such that : 242 | 243 | * *im.isMethod* evaluates to `true`. 244 | 245 | * *im.memberName* evaluates to `noSuchMethod`. 246 | 247 | * *im.positionalArguments* evaluates to an immutable list whose sole element is *im*. 248 | 249 | * *im.namedArguments* evaluates to to the value of **const** `{}`. 250 | 251 | and the result of the latter invocation is the result of evaluating *i*. 252 | 253 | *It is possible to bring about such a situation by overriding `noSuchMethod()` with the wrong number of arguments:* 254 | 255 | ``` 256 | class Perverse { noSuchMethod(x,y) => x + y; } 257 | new Perverse.unknownMethod(); 258 | ``` 259 | 260 | *Notice that the wording carefully avoids re-evaluating the receiver *o* and the 261 | arguments *ai*.* 262 | 263 | Let *T* be the static type of *o*. It is a static type warning if *T* does not have 264 | an accessible (6.2) instance member named *m* unless ~~either:~~ *T* or a superinterface of *T* is annotated with an annotation denoting a 265 | constant identical to the constant `@proxy` defined in `dart:core`. ~~Or 266 | *T* is `Type`, *e* is a constant type literal and the class corresponding to *e* has 267 | a static getter named *m*.~~ 268 | 269 | If *T.m* exists, it is a static type warning if the type *F* of *T.m* may not be assigned to a function type. If *T.m* does not exist, or if *F* is not a function type, the static type of *i* is dynamic; otherwise the static type of *i* is the declared return type of *F*. 270 | It is a compile-time error to invoke any of the methods of class `Object` on a prefix object (18.1) ~~or on a constant type literal that is immediately followed by the token ‘.’~~. 271 | 272 | 273 | 274 | #### 16.18 Property Extraction 275 | 276 | *Property extraction* allows for a member of an object to be concisely extracted from the object. A property extraction can be either: 277 | 278 | 1. A *closurization* (16.18.1) which allows a method to be treated as if it were a getter for a function valued object. Or 279 | 2. A *getter invocation* which returns the result of invoking of a getter method. 280 | 281 | Evaluation of a property extraction *i* of the form *e.m* proceeds as follows: 282 | 283 | First, the expression *e* is evaluated to an object *o*. Let *f* be the result of looking up (16.15.1) method (10.1) *m* in *o* with respect to the current library *L*. ~~If *o* is an instance of `Type` but *e* is not a constant type literal, then if *m* is a method that forwards (9.1) to a static method, method lookup fails.~~ If method lookup succeeds and *f* is a concrete method then *i* evaluates to the closurization of *o.m*. 284 | 285 | Otherwise, *i* is a getter invocation, and the getter function (10.2) *m* is looked up (16.15.2) in *o* with respect to *L*. ~~If *o* is an instance of `Type` but *e* is not a constant type literal, then if *m* is a getter that forwards to a static getter, getter lookup fails~~. Otherwise, the body of *m* is executed with this bound to *o*. The value of *i* is the result returned by the call to the getter function. 286 | 287 | If the getter lookup has failed, then a new instance *im* of the predefined class `Invocation` is created, such that : 288 | 289 | * *im.isGetter* evaluates to `true`. 290 | 291 | * *im.memberName* evaluates to `’m’`. 292 | 293 | * *im.positionalArguments* evaluates to **const** `[]`. 294 | 295 | * *im.namedArguments* evaluates to **const** `{}`. 296 | 297 | Then the method `noSuchMethod()` is looked up in *o* and invoked with argument *im*, and the result of this invocation is the result of evaluating *i*. However, if the implementation found cannot be invoked with a single positional argument, the implementation of `noSuchMethod()` in class `Object` is invoked on *o* with argument *im′*, where *im′* is an instance of `Invocation` such that : 298 | 299 | * *im.isMethod* evaluates to `true`. 300 | 301 | * *im.memberName* evaluates to `noSuchMethod`. 302 | 303 | * *im.positionalArguments* evaluates to an immutable list whose sole element is *im*. 304 | 305 | * *im.namedArguments* evaluates to to the value of **const** `{}`. 306 | 307 | and the result of the latter invocation is the result of evaluating *i*. 308 | 309 | It is a compile-time error if *m* is a member of class `Object` and *e* is ~~either~~ a 310 | prefix object (18.1)~~or a constant type literal~~. 311 | 312 | ~~*This precludes `int.toString` but not `(int).toString` because in the latter case, *e* is a parenthesized expression.*~~ 313 | 314 | Let *T* be the static type of *e*. It is a static type warning if *T* does not have a method or getter named *m* unless ~~either:~~ *T* or a superinterface of *T* is annotated with an annotation denoting a constant identical to the constant `@proxy` defined in `dart:core`.~~Or~~ 315 | ~~* *T* is `Type`, *e* is a constant type literal and the class corresponding to *e* has a static method or getter named *m*.~~ 316 | 317 | If *i* is a getter invocation, the static type of *i* is: 318 | 319 | * The declared return type of *T.m*, if *T.m* exists. 320 | 321 | ~~* The declared return type of *m*, if *T* is `Type`, *e* is a constant type literal and the class corresponding to *e* has a static method or getter named *m*.~~ 322 | 323 | * The type **dynamic** otherwise. 324 | 325 | If *i* is a closurization, its static type is as described in section 16.18.1. 326 | 327 | 328 | **Rest of Section Unchanged ** 329 | 330 | #### 16.19 Assignment 331 | 332 | The section that changes is: 333 | 334 | Evaluation of an assignment of the form *e1.v = e2* proceeds as follows: 335 | 336 | The expression *e1* is evaluated to an object *o1*. Then, the expression *e2* is evaluated to an object *o2*. Then, the setter *v =* is looked up (16.15.2) in *o1* with 337 | respect to the current library.~~If *o1* is an instance of `Type` but *e1* is not a constant type literal, then if `v =` is a setter that forwards (9.1) to a static setter, setter lookup fails. Otherwise, t~~The body of *v =* is executed with its formal parameter bound to *o2* and **this** bound to *o1*. 338 | 339 | If the setter lookup has failed, then a new instance *im* of the predefined class `Invocation` is created, such that : 340 | 341 | * *im.isMethod* evaluates to `true`. 342 | 343 | * *im.memberName* evaluates to `v=`. 344 | 345 | * *im.positionalArguments* evaluates to an immutable list with the same values as *[o2]*. 346 | 347 | * *im.namedArguments* evaluates to to the value of **const** `{}`. 348 | 349 | Then the method `noSuchMethod()` is looked up in *o1* and invoked with argument *im*. 350 | However, if the implementation found cannot be invoked with a single positional argument, the implementation of `noSuchMethod()` in class `Object` is invoked on *o1* with argument *im′*, where *im′* is an instance of `Invocation` such that : 351 | 352 | * *im.isMethod* evaluates to `true`. 353 | 354 | * *im.memberName* evaluates to `noSuchMethod`. 355 | 356 | * *im.positionalArguments* evaluates to an immutable list whose sole element is *im*. 357 | 358 | * *im.namedArguments* evaluates to to the value of **const** `{}`. 359 | 360 | The value of the assignment expression is *o2* irrespective of whether setter lookup has failed or succeeded. 361 | 362 | In checked mode, it is a dynamic type error if *o2* is not **null** and the interface of the class of *o2* is not a subtype of the actual type of *e1.v*. 363 | 364 | Let *T* be the static type of *e1*. It is a static type warning if *T* does not have an accessible instance setter named *v =* unless ~~either:~~ *T* or a superinterface of *T* is annotated with an annotation denoting a constant identical to the constant `@proxy` defined in `dart:core`.~~Or~~ 365 | ~~* *T* is `Type`, *e1* is a constant type literal and the class corresponding to *e1* has a static setter named *v =*.~~ 366 | 367 | It is a static type warning if the static type of *e2* may not be assigned to the static type of the formal parameter of the setter *v =*. The static type of the expression *e1.v = e2* is the static type of *e2*. 368 | 369 | Evaluation of an assignment of the form *e1[e2] = e3* is equivalent to the evaluation of the expression `(a, i, e){a.[]=(i, e); return e; } (e1 , e2 , e3 )`. The static type of the expression *e1[e2] = e3* is the static type of *e3*. 370 | 371 | It is a static warning if an assignment of the form *v = e* occurs inside a top level or static function (be it function, method, getter, or setter) or variable initializer and there is neither a local variable declaration with name *v* nor setter declaration with name *v =* in the lexical scope enclosing the assignment. 372 | 373 | It is a compile-time error to invoke any of the setters of class `Object` on a prefix object (18.1)~~or on a constant type literal that is immediately followed by the token ‘.’~~. 374 | 375 | 376 | In addition, we must update section 16.32 which specifies the static type of an identifier so that type literals are assigned the type of their metaclass. 377 | 378 | #### 16.32 Identifier Reference 379 | 380 | One word change here: 381 | 382 | * If *d* is a class, type alias or type parameter *T* the static type of *e* is ~~`Type`~~ *T.class*. 383 | 384 | ### A working implementation 385 | 386 | TBD 387 | 388 | ### Tests 389 | 390 | TBD 391 | 392 | ## Patents rights 393 | 394 | TC52, the Ecma technical committee working on evolving the open [Dart standard][], operates under a royalty-free patent policy, [RFPP][] (PDF). This means if the proposal graduates to being sent to TC52, you will have to sign the Ecma TC52 [external contributer form]() and submit it to Ecma. 395 | 396 | [tex]: http://www.latex-project.org/ 397 | [language spec]: https://www.dartlang.org/docs/spec/ 398 | [dart standard]: http://www.ecma-international.org/publications/standards/Ecma-408.htm 399 | [rfpp]: http://www.ecma-international.org/memento/TC52%20policy/Ecma%20Experimental%20TC52%20Royalty-Free%20Patent%20Policy.pdf 400 | [external contributer form]: http://www.ecma-international.org/memento/TC52%20policy/Contribution%20form%20to%20TC52%20Royalty%20Free%20Task%20Group%20as%20a%20non-member.pdf --------------------------------------------------------------------------------