@@ -108,8 +108,8 @@ that assignment).
108
108
- Lists
109
109
- We use the notation ` [a, b] ` to denote a list containing elements ` a ` and
110
110
` b ` .
111
- - We use the notation ` a::l ` where ` l ` is a list to denote a list beginning
112
- with ` a ` and followed by all of the elements of ` l ` .
111
+ - We use the notation ` [...l, a] ` where ` l ` is a list to denote a list
112
+ beginning with all the elements of ` l ` and followed by ` a ` .
113
113
114
114
- Stacks
115
115
- We use the notation ` push(s, x) ` to mean pushing ` x ` onto the top of the
@@ -118,8 +118,8 @@ that assignment).
118
118
the top element of ` s ` . If ` s ` is empty, the result is undefined.
119
119
- We use the notation ` top(s) ` to mean the top element of the stack ` s ` . If
120
120
` s ` is empty, the result is undefined.
121
- - Informally, we also use ` a::t ` to describe a stack ` s ` such that ` top(s) ` is
122
- ` a ` and ` pop(s) ` is ` t ` .
121
+ - Informally, we also use ` [...t, a] ` to describe a stack ` s ` such that
122
+ ` top(s) ` is ` a ` and ` pop(s) ` is ` t ` .
123
123
124
124
### Models
125
125
@@ -131,10 +131,10 @@ source code.
131
131
- ` declaredType ` is the type assigned to the variable at its declaration site
132
132
(either explicitly or by type inference).
133
133
134
- - ` promotedTypes ` is an ordered set of types that the variable has been promoted
135
- to, with the final entry in the ordered set being the current promoted type of
136
- the variable. Note that each entry in the ordered set must be a subtype of
137
- all previous entries , and of the declared type.
134
+ - ` promotedTypes ` is a list of types that the variable has been promoted to,
135
+ with the final type in the list being the current promoted type of the
136
+ variable. Note that each type in the list must be a subtype of all previous
137
+ types , and of the declared type.
138
138
139
139
- ` tested ` is a set of types which are considered "of interest" for the purposes
140
140
of promotion, generally because the variable in question has been tested
@@ -238,9 +238,14 @@ We also make use of the following auxiliary functions:
238
238
- ` VM3 = VariableModel(d3, p3, s3, a3, u3, c3) ` where
239
239
- ` d3 = d1 = d2 `
240
240
- Note that all models must agree on the declared type of a variable
241
- - ` p3 = p1 ^ p2 `
242
- - ` p1 ` and ` p2 ` are totally ordered subsets of a global partial order.
243
- Their intersection is a subset of each, and as such is also totally ordered.
241
+ - ` p3 ` is a list formed by taking all the types that are in both ` p1 ` and
242
+ ` p2 ` , and ordering them such that each type in the list is a subtype of all
243
+ previous types.
244
+ - _ Note: it is not specified how to order elements of this list that are
245
+ mutual subtypes of each other. This will soon be addressed by changing
246
+ the behavior of flow analysis so that each type in the list is a proper
247
+ subtype of the previous. (See
248
+ https://github.com/dart-lang/language/issues/4368 .)
244
249
- ` s3 = s1 U s2 `
245
250
- The set of test sites is the union of the test sites on either path
246
251
- ` a3 = a1 && a2 `
@@ -258,14 +263,14 @@ We also make use of the following auxiliary functions:
258
263
where ` r2 ` is ` r ` with ` true ` pushed as the top element of the stack.
259
264
260
265
- ` drop(M) ` , where ` M = FlowModel(r, VM) ` is defined as ` FlowModel(r1, VM) `
261
- where ` r ` is of the form ` n0::r1 ` . This is the flow model which drops
266
+ where ` r ` is of the form ` [...r1, n0] ` . This is the flow model which drops
262
267
the reachability information encoded in the top entry in the stack.
263
268
264
269
- ` unsplit(M) ` , where ` M = FlowModel(r, VM) ` is defined as `M1 = FlowModel(r1,
265
- VM)` where ` r` is of the form ` n0::n1::s ` and ` r1 = ( n0&&n1)::s `. The model
266
- ` M1 ` is a flow model which collapses the top two elements of the reachability
267
- model from ` M ` into a single boolean which conservatively summarizes the
268
- reachability information present in ` M ` .
270
+ VM)` where ` r` is of the form ` [ ...s, n1, n0 ] ` and ` r1 = [ ...s, n0&&n1] `. The
271
+ model ` M1 ` is a flow model which collapses the top two elements of the
272
+ reachability model from ` M ` into a single boolean which conservatively
273
+ summarizes the reachability information present in ` M ` .
269
274
270
275
- ` merge(M1, M2) ` , where ` M1 ` and ` M2 ` are flow models is the inverse of ` split `
271
276
and represents the result of joining two flow models at the merge of two
@@ -393,7 +398,7 @@ Promotion policy is defined by the following operations on flow models.
393
398
394
399
We say that the ** current type** of a variable ` x ` in variable model ` VM ` is ` S ` where:
395
400
- ` VM = VariableModel(declared, promoted, tested, assigned, unassigned, captured) `
396
- - ` promoted = S::l ` or (` promoted = [] ` and ` declared = S ` )
401
+ - ` promoted = [...l, S] ` or (` promoted = [] ` and ` declared = S ` )
397
402
398
403
Policy:
399
404
- We say that at type ` T ` is a type of interest for a variable ` x ` in a set of
@@ -421,8 +426,8 @@ Policy:
421
426
type ` T ` given variable model ` VM ` if
422
427
- ` VM = VariableModel(declared, promoted, tested, assigned, unassigned, captured) `
423
428
- and ` captured ` is false
424
- - and declared:: promoted contains a type ` S ` such that ` T ` is ` S ` or ` T ` is
425
- ** NonNull(` S ` )** .
429
+ - and [ ... promoted, declared ] contains a type ` S ` such that ` T ` is ` S ` or
430
+ ` T ` is ** NonNull(` S ` )** .
426
431
427
432
Definitions:
428
433
@@ -433,13 +438,14 @@ Definitions:
433
438
- if ` captured ` is true then:
434
439
- ` VM = VariableModel(declared, promoted, tested, true, false, captured) ` .
435
440
- otherwise if ` x ` is promotable via assignment of ` E ` given ` VM `
436
- - ` VM = VariableModel(declared, T::promoted, tested, true, false, captured) ` .
441
+ - `VM = VariableModel(declared, [ ...promoted, T] , tested, true, false,
442
+ captured)`.
437
443
- otherwise if ` x ` is demotable via assignment of ` E ` given ` VM `
438
444
- ` VM = VariableModel(declared, demoted, tested, true, false, captured) ` .
439
- - where ` previous ` is the suffix of ` promoted ` starting with the first type
445
+ - where ` previous ` is the prefix of ` promoted ` ending with the first type
440
446
` S ` such that ` T <: S ` , and:
441
- - if ` S ` is nullable and if ` T <: Q ` where ` Q ` is ** NonNull(` S ` )** then
442
- ` demoted ` is ` Q:: previous`
447
+ - if ` S ` is nullable and if ` T <: Q ` where ` Q ` is ** NonNull(` S ` )** then
448
+ ` demoted ` is ` [... previous, Q] `
443
449
- otherwise ` demoted ` is ` previous `
444
450
445
451
- ` stripParens(E1) ` , where ` E1 ` is an expression, is the result of stripping
@@ -467,8 +473,8 @@ Definitions:
467
473
- Else if ` S ` is ` X extends R ` then let ` T1 ` = ` X & T `
468
474
- Else If ` S ` is ` X & R ` then let ` T1 ` = ` X & T `
469
475
- Else ` x ` is not promotable (shouldn't happen since we checked above)
470
- - Let `VM2 = VariableModel(declared, T1:: promoted, T:: tested, assigned ,
471
- unassigned, captured)`
476
+ - Let `VM2 = VariableModel(declared, [ ... promoted, T1 ] , [ ... tested, T ] ,
477
+ assigned, unassigned, captured)`
472
478
- Let ` M2 = FlowModel(r, VI[x -> VM2]) `
473
479
- If ` T1 <: Never ` then ` M3 ` = ` unreachable(M2) ` , otherwise ` M3 ` = ` M2 `
474
480
- ` promoteToNonNull(E, M) ` where ` E ` is an expression and ` M ` is a flow model is
0 commit comments