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

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

Issue 2994363003: Generalized void informal spec clarified in several locations. (Closed)
Patch Set: Created 3 years, 4 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`,
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
36 based on the program logic. Hence, there is **no requirement** for the 36 value of the corresponding expression evaluation is useless. Hence, there
Lasse Reichstein Nielsen 2017/08/22 05:31:06 Maybe: "useless and unspecified"
eernst 2017/08/22 09:09:46 Adjusted to 'meaningless'.
37 generalized void mechanism to be strict and **sound**. However, it is the 37 is **no requirement** for the generalized void mechanism to be strict and
38 intention that the mechanism should be sufficiently strict to make the 38 **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
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
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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 168
168 *Conversely, `void` cannot denote any other entity than the type void: 169 *Conversely, `void` cannot denote any other entity than the type void:
169 `void` cannot occur as the declared name of any declaration (including 170 `void` cannot occur as the declared name of any declaration (including
170 library prefixes, types, variables, parameters, etc.). This implies that 171 library prefixes, types, variables, parameters, etc.). This implies that
171 `void` is not subject to scoped lookup, and the name is not exported by any 172 `void` is not subject to scoped lookup, and the name is not exported by any
172 system library. Similarly, it can never be accessed using a prefixed 173 system library. Similarly, it can never be accessed using a prefixed
173 expression (`p.void`). Hence, `void` has a fixed meaning everywhere in all 174 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 Dart programs, and it can only occur as a stand-alone word.*
175 176
176 When `void` is passed as an actual type argument to a generic class or a 177 When `void` is passed as an actual type argument to a generic class or a
177 generic function, and when the type void occurs as a parameter type in a 178 generic function invocation, and when the type void occurs as a parameter
178 function type, the reified representation is equal (according to `==`) to 179 type in a function type, the reified representation is equal (according to
Lasse Reichstein Nielsen 2017/08/22 05:31:06 Consider: equal -> equivalent We use "equivalent"
Lasse Reichstein Nielsen 2017/08/22 05:31:07 What does it mean to "occur as a parameter type" i
eernst 2017/08/22 09:09:46 Done.
179 the reified representation of the built-in class `Object`. 180 `==`) to the reified representation of the built-in class `Object`.
180 181
181 *It is encouraged for an implementation to use a reified representation for 182 *It is encouraged for an implementation to use a reified representation for
Lasse Reichstein Nielsen 2017/08/22 05:31:06 Wording, consider: "An implementation is encourage
182 `void` as a type argument and as a parameter type in a function type which 183 `void` as a type argument and as a parameter type in a function type which
183 is not `identical` to the reified representation of the built-in class 184 is not `identical` to the reified representation of the built-in class
184 `Object`, but they must be equal. This allows implementations to produce 185 `Object`, but they must be equal. This allows implementations to produce
185 better diagnostic messages, e.g., in case of a runtime error.* 186 better diagnostic messages, e.g., in case of a runtime error.*
186 187
187 *This treatment of the reified representation of the type void reinforces 188 *This treatment of the reified representation of the type void reinforces
188 the understanding that "voidness" is merely a statically known flag on the 189 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 190 built-in class `Object`, it is not a separate type. However, for backward
190 compatibility we need to treat return types differently.* 191 compatibility we need to treat return types differently.*
191 192
(...skipping 25 matching lines...) Expand all
217 218
218 Consider a function type _T_ where the return type is the type void. The 219 Consider a function type _T_ where the return type is the type void. The
219 dynamic more-specific-than relation, `<<`, and the dynamic subtype 220 dynamic more-specific-than relation, `<<`, and the dynamic subtype
220 relation, `<:`, are determined by the existing rules in the language 221 relation, `<:`, are determined by the existing rules in the language
221 specification, supplemented by the above rule for handling occurrences of 222 specification, supplemented by the above rule for handling occurrences of
222 the type void other than as a return type. 223 the type void other than as a return type.
223 224
224 *This ensures backward compatibility for the cases where the type void can 225 *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 226 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 227 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, 228 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 229 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 230 situation where a value of type `void Function(...)` is assigned to a
230 variable or parameter `x` whose type annotation is `Object Function(...)`, 231 variable or parameter `x` whose type annotation is `Object Function(...)`,
231 where the argument types are arbitrary, but such that the assignment is 232 where the argument types are arbitrary, but such that the assignment is
232 permitted. In that situation, in checked mode, the assignment will fail 233 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 234 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 235 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 236 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 237 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).* 238 voidness preservation to detect and avoid this situation at compile time).*
238 239
239 *The semantics of checked mode checks involving types where the type void 240 *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 241 occurs is determined by the semantics of subtype tests, so we do not
241 specify that separately.* 242 specify that separately.*
242 243
243 An instantiation of a generic class `G` is malbounded if it contains `void` 244 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 245 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 246 parameter does not have a bound, or it has a bound which is the built-in
246 class `Object`, or `dynamic`. 247 class `Object`, or `dynamic`.
247 248
248 *The treatment of malbounded types follows the current specification.* 249 *The treatment of malbounded types follows the current specification.*
249 250
250 ## Static Analysis 251 ## Static Analysis
251 252
252 For the static analysis, the more-specific-than relation, `<<`, and the 253 For the static analysis, the more-specific-than relation, `<<`, and the
253 subtype relation, `<:`, are determined by the same rules as described above 254 subtype relation, `<:`, are determined by the same rules as described above
254 for the dynamic semantics. 255 for the dynamic semantics.
255 256
256 *That is, the type void is considered to be equivalent to the built-in 257 *That is, the type void is considered to be equivalent to the built-in
Lasse Reichstein Nielsen 2017/08/22 05:31:06 Here we use "equivalent".
257 class `Object`, except when used as a return type, in which case it is 258 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, 259 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 260 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" 261 to the built-in class `Object`. As mentioned, this document does not
261 in types and flag implicit casts wherein information about voidness may 262 specify voidness preservation; however, when voidness preservation checks
262 indirectly be lost. With voidness preservation in place, we expect to be 263 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 264 treatment of void as a return type in Dart 1.x: The function type downcast
264 checks.* 265 which will be rejected in Dart 1.x (at run time, with a static warning at
266 compile time) will become a voidness preservation violation, i.e., a
267 compile-time error.*
265 268
266 It is a static warning for an expression to have type void, except for the 269 It is a static warning for an expression to have type void (in Dart 2: a
267 following situations: 270 compile-time error), except for the following situations:
268 271
269 * In an expressionStatement `e;`, e may have type void. 272 * In an expressionStatement `e;`, e may have type void.
270 * In the initialization and increment expressions of a for-loop, 273 * In the initialization and increment expressions of a for-loop,
271 `for (e1; e2; e3) {..}`, `e1` and `e3` may have type void. 274 `for (e1; e2; e3) {..}`, `e1` and `e3` may have type void.
272 * In a typeCast `e as T`, `e` may have type void. 275 * In a typeCast `e as T`, `e` may have type void.
273 * In a parenthesized expression `(e)`, `e` may have type void. 276 * In a parenthesized expression `(e)`, `e` may have type void.
274 * In a return statement `return e;`, when the return type of the innermost 277 * 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. 278 enclosing function is the type void, `e` may have type void.
276 279
277 *Note that the parenthesized expression itself has type void, so it is 280 *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 281 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 282 return statements returning an expression of type void in Dart 2, but
280 it is allowed here for backward compatibility.* 283 it is allowed here for backward compatibility.*
281 284
285 *The value yielded by an expression of type void must be discarded (and
286 hence ignored), except when explicitly subjected to a type cast. This
287 "makes it hard to use useless values", but leaves a small escape hatch open
288 for the cases where the developer knows that the typing misrepresents the
289 actual situation.*
290
282 During bounds checking, it is possible that a bound of a formal type 291 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 292 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 293 void. In this case, the bound is considered to be the built-in class
285 `Object`. 294 `Object`.
286 295
287 ## Discussion 296 ## Discussion
288 297
289 Expressions derived from typeCast and typeTest do not support `void` as the 298 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 299 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 300 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, 301 `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 302 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 303 `Object` plus a "static voidness flag"), but values of type void should be
295 discarded. 304 discarded. So there is no point in *obtaining* the type void for a given
305 expression which already has a different type.
296 306
297 The treatment of bounds is delicate. We syntactically prohibit `void` as a 307 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 308 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 309 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 310 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 311 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` 312 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 313 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 314 this would require a transitive traversal of all generic classes and
305 and functions where the corresponding formal type parameter is passed on to 315 functions where the corresponding formal type parameter is passed on to
306 other generic classes or functions, which would be highly brittle: A tiny 316 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 317 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 318 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 319 the type void. This motivated the decision to treat such a void-valued
310 bound as `Object`. 320 bound as `Object`.
311 321
312 ## Updates 322 ## Updates
313 323
314 * August 16h 2017: Removed exceptions allowing `e is T` and `e is! T`. 324 * August 17th 2017: Several parts clarified.
325
326 * August 16th 2017: Removed exceptions allowing `e is T` and `e is! T`.
315 327
316 * August 9th 2017: Transferred to SDK repo, docs/language/informal. 328 * August 9th 2017: Transferred to SDK repo, docs/language/informal.
317 329
318 * July 16th 2017: Reformatted as a gist. 330 * July 16th 2017: Reformatted as a gist.
319 331
320 * June 13th 2017: Compile-time error for using a void value was changed to 332 * June 13th 2017: Compile-time error for using a void value was changed to
321 static warning. 333 static warning.
322 * June 12th 2017: Grammar changed extensively, to use 334
323 `typeNotVoid` rather than 335 * June 12th 2017: Grammar changed extensively, to use `typeNotVoid`
324 `voidOrType`. 336 rather than `voidOrType`.
325 * June 5th 2017: Added `typeCast` and 337
326 `typeTest` to the locations where void 338 * June 5th 2017: Added `typeCast` and `typeTest` to the locations where
327 expressions may occur. 339 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