@@ -110,6 +110,14 @@ that assignment).
110
110
` b ` .
111
111
- We use the notation ` [...l, a] ` where ` l ` is a list to denote a list
112
112
beginning with all the elements of ` l ` and followed by ` a ` .
113
+ - A list of types ` p ` is called a _ promotion chain_ iff, for all ` i < j ` ,
114
+ ` p[i] <: p[j] ` . _ Note that since the subtyping relation is transitive, in
115
+ order to establish that ` p ` is a promotion chain, it is sufficient to check
116
+ the ` p[i] <: p[j] ` relation for each adjacent pair of types._
117
+ - A promotion chain ` p ` is said to be _ valid for declared type ` T ` _ iff every
118
+ type in ` p ` is a subtype of ` T ` . _ Note that since the subtyping relation is
119
+ transitive, in order to establish that ` p ` is valid for declared type ` T ` ,
120
+ it is sufficient to check that the first type in ` p ` is a subtype of ` T ` ._
113
121
114
122
- Stacks
115
123
- We use the notation ` push(s, x) ` to mean pushing ` x ` onto the top of the
@@ -123,18 +131,18 @@ that assignment).
123
131
124
132
### Models
125
133
126
- A * variable model* , denoted `VariableModel(declaredType, promotedTypes ,
134
+ A * variable model* , denoted `VariableModel(declaredType, promotionChain ,
127
135
tested, assigned, unassigned, writeCaptured)`, represents what is statically
128
136
known to the flow analysis about the state of a variable at a given point in the
129
137
source code.
130
138
131
139
- ` declaredType ` is the type assigned to the variable at its declaration site
132
140
(either explicitly or by type inference).
133
141
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.
142
+ - ` promotionChain ` is the variable's promotion chain. This is a list of types
143
+ that the variable has been promoted to, with the final type in the list being
144
+ the current promoted type of the variable. It must always be a valid promotion
145
+ chain for declared type ` declaredType ` .
138
146
139
147
- ` tested ` is a set of types which are considered "of interest" for the purposes
140
148
of promotion, generally because the variable in question has been tested
@@ -397,8 +405,8 @@ We also make use of the following auxiliary functions:
397
405
Promotion policy is defined by the following operations on flow models.
398
406
399
407
We say that the ** current type** of a variable ` x ` in variable model ` VM ` is ` S ` where:
400
- - ` VM = VariableModel(declared, promoted , tested, assigned, unassigned, captured) `
401
- - ` promoted = [...l, S]` or (` promoted = []` and ` declared = S ` )
408
+ - ` VM = VariableModel(declared, promotionChain , tested, assigned, unassigned, captured) `
409
+ - ` promotionChain = [...l, S]` or (` promotionChain = []` and ` declared = S ` )
402
410
403
411
Policy:
404
412
- We say that at type ` T ` is a type of interest for a variable ` x ` in a set of
@@ -407,7 +415,7 @@ Policy:
407
415
408
416
- We say that a variable ` x ` is promotable via type test with type ` T ` given
409
417
variable model ` VM ` if
410
- - ` VM = VariableModel(declared, promoted , tested, assigned, unassigned, captured) `
418
+ - ` VM = VariableModel(declared, promotionChain , tested, assigned, unassigned, captured) `
411
419
- and ` captured ` is false
412
420
- and ` S ` is the current type of ` x ` in ` VM `
413
421
- and not ` S <: T `
@@ -416,23 +424,27 @@ Policy:
416
424
417
425
Definitions:
418
426
419
- - ` currentType(declared, promoted) ` , where ` declared ` is a type and ` promoted `
420
- is a list of types, is the type ` T ` , defined as follows:
421
- - If ` promoted ` is ` [] ` , ` T ` is ` declared ` .
422
- - Otherwise, ` T ` is the last type in the ` promoted ` list.
423
-
424
- - ` demote(promoted, written) ` , where ` promoted ` is a list of types and ` written `
425
- is a type, is a list obtained by deleting any elements from ` promoted ` that do
426
- not satisfy ` written <: T ` . _ In effect, this removes any type promotions that
427
- are no longer valid after the assignment of a value of type ` written ` ._
428
-
429
- - ` toi_promote(declared, demoted, tested, written) ` , where ` demoted ` and
430
- ` tested ` are lists of types, and ` declared ` and ` written ` are types, is the
431
- list ` promoted ` , defined as follows. _ ("toi" stands for "type of interest".)_
432
- - Let ` current = currentType(declared, demoted) ` . _ (This is the type of the
433
- variable after demotions, but before type of interest promotion.)_
434
- - If ` written ` and ` current ` are the same type, then ` promoted ` is
435
- ` demoted ` . _ (No type of interest promotion is necessary in this case.)_
427
+ - ` demote(promotionChain, written) ` , is a promotion chain obtained by deleting
428
+ any elements from ` promotionChain ` that do not satisfy ` written <: T ` . _ In
429
+ effect, this removes any type promotions that are no longer valid after the
430
+ assignment of a value of type ` written ` ._
431
+ - _ Note that if ` promotionChain ` is valid for declared type ` T ` , it follows
432
+ that ` demote(promotionChain, written) ` is also valid for declared type ` T ` ._
433
+
434
+ - ` toi_promote(declared, promotionChain, tested, written) ` , where ` declared ` and
435
+ ` written ` are types satisfying ` written <: declared ` , ` promotionChain ` is
436
+ valid for declared type ` declared ` , and all types ` T ` in ` promotionChain `
437
+ satisfy ` written <: T ` , is the promotion chain ` newPromotionChain ` , defined as
438
+ follows. _ ("toi" stands for "type of interest".)_
439
+ - Let ` provisionalType ` be the last type in ` promotionChain ` , or ` declared ` if
440
+ ` promotionChain ` is empty. _ (This is the type of the variable after
441
+ demotions, but before type of interest promotion.)_
442
+ - _ Since the last type in a promotion chain is a subtype of all the others,
443
+ it follows that all types ` T ` in ` promotionChain ` satisfy `provisionalType
444
+ <: T`._
445
+ - If ` written ` and ` current ` are the same type, then ` newPromotionChain ` is
446
+ ` promotionChain ` . _ (No type of interest promotion is necessary in this
447
+ case.)_
436
448
- Otherwise _ (when ` written ` is not ` current ` )_ , let ` p1 ` be a set containing
437
449
the following types:
438
450
- ** NonNull** (` declared ` ), if it is not the same as ` declared ` .
@@ -442,38 +454,50 @@ Definitions:
442
454
443
455
_ The types in ` p1 ` are known as the types of interest._
444
456
- Let ` p2 ` be the set ` p1 \ { current } ` _ (where ` \ ` denotes set difference)_ .
445
- - If the ` written ` type is in ` p2 ` , and ` written <: current ` , then ` promoted `
446
- is ` [...demoted, written] ` . _ Writing a value whose static type is a type of
447
- interest promotes to that type._
448
- - _ Since ` written ` is the type assigned to the variable (after type
449
- coercion), in non-erroneous code it is guaranteed to be a subtype of
450
- ` declared ` . And ` toi_promote ` is always applied to the result of ` demote ` ,
451
- so all types in ` demoted ` are guaranteed to be supertypes of
452
- ` written ` . Therefore, the requirement that ` written <: current ` is
453
- automatically satisfied for non-erroneous code._
457
+ - If the ` written ` type is in ` p2 ` , and ` written <: provisionalType ` , then
458
+ ` newPromotionChain ` is ` [...promotionChain, written] ` . _ Writing a value
459
+ whose static type is a type of interest promotes to that type._
460
+ - _ By precondition, ` written <: declared ` and ` written <: T ` for all types
461
+ in ` promotionChain ` . Therefore, ` newPromotionChain ` satisfies the
462
+ definition of a promotion chain, and is valid for declared type
463
+ ` declared ` ._
454
464
- Otherwise _ (when ` written ` is not in ` p2 ` )_ :
455
465
- Let ` p3 ` be the set of all types ` T ` in ` p2 ` such that `written <: T <:
456
- current `.
466
+ provisionalType `.
457
467
- If ` p3 ` contains exactly one type ` T ` that is a subtype of all the others,
458
- then ` promoted ` is ` [...demoted , T] ` . _ Writing a value whose static type
459
- is a subtype of a type of interest promotes to that type of interest,
468
+ then ` promoted ` is ` [...promotionChain , T] ` . _ Writing a value whose static
469
+ type is a subtype of a type of interest promotes to that type of interest,
460
470
provided there is a single "best" type of interest available to promote
461
471
to._
462
- - Otherwise, ` promoted ` is ` demoted ` . _ If there is no single "best" type
463
- of interest to promote to, then no type of interest promotion is done._
472
+ - _ Since ` T <: provisionalType <: declared ` , and all types ` U ` in
473
+ ` promotionChain ` satisfy ` provisionalType <: U ` , it follows that all
474
+ types ` U ` in ` promotionChain ` satisfy ` T <: U ` . Therefore
475
+ ` newPromotionChain ` satisfies the definition of a promotion chain, and
476
+ is valid for declared type ` declared ` ._
477
+ - Otherwise, ` newPromotionChain ` is ` promotionChain ` . _ If there is no single
478
+ "best" type of interest to promote to, then no type of interest promotion
479
+ is done._
464
480
465
481
- ` assign(x, E, M) ` where ` x ` is a local variable, ` E ` is an expression of
466
- inferred type ` T ` , and ` M = FlowModel(r, VI) ` is the flow model for ` E ` is
467
- defined to be ` FlowModel(r, VI[x -> VM]) ` where:
482
+ inferred type ` T ` (which must be a subtype of ` x ` 's declared type), and `M =
483
+ FlowModel(r, VI)` is the flow model for ` E` is defined to be ` FlowModel(r,
484
+ VI[ x -> VM] )` where:
468
485
- `VI(x) = VariableModel(declared, promoted, tested, assigned, unassigned,
469
486
captured)`
470
487
- If ` captured ` is true then:
471
- - ` VM = VariableModel(declared, promoted , tested, true, false, captured) ` .
488
+ - ` VM = VariableModel(declared, promotionChain , tested, true, false, captured) ` .
472
489
- Otherwise:
473
490
- Let ` written = T ` .
474
- - Let ` demoted = demote(promoted, written) ` .
475
- - Let ` promoted' = toi_promote(declared, demoted, tested, written) ` .
476
- - Then `VM = VariableModel(declared, promoted', tested, true, false,
491
+ - Let ` promotionChain' = demote(promotionChain, written) ` .
492
+ - Let `promotionChain'' = toi_promote(declared, promotionChain', tested,
493
+ written)`.
494
+ - _ The preconditions for ` toi_promote ` are satisfied because:_
495
+ - _ ` demote ` deletes any elements from ` promotionChain ` that do not
496
+ satisfy ` written <: T ` , therefore every element of ` promotionChain' `
497
+ satisfies ` written <: T ` ._
498
+ - _ ` written = T ` and ` T ` is a subtype of ` x ` 's declared type, therefore
499
+ ` written <: declared ` ._
500
+ - Then `VM = VariableModel(declared, promotionChain'', tested, true, false,
477
501
captured)`.
478
502
479
503
- ` stripParens(E1) ` , where ` E1 ` is an expression, is the result of stripping
@@ -579,7 +603,12 @@ then they are all assigned the same value as `after(N)`.
579
603
- ** Local-variable assignment** : If ` N ` is an expression of the form ` x = E1 `
580
604
where ` x ` is a local variable, then:
581
605
- Let ` before(E1) = before(N) ` .
582
- - Let ` after(N) = assign(x, E1, after(E1)) ` .
606
+ - Let ` E1' ` be the result of applying type coercion to ` E1 ` , to coerce it to
607
+ the declared type of ` x ` .
608
+ - Let ` after(N) = assign(x, E1', after(E1)) ` .
609
+ - _ Since type coercion to type ` T ` produces an expression whose static type
610
+ is a subtype of ` T ` , the precondition of ` assign ` is satisfied, namely
611
+ that the static type of ` E1' ` must be a subtype of ` x ` 's declared type._
583
612
584
613
- ** operator==** If ` N ` is an expression of the form ` E1 == E2 ` , where the
585
614
static type of ` E1 ` is ` T1 ` and the static type of ` E2 ` is ` T2 ` , then:
@@ -645,7 +674,12 @@ then they are all assigned the same value as `after(N)`.
645
674
- ** Local variable conditional assignment** : If ` N ` is an expression of the form
646
675
` x ??= E1 ` where ` x ` is a local variable, then:
647
676
- Let ` before(E1) = split(promote(x, Null, before(N))) ` .
648
- - Let ` M1 = assign(x, E1, after(E1)) `
677
+ - Let ` E1' ` be the result of applying type coercion to ` E1 ` , to coerce it to
678
+ the declared type of ` x ` .
679
+ - Let ` M1 = assign(x, E1', after(E1)) `
680
+ - _ Since type coercion to type ` T ` produces an expression whose static type
681
+ is a subtype of ` T ` , the precondition of ` assign ` is satisfied, namely
682
+ that the static type of ` E1' ` must be a subtype of ` x ` 's declared type._
649
683
- Let ` M2 = split(promoteToNonNull(x, before(N))) `
650
684
- Let ` after(N) = merge(M1, M2) `
651
685
0 commit comments