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

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

Issue 2994003002: Transferred the generalized void informal spec to docs/language/informal (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
(Empty)
1 ## Feature: Generalized Void
2
3 Author: eernst@
4
5 **Status**: Under implementation.
6
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
9 generalized support for `void`, without the function type subtype exception
10 that this feature includes for backward compatibility in Dart 1.x. This
11 document specifies the feature for Dart 1.x and indicates how Dart 2
12 differs at relevant points.
13
14 **The feature** described here, *generalized void*, allows for using the
15 type `void` as a type annotation, and as a type argument.
Lasse Reichstein Nielsen 2017/08/09 13:41:42 Not sure there should be a comma here.
eernst 2017/08/09 14:30:03 Done.
16
17 The **motivation** for allowing the extended usage is that it helps
18 developers state the intent that a particular **value should be
19 ignored**. For example, a `Future<void>` may be awaited in order to satisfy
20 ordering dependencies in the execution, but no useful value will be
21 available at completion. Similarly, a `Visitor<void>` (where we assume the
22 type argument is used to describe a value returned by the visitor) may be
23 used to indicate that the visit is performed for its side-effects
24 alone. The generalized void feature includes mechanisms to help developers
25 avoid using such a value.
Lasse Reichstein Nielsen 2017/08/09 13:41:42 Is it worth mentioning that the type parameter of
eernst 2017/08/09 14:30:04 Added a small paragraph mentioning this, and using
26
27 Note that is not technically dangerous to use a value of type `void`, it
28 does not violate any constraints at the level of the language semantics.
29 Developers just made the decision to declare that the value is useless,
30 based on the program logic. Hence, there is **no requirement** for the
31 generalized void mechanism to be strict and **sound**. However, it is the
32 intention that the mechanism should be sufficiently strict to make the
33 mechanism helpful and non-frustrating in practice.
34
35 No constraints are imposed on which values may be given type `void`, so in
36 that sense `void` can be considered to be just another name for the type
37 `Object`, flagged as useless. Note that this is an approximate rule (in
38 Dart 1.x), it fails to hold for function types.
39
40 The mechanisms helping developers to avoid using values of type `void` are
41 divided into **two phases**. This document specifies the first phase. The
42 second phase may be added to Dart 1.x later, or it may only be provided in
Lasse Reichstein Nielsen 2017/08/09 13:41:42 Definitely not going into Dart 1.0, everything we
eernst 2017/08/09 14:30:03 Removed the entire sentence. Everything will be ab
43 Dart 2.0, depending on the schedule.
44
45 The **first phase** uses restrictions which are based on syntactic criteria
46 in order to ensure that direct usage of a value of type `void` is a static
47 warning (in Dart 2: an error). A few exceptions are allowed, e.g., type
48 casts, such that developers can explicitly make the choice to use such a
49 value. The general rule is that all values of type `void` must be
50 discarded.
51
52 The **second phase** will deal with casts and preservation of
53 voidness. Some casts will cause derived expressions to switch from having
54 type `void` to having some other type, and hence those casts introduce the
55 possibility that "a void value" will get passed and used. Here is an
56 example:
57
58 ```dart
59 class A<T> { T foo(); }
60 A<Object> a = new A<void>(); // Violates voidness preservation.
61 var x = a.foo(); // Use a "void value", with static type Object.
62 ```
63
64 We plan to introduce a **voidness preservation analysis** (which is similar
Lasse Reichstein Nielsen 2017/08/09 13:41:42 plan -> intend
eernst 2017/08/09 14:30:03 Done.
65 to a small type system) to keep track of such situations. As mentioned, the
66 second phase is **not specified in this document**, and it is possible that
67 voidness preservation will be checked in Dart 2 and strong mode, but that
68 it is never added to Dart 1.x. In any case, voidness preservation is a
Lasse Reichstein Nielsen 2017/08/09 13:41:42 Again, we are past Dart 1.x now.
eernst 2017/08/09 14:30:03 Deleted the part that mentions language versions:
69 purely static analysis, and there are no plans to introduce dynamic
70 checking for it.
71
72 ## Syntax
73
74 The reserved word `void` remains a reserved word, but it will now be usable
75 in additional contexts. Below are the grammar rules affected by this
76 change. New grammar rules are marked NEW, other grammar rules are
77 modified. Unchanged alternatives in a rule are shown as `...`. The grammar
78 rules used as a starting point for this syntax are taken from the language
79 specification as of June 2nd, 2017 (git commit 0603b18).
Lasse Reichstein Nielsen 2017/08/09 13:41:42 We will need to update this for Function types (wh
eernst 2017/08/09 14:30:03 The reference to the spec grammar below (CL 268890
80
81 ```
82 typeNotVoid ::= // NEW
83 typeName typeArguments?
84 type ::= // ENTIRE RULE MODIFIED
85 typeNotVoid | 'void'
86 redirectingFactoryConstructorSignature ::=
87 'const'? 'factory' identifier ('.' identifier)?
88 formalParameterList `=' typeNotVoid ('.' identifier)?
89 superclass ::=
90 'extends' typeNotVoid
91 mixinApplication ::=
92 typeNotVoid mixins interfaces?
93 typeParameter ::=
94 metadata identifier ('extends' typeNotVoid)?
95 newExpression ::=
96 'new' typeNotVoid ('.' identifier)? arguments
97 constObjectExpression ::=
98 'const' typeNotVoid ('.' identifier)? arguments
99 typeTest ::=
100 isOperator typeNotVoid
101 typeCast ::=
102 asOperator typeNotVoid
103 onPart ::=
104 catchPart block |
105 'on' typeNotVoid catchPart? block
106 typeNotVoidList ::=
107 typeNotVoid (',' typeNotVoid)*
108 mixins ::=
109 'with' typeNotVoidList
110 interfaces ::=
111 'implements' typeNotVoidList
112 functionSignature ::=
113 metadata type? identifier formalParameterList
114 functionFormalParameter ::=
115 metadata 'covariant'? type? identifier formalParameterList
116 operatorSignature ::=
117 type? 'operator' operator formalParameterList
118 getterSignature ::=
119 type? 'get' identifier
120 setterSignature ::=
121 type? 'set' identifier formalParameterList
122 topLevelDefinition ::=
123 ...
124 type? 'get' identifier functionBody |
125 type? 'set' identifier formalParameterList functionBody |
126 ...
127 functionPrefix ::=
128 type? identifier
129 ```
130
131 The rule for `returnType` in the grammar is deleted.
132
133 *This is because we can now use `type`, which derives the same expressions
134 as `returnType` used to derive. In that sense, some of these grammar
135 modifications are renames. Note that the grammar contains known mistakes,
136 especially concerned with the placement of `metadata`. This document makes
137 no attempt to correct those mistakes, that is a separate issue.*
138
139 *A complete grammar which includes support for generalized void is
140 available in the file Dart.g
141 from
142 [https://codereview.chromium.org/2688903004/](https://codereview.chromium.org/26 88903004/).*
143
144 ## Dynamic semantics
145
146 There are no values at run time whose dynamic type is the type void.
147
148 *This implies that it is never required for the getter `runtimeType` in the
149 built-in class `Object` to return a reified representation of the type
150 void. Note, however, that apart from the fact that usage is restricted for
151 values with the type void, it is possible for an expression of type void to
152 evaluate to any value. In that sense, every value has the type void, it is
153 just not the only type that it has, and loosely speaking it is not the most
154 specific type.*
155
156 There is no value which is the reified representation of the type void at
157 run time.
158
159 *Syntactically, `void` cannot occur as an expression, and hence expression
160 evaluation cannot directly yield such a value. However, a formal type
161 parameter can be used in expressions, and the actual type argument bound to
162 that formal type parameter can be the type void. That case is specified
163 explicitly below. Apart from the reserved word `void` and a formal type
164 parameter, no other term can denote the type void.*
165
166 *Conversely, `void` cannot denote any other entity than the type void:
167 `void` cannot occur as the declared name of any declaration (including
168 library prefixes, types, variables, parameters, etc.). This implies that
169 `void` is not subject to scoped lookup, and the name is not exported by any
170 system library. Similarly, it can never be accessed using a prefixed
171 expression (`p.void`). Hence, `void` has a fixed meaning everywhere in all
172 Dart programs, and it can only occur as a stand-alone word.*
173
174 When `void` is passed as an actual type argument to a generic class or a
175 generic function, and when the type void occurs as a parameter type in a
176 function type, the reified representation is equal (according to `==`) to
177 the reified representation of the built-in class `Object`.
178
179 *It is encouraged for an implementation to use a reified representation for
180 `void` as a type argument and as a parameter type in a function type which
181 is not `identical` to the reified representation of the built-in class
182 `Object`, but they must be equal. This allows implementations to produce
183 better diagnostic messages, e.g., in case of a runtime error.*
184
185 *This treatment of the reified representation of the type void reinforces
186 the understanding that "voidness" is merely a statically known flag on the
187 built-in class `Object`, it is not a separate type. However, for backward
188 compatibility we need to treat return types differently.*
189
190 When `void` is specified as the return type of a function, the reified
191 representation of the return type is left unspecified.
192
193 *There is no way for a Dart program at run time to obtain a reified
194 representation of that return type alone, even when the function type as a
195 whole may be obtained (e.g., the function type could be evaluated as an
196 expression). It is therefore not necessary to reified representation of
197 such a return type.*
198
199 *It may be possible to use a reflective subsystem (mirrors) to deconstruct
200 a function type whose return type is the type void, but the existing design
201 of the system library `dart:mirrors` already handles this case by allowing
202 for a type mirror that does not have a reflected type.*
203
204 Consider a type _T_ where the type void occurs as an actual type argument
205 to a generic class, or as a parameter type in a function type. Dynamically,
206 the more-specific-than relation (`<<`) and the dynamic subtype relation
207 (`<:`) between _T_ and other types are determined by the following rule:
208 the type void is treated as being the built-in class `Object`.
209
210 *Dart 1.x does not support generic function types dynamically, because they
211 are erased to regular function types during compilation. Hence there is no
212 need to specify the the typing relations for generic function types. In
213 Dart 2, the subtype relationship for generic function types follows from
214 the rule that `void` is treated as `Object`.*
215
216 Consider a function type _T_ where the return type is the type void. The
217 dynamic more-specific-than relation, `<<`, and the dynamic subtype
218 relation, `<:`, are determined by the existing rules in the language
219 specification, supplemented by the above rule for handling occurrences of
220 the type void other than as a return type.
221
222 *This ensures backward compatibility for the cases where the type void can
223 be used already today. It follows that it will be a breaking change to
224 switch to a ruleset where the type void even as a return type is treated
225 like the built-in class Object, i.e. when switching to Dart 2.0. However,
226 the only situation where the semantics differs is as follows: Consider a
227 situation where a value of type `void Function(...)` is assigned to a
228 variable or parameter `x` whose type annotation is `Object Function(...)`,
229 where the argument types are arbitrary, but such that the assignment is
230 permitted. In that situation, in checked mode, the assignment will fail
231 with the current semantics, because the type of that value is not a subtype
232 of the type of `x`. The rules in this document preserve that behavior. If
233 we were to consistently treat the type void as `Object` at run time (as in
234 Dart 2) then this assignment would be permitted (but we would then use
235 voidness preservation to detect and avoid this situation at compile time).*
236
237 *The semantics of checked mode checks involving types where the type void
238 occurs is determined by the semantics of subtype tests, so we do not
239 specify that separately.*
240
241 An instantiation of a generic class `G` is malbounded if it contains `void`
242 as an actual type argument for a formal type parameter, unless that type
243 parameter does not have a bound, or it has a bound which is the built-in
244 class `Object`, or `dynamic`.
245
246 *The treatment of malbounded types follows the current specification.*
247
248 ## Static Analysis
249
250 For the static analysis, the more-specific-than relation, `<<`, and the
251 subtype relation, `<:`, are determined by the same rules as described above
252 for the dynamic semantics.
253
254 *That is, the type void is considered to be equivalent to the built-in
255 class `Object`, except when used as a return type, in which case it is
256 effectively considered to be a proper supertype of `Object`. As mentioned,
257 voidness preservation is a separate analysis which is not specified by this
258 document, but it is intended to be used in the future to track "voidness"
259 in types and flag implicit casts wherein information about voidness may
260 indirectly be lost. With voidness preservation in place, we expect to be
261 able to treat the type void as `Object` in all cases during subtype
262 checks.*
263
264 It is a static warning for an expression to have type void, except for the
Lasse Reichstein Nielsen 2017/08/09 13:41:42 In Dart 2, this will be a compile-time error, so j
eernst 2017/08/09 14:30:03 Ah, that's funny: I had 'compile-time error' here
265 following situations:
266
267 * In an expressionStatement `e;`, e may have type void.
268 * In the initialization and increment expressions of a for-loop,
269 `for (e1; e2; e3) {..}`, `e1` and `e3` may have type void.
270 * In a typeCast `e as T`, `e` may have type void.
271 * In a typeTest `e is T` or `e is! T`, `e` may have type void.
272 * In a parenthesized expression `(e)`, `e` may have type void.
273 * In a return statement `return e;`, when the return type of the innermost
274 enclosing function is the type void, `e` may have type void.
275
276 *Note that the parenthesized expression itself has type void, so it is
277 again subject to the same constraints. Also note that we may not allow
278 return statements returning an expression of type void in the future, but
279 it is allowed here for backward compatibility.*
280
281 During bounds checking, it is possible that a bound of a formal type
282 parameter of a generic class or function is statically known to be the type
283 void. In this case, the bound is considered to be the built-in class
284 `Object`.
285
286 ## Discussion
287
288 Expressions derived from typeCast and typeTest do not support `void` as the
289 target type. We have omitted support for this situation because we consider
290 it to be useless. If void is passed indirectly via a type variable `T` then
291 `e as T`, `e is T`, and `e is! T` will treat `T` like `Object`. In general,
292 the rationale is that the type void admits all values (because it is just
293 `Object` plus a "static voidness flag"), but values of type void should be
294 discarded.
295
296 The treatment of bounds is delicate. We syntactically prohibit `void` as a
297 bound of a formal type parameter of a generic class or function. It is
298 possible to pass the type void as an actual type argument to a generic
299 class, and that type argument might in turn be used as the bound of another
300 formal type parameter of the class, or of a generic function in the
301 class. It would be possible to make it a compile-time error to pass `void`
302 as a type argument to a generic class where it will be used as a bound, but
303 this would presumably require a transitive traversal of all generic classes
304 and functions where the corresponding formal type parameter is passed on to
305 other generic classes or functions, which would be highly brittle: A tiny
306 change to a generic class or function could break code far away. So we do
307 not wish to prevent formal type parameter bounds from indirectly becoming
308 the type void. This motivated the decision to treat such a void-valued
309 bound as `Object`.
310
311 ## Updates
312
313 * August 9th 2017: Transferred to SDK repo, docs/language/informal.
314
315 * July 16th 2017: Reformatted as a gist.
316
317 * June 13th 2017: Compile-time error for using a void value was changed to
318 static warning.
319 * June 12th 2017: Grammar changed extensively, to use
320 `typeNotVoid` rather than
321 `voidOrType`.
322 * June 5th 2017: Added `typeCast` and
323 `typeTest` to the locations where void
324 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