Skip to content

Commit 85e7b86

Browse files
Clean-ups to horizontal inference feature specification. (#2236)
1 parent 51de4a1 commit 85e7b86

File tree

2 files changed

+112
-27
lines changed

2 files changed

+112
-27
lines changed

accepted/future-releases/horizontal-inference/feature-specification.md

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Horizontal inference
22

3-
Author: [email protected], Version: 1.0 (See [Changelog](#Changelog) at end)
3+
Author: [email protected], Version: 1.2 (See [Changelog](#Changelog) at end)
44

55
Horizontal inference allows certain arguments of an invocation (specifically
66
function literals) to be type inferred in a context derived from the type of
@@ -38,7 +38,7 @@ var largestValue = values.fold(0, (a, b) => a < b ? b : a);
3838
Today this doesn't work, because without the leading `int`, the downwards
3939
inference phase of type inference has no information with which to choose a
4040
preliminary type for the type parameter `T`, so the type context used for
41-
inference of the function literal `(a, b) => a < b ? b : a` is `? Function(?,
41+
inference of the function literal `(a, b) => a < b ? b : a` is `_ Function(_,
4242
int)`. Hence, `a` gets assigned a static type of `Object?`, and this leads to a
4343
compile error at `a < b`.
4444

@@ -114,11 +114,15 @@ In this document we make use of the following terms:
114114
normal Dart type syntax, extended with a type known as "the unknown type"
115115
(denoted `_`), which allows representation of incomplete type information.
116116

117-
- An expression's "type context" is a type schema representing what is known
118-
about the probable type of the expression just before the portion of the type
119-
inference algorithm that visits it. This, together with other information
120-
defined in [flow analysis][], constitutes the _input_ to the corresponding
121-
type inference step.
117+
- An expression's "type context" is a type schema representing information
118+
captured by the type inference algorithm from the context surrounding it. In
119+
most circumstances, it represents the set of static types that the expression
120+
could have without provoking a static error. _(There are a few exceptions;
121+
for example the context of the RHS of an assignment to a promoted variable is
122+
the set of types that the expression could have without causing the variable
123+
to be demoted)._ The type context of an expression, together with other
124+
information defined in [flow analysis][], constitutes the **input** to the
125+
corresponding type inference step.
122126

123127
- An "implicit type argument" is a type argument to a generic invocation whose
124128
precise value is not directly specified in code, but is instead determined
@@ -141,22 +145,27 @@ In this document we make use of the following terms:
141145
a type variable based on a set of constraints. It may contain occurrences of
142146
the unknown type.
143147

148+
- The "constraint solution for a set of type variables" (defined
149+
[here][constraint solution for a set of type variables]) is a mapping from
150+
type variables to type schemas, formed from a set of constraints and a partial
151+
solution. Typically, each type variable is mapped to the result of solving
152+
the constraints that apply to it (according to the bullet above), plus an
153+
additional constraint based on the bound of the type variable. The partial
154+
solution is used to break loops when the bound of one type variable refers to
155+
others, and to effectively "freeze" the solution of each variable at the time
156+
it becomes fully known (that is, it does not contain `_`).
157+
144158
- The "grounded constraint solution for a type variable" (defined
145159
[here][grounded constraint solution for a type variable]) is a final
146-
assignment of a type to a type schema based on a set of constraints. It is a
147-
type, not a type schema, so it may not contain occurrences of the unknown
160+
assignment of a type to a type variable based on a set of constraints. It is
161+
a type, not a type schema, so it may not contain occurrences of the unknown
148162
type.
149163

150-
- The "(possibly grounded) constraint solution for a set of type variables,
151-
considering bounds" is a mapping from type variables to type schemas (or, in
152-
the grounded case, types), formed from a set of constraints. Each type
153-
variable is mapped to the result of solving the constraints that apply to it
154-
(according to one of the two bullets above), plus an additional constraint
155-
based on the bound of the type variable. Since the bounds of some type
156-
variables may depend on the values of others, the exact algorithm for this is
157-
subtle, and depends on the order in which the type variables are considered.
158-
The exact algorithm is outside the scope of this document; unfortunately I
159-
haven't found an exact specification for it.
164+
- The "grounded constraint solution for a set of type variables" (defined
165+
[here][grounded constraint solution for a set of type variables]) is a final
166+
mapping from type variables to types, formed from a set of constraints and a
167+
partial solution. It parallels the corresponding definition for the
168+
non-grounded constraint solution.
160169

161170
- A "function literal expression" is a syntactic construct that consists of a
162171
_\<functionExpression\>_, possibly enclosed in parentheses, and possibly
@@ -178,7 +187,9 @@ In this document we make use of the following terms:
178187
[type constraints]: https://github.com/dart-lang/language/blob/master/resources/type-system/inference.md#type-constraints
179188
[subtype constraint generation]: https://github.com/dart-lang/language/blob/master/resources/type-system/inference.md#subtype-constraint-generation
180189
[constraint solution for a type variable]: https://github.com/dart-lang/language/blob/master/resources/type-system/inference.md#constraint-solution-for-a-type-variable
190+
[constraint solution for a set of type variables]: https://github.com/dart-lang/language/blob/master/resources/type-system/inference.md#constraint-solution-for-a-set-of-type-variables
181191
[grounded constraint solution for a type variable]: https://github.com/dart-lang/language/blob/master/resources/type-system/inference.md#grounded-constraint-solution-for-a-type-variable
192+
[grounded constraint solution for a set of type variables]: https://github.com/dart-lang/language/blob/master/resources/type-system/inference.md#grounded-constraint-solution-for-a-set-of-type-variables
182193

183194
## Type inference algorithm for invocations
184195

@@ -209,8 +220,10 @@ Performing type inference on an invocation consists of the following steps:
209220
try to match the return type of the target function type as a subtype of the
210221
invocation's type context. This produces an initial set of type constraints.
211222
Then, using those constraints, find the constraint solution for the target
212-
function type's type variables, considering bounds. This produces a
213-
preliminary mapping of type variables to type schemas.
223+
function type's type variables, using an initial partial solution that maps
224+
all type variables to the unknown type. This produces a preliminary partial
225+
solution for the inferred types, which will be updated in later type
226+
inference steps.
214227

215228
4. Visit arguments: Partition the arguments into stages (see [argument
216229
partitioning](#Argument-partitioning) below), and then for each stage _k_, do
@@ -246,15 +259,17 @@ Performing type inference on an invocation consists of the following steps:
246259

247260
* Horizontal inference: if generic inference is needed, and this is not the
248261
last stage, use all the type constraints gathered so far to find the
249-
constraint solution for the target function's type variables, considering
250-
bounds. This produces an updated preliminary mapping of type parameters to
251-
type schemas.
262+
constraint solution for the target function's type variables, using the
263+
preliminary partial solution from the most recent previous execution of
264+
either this step or step 3. This produces an updated partial solution for
265+
the inferred types.
252266

253267
5. Upwards inference: if generic inference is needed, use all the type
254268
constraints gathered so far to find the **grounded** constraint solution for
255-
the target function's type variables, considering bounds. This produces the
256-
final mapping of type parameters to type schemas. Check that each type is a
257-
subtype of the bound of its corresponding type parameter.
269+
the target function's type variables, using the preliminary partial solution
270+
from the most recent execution of step 4. This produces the final solution
271+
for the inferred types. Check that each inferred type is a subtype of the
272+
bound of its corresponding type parameter.
258273

259274
6. Type checking: Check that the static type of each argument is assignable to
260275
the type obtained by substituting the final mapping (from step 5) into the
@@ -464,6 +479,17 @@ invocation target isn’t generic._
464479

465480
## Changelog
466481

482+
### 1.2
483+
484+
- Use `_` consistently to refer to the "unknown" type schema.
485+
486+
- Clarify what is meant by the term "type schema".
487+
488+
- Clarify the notions of "constraint solution for a set of type variables" and
489+
"grounded constraint solution for a set of type variables". These are now
490+
defined in `resources/type-system/inference.md`, so we include links to their
491+
definitions.
492+
467493
### 1.1
468494

469495
- Add "terminology" section, with references to other docs, and improve

resources/type-system/inference.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ Status: Draft
66

77
## CHANGELOG
88

9+
2022.05.12
10+
- Define the notions of "constraint solution for a set of type variables" and
11+
"Grounded constraint solution for a set of type variables". These
12+
definitions capture how type inference handles type variable bounds, as well
13+
as how inferred types become "frozen" once they are fully known.
14+
915
2019.09.01
1016
- Fix incorrect placement of left top rule in constraint solving.
1117

@@ -680,6 +686,39 @@ The constraint solution for a type variable `X` with respect to a constraint set
680686
Note that the constraint solution is a type schema, and hence may contain
681687
occurences of the unknown type.
682688

689+
#### Constraint solution for a set of type variables
690+
691+
The constraint solution for a set of type variables `{X0, ..., Xn}` with respect
692+
to a constraint set `C` and partial solution `{T0, ..., Tn}`, is defined to be
693+
the set of type schemas `{U0, ..., Un}` such that:
694+
- If `Ti` is known (that is, does not contain `_`), then `Ui = Ti`. _(Note
695+
that the upcoming "variance" feature will relax this rule so that it only
696+
applies to type variables without an explicitly declared variance.)_
697+
- Otherwise, let `Vi` be the constraint solution for the type variable `Xi`
698+
with respect to the constraint set `C`.
699+
- If `Vi` is not known (that is, it contains `_`), then `Ui = Vi`.
700+
- Otherwise, if `Xi` does not have an explicit bound, then `Ui = Vi`.
701+
- Otherwise, let `Bi` be the bound of `Xi`. Then, let `Bi'` be the type
702+
schema formed by substituting type schemas `{U0, ..., Ui-1, Ti, ..., Tn}` in
703+
place of the type variables `{X0, ..., Xn}` in `Bi`. _(That is, we
704+
substitute `Uj` for `Xj` when `j < i` and `Tj` for `Xj` when `j >= i`)._
705+
Then `Ui` is the constraint solution for the type variable `Xi` with respect
706+
to the constraint set `C + (X <: Bi')`.
707+
708+
_This definition can perhaps be better understood in terms of the practical
709+
consequences it has on type inference:_
710+
- _Once type inference has determined a known type for a type variable (that
711+
is, a type that does not contain `_`), that choice is frozen and is not
712+
affected by later type inference steps. (Type inference accomplishes this
713+
by passing in any frozen choices as part of the partial solution)._
714+
- _The bound of a type variable is only included as a constraint when the
715+
choice of type for that type variable is about to be frozen._
716+
- _During each round of type inference, type variables are inferred left to
717+
right. If the bound of one type variable refers to one or more type
718+
variables, then at the time the bound is included as a constraint, the type
719+
variables it refers to are assumed to take on the type schemas most recently
720+
assigned to them by type inference._
721+
683722
#### Grounded constraint solution for a type variable
684723

685724
The grounded constraint solution for a type variable `X` with respect to a
@@ -696,6 +735,26 @@ constraint set `C` is define as follows:
696735
Note that the grounded constraint solution is a type, and hence may not contain
697736
occurences of the unknown type.
698737

738+
#### Grounded constraint solution for a set of type variables
739+
740+
The grounded constraint solution for a set of type variables `{X0, ..., Xn}`
741+
with respect to a constraint set `C`, with partial solution `{T0, ..., Tn}`, is
742+
defined to be the set of types `{U0, ..., Un}` such that:
743+
- If `Ti` is known (that is, does not contain `_`), then `Ui = Ti`. _(Note
744+
that the upcoming "variance" feature will relax this rule so that it only
745+
applies to type variables without an explicitly declared variance.)_
746+
- Otherwise, if `Xi` does not have an explicit bound, then `Ui` is the
747+
grounded constraint solution for the type variable `Xi` with respect to the
748+
constraint set `C`.
749+
- Otherwise, let `Bi` be the bound of `Xi`. Then, let `Bi'` be the type
750+
schema formed by substituting type schemas `{U0, ..., Ui-1, Ti, ..., Tn}` in
751+
place of the type variables `{X0, ..., Xn}` in `Bi`. _(That is, we
752+
substitute `Uj` for `Xj` when `j < i` and `Tj` for `Xj` when `j >= i`)._
753+
Then `Ui` is the grounded constraint solution for the type variable `Xi`
754+
with respect to the constraint set `C + (X <: Bi')`.
755+
756+
_This definition parallels the definition of the (non-grounded) constraint
757+
solution for a set of type variables._
699758

700759
#### Constrained type variables
701760

0 commit comments

Comments
 (0)