Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Side by Side Diff: docs/language/informal/generalized-void.md

Issue 2994363003: Generalized void informal spec clarified in several locations. (Closed)
Patch Set: Updated "Updates" Created 3 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 ## Feature: Generalized Void 1 ## Feature: Generalized Void
2 2
3 Author: eernst@ 3 Author: eernst@
4 4
5 **Status**: Under implementation. 5 **Status**: Under implementation.
6 6
7 **This document** is an informal specification of the generalized support 7 **This document** is an informal specification of the generalized support
8 in Dart 1.x for the type `void`. Dart 2 will have a very similar kind of 8 in Dart 1.x for the type `void`. Dart 2 will have a very similar kind of
9 generalized support for `void`, without the function type subtype exception 9 generalized support for `void`, without the function type subtype exception
10 that this feature includes for backward compatibility in Dart 1.x. This 10 that this feature includes for backward compatibility in Dart 1.x. This
(...skipping 12 matching lines...) Expand all
23 used to indicate that the visit is performed for its side-effects 23 used to indicate that the visit is performed for its side-effects
24 alone. The generalized void feature includes mechanisms to help developers 24 alone. The generalized void feature includes mechanisms to help developers
25 avoid using such a value. 25 avoid using such a value.
26 26
27 In general, situations where it may be desirable to use `void` as 27 In general, situations where it may be desirable to use `void` as
28 a type argument arise when the corresponding formal type variable is used 28 a type argument arise when the corresponding formal type variable is used
29 covariantly. For instance, the class `Future<T>` uses return types 29 covariantly. For instance, the class `Future<T>` uses return types
30 like `Future<T>` and `Stream<T>`, and it uses `T` as a parameter type of a 30 like `Future<T>` and `Stream<T>`, and it uses `T` as a parameter type of a
31 callback in the method `then`. 31 callback in the method `then`.
32 32
33 Note that is not technically dangerous to use a value of type `void`, it 33 Note that it is not technically dangerous to use a value of type `void`,
Lasse Reichstein Nielsen 2017/08/30 05:29:51 In my quixotic quest to abolish "it" (which you ca
eernst 2017/09/01 07:49:45 Done.
34 does not violate any constraints at the level of the language semantics. 34 doing so does not violate any constraints at the level of the language
35 Developers just made the decision to declare that the value is useless, 35 semantics. By using the type `void`, developers just indicate that the
Lasse Reichstein Nielsen 2017/08/30 05:29:51 Drop "just". It's a word that carries a lot of ins
eernst 2017/09/01 07:49:45 Done.
36 based on the program logic. Hence, there is **no requirement** for the 36 value of the corresponding expression evaluation is meaningless. Hence,
37 generalized void mechanism to be strict and **sound**. However, it is the 37 there is **no requirement** for the generalized void mechanism to be strict
38 intention that the mechanism should be sufficiently strict to make the 38 and **sound**. However, it is the intention that the mechanism should be
39 mechanism helpful and non-frustrating in practice. 39 sufficiently sound to make the mechanism helpful and non-frustrating in
40 practice.
40 41
41 No constraints are imposed on which values may be given type `void`, so in 42 No constraints are imposed on which values may be given type `void`, so in
42 that sense `void` can be considered to be just another name for the type 43 that sense `void` can be considered to be just another name for the type
43 `Object`, flagged as useless. Note that this is an approximate rule (in 44 `Object`, flagged as useless. Note that this is an approximate rule in
44 Dart 1.x), it fails to hold for function types. 45 Dart 1.x, it fails to hold for function types; it does hold in Dart 2.
45 46
46 The mechanisms helping developers to avoid using values of type `void` are 47 The mechanisms helping developers to avoid using values of type `void` are
Lasse Reichstein Nielsen 2017/08/30 05:29:51 values of type `void` -> values of expression of t
eernst 2017/09/01 07:49:45 Done.
47 divided into **two phases**. This document specifies the first phase. 48 divided into **two phases**. This document specifies the first phase.
48 49
49 The **first phase** uses restrictions which are based on syntactic criteria 50 The **first phase** uses restrictions which are based on syntactic criteria
50 in order to ensure that direct usage of a value of type `void` is a static 51 in order to ensure that direct usage of a value of type `void` is a static
Lasse Reichstein Nielsen 2017/08/30 05:29:51 values of type `void` -> ... you get the point. Mo
51 warning (in Dart 2: an error). A few exceptions are allowed, e.g., type 52 warning (in Dart 2: an error). A few exceptions are allowed, e.g., type
52 casts, such that developers can explicitly make the choice to use such a 53 casts, such that developers can explicitly make the choice to use such a
53 value. The general rule is that all values of type `void` must be 54 value. The general rule is that all values of type `void` must be
54 discarded. 55 ignored.
55 56
56 The **second phase** will deal with casts and preservation of 57 The **second phase** will deal with casts and preservation of
57 voidness. Some casts will cause derived expressions to switch from having 58 voidness. Some casts will cause derived expressions to switch from having
58 type `void` to having some other type, and hence those casts introduce the 59 type `void` to having some other type, and hence those casts introduce the
59 possibility that "a void value" will get passed and used. Here is an 60 possibility that "a void value" will get passed and used. Here is an
60 example: 61 example:
61 62
62 ```dart 63 ```dart
63 class A<T> { T foo(); } 64 class A<T> { T foo(); }
64 A<Object> a = new A<void>(); // Violates voidness preservation. 65 A<Object> a = new A<void>(); // Violates voidness preservation.
65 var x = a.foo(); // Use a "void value", with static type Object. 66 var x = a.foo(); // Use a "void value", now with static type Object.
66 ``` 67 ```
67 68
68 We intend to introduce a **voidness preservation analysis** (which is 69 We intend to introduce a **voidness preservation analysis** (which is
69 similar to a small type system) to keep track of such situations. As 70 similar to a small type system) to keep track of such situations. As
70 mentioned, the second phase is **not specified in this document**. Voidness 71 mentioned, the second phase is **not specified in this document**. Voidness
71 preservation is a purely static analysis, and there are no plans to 72 preservation is a purely static analysis, and there are no plans to
72 introduce dynamic checking for it. 73 introduce dynamic checking for it.
73 74
74 ## Syntax 75 ## Syntax
75 76
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 There is no value which is the reified representation of the type void at 159 There is no value which is the reified representation of the type void at
159 run time. 160 run time.
160 161
161 *Syntactically, `void` cannot occur as an expression, and hence expression 162 *Syntactically, `void` cannot occur as an expression, and hence expression
162 evaluation cannot directly yield such a value. However, a formal type 163 evaluation cannot directly yield such a value. However, a formal type
163 parameter can be used in expressions, and the actual type argument bound to 164 parameter can be used in expressions, and the actual type argument bound to
164 that formal type parameter can be the type void. That case is specified 165 that formal type parameter can be the type void. That case is specified
165 explicitly below. Apart from the reserved word `void` and a formal type 166 explicitly below. Apart from the reserved word `void` and a formal type
166 parameter, no other term can denote the type void.* 167 parameter, no other term can denote the type void.*
167 168
168 *Conversely, `void` cannot denote any other entity than the type void: 169 *There is no way for a Dart program at run time to obtain a reified
169 `void` cannot occur as the declared name of any declaration (including 170 representation of a return type or parameter type of a function type, even
170 library prefixes, types, variables, parameters, etc.). This implies that 171 when the function type as a whole may be obtained (e.g., the function type
171 `void` is not subject to scoped lookup, and the name is not exported by any 172 could be evaluated as an expression). It is therefore not necessary to
Lasse Reichstein Nielsen 2017/08/30 05:29:51 The function type cannot actually be evaluated as
eernst 2017/09/01 07:49:45 Right, or it could be defined in a non-parameteriz
172 system library. Similarly, it can never be accessed using a prefixed 173 have a reified representation of such a return type.*
Lasse Reichstein Nielsen 2017/08/30 05:29:51 A reified representation of such a return type is
eernst 2017/09/01 07:49:45 Done. There goes another `it`. ;-)
173 expression (`p.void`). Hence, `void` has a fixed meaning everywhere in all
174 Dart programs, and it can only occur as a stand-alone word.*
175 174
176 When `void` is passed as an actual type argument to a generic class or a 175 For a composite type (a generic class instantiation or a function type),
177 generic function, and when the type void occurs as a parameter type in a 176 the reified representation at run time must be such that the type void and
Lasse Reichstein Nielsen 2017/08/30 05:29:51 void -> `void` ?
eernst 2017/09/01 07:49:45 I actually have 21 occurrences of '`void`' and 64
178 function type, the reified representation is equal (according to `==`) to 177 the built-in class `Object` are treated as equal according to `==`, but
179 the reified representation of the built-in class `Object`. 178 they need not be `identical`.
180 179
181 *It is encouraged for an implementation to use a reified representation for 180 *For example, with `typedef F<S, T> = S Function(T)`, the `Type` instance
182 `void` as a type argument and as a parameter type in a function type which 181 for `F<Object, void>` at run time is `==` to the one for `F<void, void>`
183 is not `identical` to the reified representation of the built-in class 182 and for `F<void, Object>`.*
184 `Object`, but they must be equal. This allows implementations to produce 183
185 better diagnostic messages, e.g., in case of a runtime error.* 184 *In case of a dynamic error, implementations are encouraged to emit an
185 error message that includes information about such parts of types being
186 `void` rather than `Object`. Developers will then see types which are
187 similar to the source code declarations. This may be achieved using
188 distinct `Type` objects to represent types such as `F<void, void>` and
189 `F<Object, void>`, comparing equal using `==` but not `identical`.*
186 190
187 *This treatment of the reified representation of the type void reinforces 191 *This treatment of the reified representation of the type void reinforces
188 the understanding that "voidness" is merely a statically known flag on the 192 the understanding that "voidness" is merely a statically known flag on the
189 built-in class `Object`, it is not a separate type. However, for backward 193 built-in class `Object`. However, for backward compatibility we need to
190 compatibility we need to treat return types differently.* 194 treat return types differently in Dart 1.x.*
191
192 When `void` is specified as the return type of a function, the reified
193 representation of the return type is left unspecified.
194
195 *There is no way for a Dart program at run time to obtain a reified
196 representation of that return type alone, even when the function type as a
197 whole may be obtained (e.g., the function type could be evaluated as an
198 expression). It is therefore not necessary to reified representation of
199 such a return type.*
200 195
201 *It may be possible to use a reflective subsystem (mirrors) to deconstruct 196 *It may be possible to use a reflective subsystem (mirrors) to deconstruct
202 a function type whose return type is the type void, but the existing design 197 a function type whose return type is the type void, but the existing design
203 of the system library `dart:mirrors` already handles this case by allowing 198 of the system library `dart:mirrors` already handles this case by allowing
204 for a type mirror that does not have a reflected type.* 199 for a type mirror that does not have a reflected type. All in all, the type
200 void does not need to be reified at run time.*
Lasse Reichstein Nielsen 2017/08/30 05:29:51 This is a specification, so is it or is it not rei
eernst 2017/09/01 07:49:45 All this commentary stuff is a follow-up on 'There
205 201
206 Consider a type _T_ where the type void occurs as an actual type argument 202 Consider a type _T_ where the type void occurs as an actual type argument
207 to a generic class, or as a parameter type in a function type. Dynamically, 203 to a generic class, or as a parameter type in a function type. Dynamically,
208 the more-specific-than relation (`<<`) and the dynamic subtype relation 204 the more-specific-than relation (`<<`) and the dynamic subtype relation
209 (`<:`) between _T_ and other types are determined by the following rule: 205 (`<:`) between _T_ and other types are determined by the following rule:
210 the type void is treated as being the built-in class `Object`. 206 the type void is treated as being the built-in class `Object`.
211 207
212 *Dart 1.x does not support generic function types dynamically, because they 208 *Dart 1.x does not support generic function types dynamically, because they
213 are erased to regular function types during compilation. Hence there is no 209 are erased to regular function types during compilation. Hence there is no
214 need to specify the the typing relations for generic function types. In 210 need to specify the the typing relations for generic function types. In
215 Dart 2, the subtype relationship for generic function types follows from 211 Dart 2, the subtype relationship for generic function types follows from
216 the rule that `void` is treated as `Object`.* 212 the rule that `void` is treated as `Object`.*
217 213
218 Consider a function type _T_ where the return type is the type void. The 214 Consider a function type _T_ where the return type is the type void. In
219 dynamic more-specific-than relation, `<<`, and the dynamic subtype 215 Dart 1.x, the dynamic more-specific-than relation, `<<`, and the dynamic
220 relation, `<:`, are determined by the existing rules in the language 216 subtype relation, `<:`, are determined by the existing rules in the
221 specification, supplemented by the above rule for handling occurrences of 217 language specification, supplemented by the above rule for handling
222 the type void other than as a return type. 218 occurrences of the type void other than as a return type. In Dart 2 there
219 is no exception for return types: the type void is treated as being the
220 built-in class `Object`.
223 221
224 *This ensures backward compatibility for the cases where the type void can 222 *This ensures backward compatibility for the cases where the type void can
225 be used already today. It follows that it will be a breaking change to 223 be used already today. It follows that it will be a breaking change to
226 switch to a ruleset where the type void even as a return type is treated 224 switch to a ruleset where the type void even as a return type is treated
227 like the built-in class Object, i.e. when switching to Dart 2.0. However, 225 like the built-in class Object, i.e. when switching to Dart 2. However,
228 the only situation where the semantics differs is as follows: Consider a 226 the only situation where the semantics differs is as follows: Consider a
229 situation where a value of type `void Function(...)` is assigned to a 227 situation where a value of type `void Function(...)` is assigned to a
230 variable or parameter `x` whose type annotation is `Object Function(...)`, 228 variable or parameter `x` whose type annotation is `Object Function(...)`,
231 where the argument types are arbitrary, but such that the assignment is 229 where the argument types are arbitrary, but such that the assignment is
232 permitted. In that situation, in checked mode, the assignment will fail 230 permitted. In that situation, in checked mode, the assignment will fail
233 with the current semantics, because the type of that value is not a subtype 231 with the current semantics, because the type of that value is not a subtype
234 of the type of `x`. The rules in this document preserve that behavior. If 232 of the type of `x`. The rules in this document preserve that behavior. If
235 we were to consistently treat the type void as `Object` at run time (as in 233 we were to consistently treat the type void as `Object` at run time (as in
236 Dart 2) then this assignment would be permitted (but we would then use 234 Dart 2) then this assignment would be permitted (but we would then use
237 voidness preservation to detect and avoid this situation at compile time).* 235 voidness preservation to detect and avoid this situation at compile time).*
238 236
239 *The semantics of checked mode checks involving types where the type void 237 *The semantics of checked mode checks involving types where the type void
240 occurs is determined by the semantics of subtype tests, so we do not 238 occurs is determined by the semantics of subtype tests, so we do not
241 specify that separately.* 239 specify that separately.*
242 240
243 An instantiation of a generic class `G` is malbounded if it contains `void` 241 An instantiation of a generic class `G` is malbounded if it contains `void`
244 as an actual type argument for a formal type parameter, unless that type 242 as an actual type argument for a formal type parameter, unless that type
245 parameter does not have a bound, or it has a bound which is the built-in 243 parameter does not have a bound, or it has a bound which is the built-in
246 class `Object`, or `dynamic`. 244 class `Object`, or `dynamic`.
247 245
248 *The treatment of malbounded types follows the current specification.* 246 *The treatment of malbounded types follows the current specification.*
249 247
250 ## Static Analysis 248 ## Static Analysis
251 249
252 For the static analysis, the more-specific-than relation, `<<`, and the 250 For the static analysis, the more-specific-than relation, `<<`, and the
253 subtype relation, `<:`, are determined by the same rules as described above 251 subtype relation, `<:`, are determined by the same rules as described above
254 for the dynamic semantics. 252 for the dynamic semantics, for both Dart 1.x and Dart 2.
255 253
256 *That is, the type void is considered to be equivalent to the built-in 254 *That is, the type void is considered to be equivalent to the built-in
257 class `Object`, except when used as a return type, in which case it is 255 class `Object` in Dart 1.x, except when used as a return type, in which
258 effectively considered to be a proper supertype of `Object`. As mentioned, 256 case it is effectively considered to be a proper supertype of `Object`. In
259 voidness preservation is a separate analysis which is not specified by this 257 Dart 2 subtyping, the type void is consistently considered to be equivalent
260 document, but it is intended to be used in the future to track "voidness" 258 to the built-in class `Object`. As mentioned, this document does not
261 in types and flag implicit casts wherein information about voidness may 259 specify voidness preservation; however, when voidness preservation checks
262 indirectly be lost. With voidness preservation in place, we expect to be 260 are added we get an effect in Dart 2 which is similar to the special
263 able to treat the type void as `Object` in all cases during subtype 261 treatment of void as a return type in Dart 1.x: The function type downcast
264 checks.* 262 which will be rejected in Dart 1.x (at run time, with a static warning at
263 compile time) will become a voidness preservation violation, i.e., a
264 compile-time error.*
265 265
266 It is a static warning for an expression to have type void, except for the 266 It is a static warning for an expression to have type void (in Dart 2: a
267 following situations: 267 compile-time error), except for the following situations:
268 268
269 * In an expressionStatement `e;`, e may have type void. 269 * In an expressionStatement `e;`, e may have type void.
270 * In the initialization and increment expressions of a for-loop, 270 * In the initialization and increment expressions of a for-loop,
271 `for (e1; e2; e3) {..}`, `e1` and `e3` may have type void. 271 `for (e1; e2; e3) {..}`, `e1` and `e3` may have type void.
272 * In a typeCast `e as T`, `e` may have type void. 272 * In a typeCast `e as T`, `e` may have type void.
273 * In a parenthesized expression `(e)`, `e` may have type void. 273 * In a parenthesized expression `(e)`, `e` may have type void.
274 * In a return statement `return e;`, when the return type of the innermost 274 * In a return statement `return e;`, when the return type of the innermost
275 enclosing function is the type void, `e` may have type void. 275 enclosing function is the type void, `e` may have type void.
276 276
277 *Note that the parenthesized expression itself has type void, so it is 277 *Note that the parenthesized expression itself has type void, so it is
278 again subject to the same constraints. Also note that we may not allow 278 again subject to the same constraints. Also note that we may not allow
279 return statements returning an expression of type void in the future, but 279 return statements returning an expression of type void in Dart 2, but
280 it is allowed here for backward compatibility.* 280 it is allowed here for backward compatibility.*
281 281
282 *The value yielded by an expression of type void must be discarded (and
283 hence ignored), except when explicitly subjected to a type cast. This
284 "makes it hard to use a meaningless value", but leaves a small escape hatch
285 open for the cases where the developer knows that the typing misrepresents
286 the actual situation.*
287
282 During bounds checking, it is possible that a bound of a formal type 288 During bounds checking, it is possible that a bound of a formal type
283 parameter of a generic class or function is statically known to be the type 289 parameter of a generic class or function is statically known to be the type
284 void. In this case, the bound is considered to be the built-in class 290 void. In this case, the bound is considered to be the built-in class
285 `Object`. 291 `Object`.
286 292
293 In Dart 2, it is a compile-time error when a method declaration _D2_ with
294 return type void overrides a method declaration _D1_ whose return type is
295 not void.
296
297 *This rule is a special case of voidness preservation, which is needed in
298 order to maintain the discipline which arises naturally from the function
299 type subtype rules in Dart 1.x concerning void as a return type.*
300
287 ## Discussion 301 ## Discussion
288 302
289 Expressions derived from typeCast and typeTest do not support `void` as the 303 Expressions derived from typeCast and typeTest do not support `void` as the
290 target type. We have omitted support for this situation because we consider 304 target type. We have omitted support for this situation because we consider
291 it to be useless. If void is passed indirectly via a type variable `T` then 305 it to be useless. If void is passed indirectly via a type variable `T` then
292 `e as T`, `e is T`, and `e is! T` will treat `T` like `Object`. In general, 306 `e as T`, `e is T`, and `e is! T` will treat `T` like `Object`. In general,
293 the rationale is that the type void admits all values (because it is just 307 the rationale is that the type void admits all values (because it is just
294 `Object` plus a "static voidness flag"), but values of type void should be 308 `Object` plus a "static voidness flag"), but values of type void should be
Lasse Reichstein Nielsen 2017/08/30 05:29:51 values of type void -> values with static type voi
eernst 2017/09/01 07:49:45 Done.
295 discarded. 309 discarded. So there is no point in *obtaining* the type void for a given
310 expression which already has a different type.
296 311
297 The treatment of bounds is delicate. We syntactically prohibit `void` as a 312 The treatment of bounds is delicate. We syntactically prohibit `void` as a
298 bound of a formal type parameter of a generic class or function. It is 313 bound of a formal type parameter of a generic class or function. It is
299 possible to pass the type void as an actual type argument to a generic 314 possible to pass the type void as an actual type argument to a generic
300 class, and that type argument might in turn be used as the bound of another 315 class, and that type argument might in turn be used as the bound of another
301 formal type parameter of the class, or of a generic function in the 316 formal type parameter of the class, or of a generic function in the
302 class. It would be possible to make it a compile-time error to pass `void` 317 class. It would be possible to make it a compile-time error to pass `void`
303 as a type argument to a generic class where it will be used as a bound, but 318 as a type argument to a generic class where it will be used as a bound, but
304 this would presumably require a transitive traversal of all generic classes 319 this would require a transitive traversal of all generic classes and
305 and functions where the corresponding formal type parameter is passed on to 320 functions where the corresponding formal type parameter is passed on to
306 other generic classes or functions, which would be highly brittle: A tiny 321 other generic classes or functions, which would be highly brittle: A tiny
307 change to a generic class or function could break code far away. So we do 322 change to a generic class or function could break code far away. So we do
308 not wish to prevent formal type parameter bounds from indirectly becoming 323 not wish to prevent formal type parameter bounds from indirectly becoming
309 the type void. This motivated the decision to treat such a void-valued 324 the type void. This motivated the decision to treat such a void-valued
310 bound as `Object`. 325 bound as `Object`.
311 326
312 ## Updates 327 ## Updates
313 328
314 * August 16h 2017: Removed exceptions allowing `e is T` and `e is! T`. 329 * August 22nd 2017: Reworded specification of reified types to deal with
330 only such values which may be obtained at run time (previously mentioned
331 some entities which may not exist). Added one override rule.
332
333 * August 17th 2017: Several parts clarified.
334
335 * August 16th 2017: Removed exceptions allowing `e is T` and `e is! T`.
315 336
316 * August 9th 2017: Transferred to SDK repo, docs/language/informal. 337 * August 9th 2017: Transferred to SDK repo, docs/language/informal.
317 338
318 * July 16th 2017: Reformatted as a gist. 339 * July 16th 2017: Reformatted as a gist.
319 340
320 * June 13th 2017: Compile-time error for using a void value was changed to 341 * June 13th 2017: Compile-time error for using a void value was changed to
321 static warning. 342 static warning.
322 * June 12th 2017: Grammar changed extensively, to use 343
323 `typeNotVoid` rather than 344 * June 12th 2017: Grammar changed extensively, to use `typeNotVoid`
324 `voidOrType`. 345 rather than `voidOrType`.
325 * June 5th 2017: Added `typeCast` and 346
326 `typeTest` to the locations where void 347 * June 5th 2017: Added `typeCast` and `typeTest` to the locations where
327 expressions may occur. 348 void expressions may occur.
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698