Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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. |
| OLD | NEW |