• No results found

Relating type constraints to their source

In document Decrypting Local Type Inference (Page 106-110)

3.7 On understanding the type variable instantiation

3.7.2 Relating type constraints to their source

With the TypeFocus translation from the previous section, we have shown that type con- straints can be represented as type selections on types that participate in the subtyping deriva- 92

3.7. On understanding the type variable instantiation

FUNCTIONconstraint-to-slice((app), a,ψ±,Θa)=

(app) ?,Γ,wF :∀a.S → T [?/ a] S,Γ wE : S aS <: S ⇒ C 1 aT <:   P ⇒ C2 P,Γ wF (E ) :σ C1∪C2,TT P constraint-to-slicear g((app), a,ψ±,Θa) constraint-to-slicept((app), a,ψ±,Θa)

FUNCTIONconstraint-to-slicear g((app)(P,Γ wF(E):σC1,C2,TT P), a, ψ±

a)=

1 a,ψ±g en S<:S  Θ 2 Θ SLICES(([?/

a] S,Γ wE : S),normalize(Θi ::: Θa, S,)) forΘi∈ Θ

FUNCTIONconstraint-to-slicept((app)(P,Γ wF(E):σC1,C2,TT  P), a, ψ±

a)=

1 a,ψ±g en T <:  P  Θ

2 Θ νPT, (P,Γ wF(E):σC1∪C2,TT  P),normalize(Θ

i ::: Θa, P,fv(P )) forΘi∈ Θ

Figure 3.23: Definition of the partial function constraint-to-slice of type 

(P,Γ wE : T ), T,ψ±,Θ→ ν3, which analyzes the source of type constraints used to

infer the instantiation of a type variable. The origin of type constraints is explained using Typing Slices.

tion. In this section we show that such representation is sufficient to explain the origin of every individual type constraint.

We recall from Section 2.1.5, that the(app)inference rule infers the minimal type substitu- tionσC1∪C2,T, from the two distinct a-constraint sets:

1. The a-constraint set C1, inaS<: S ⇒ C1, infers type constraints from the subtyping

check between the type of the argument and the type of the corresponding formal pa- rameter. Importantly, the S type has been inferred through a regular type inference judgment and can be analyzed using the TypeFocus-based algorithm (Section 3.5.3). 2. The a-constraint set C2, inaT<:   P ⇒ C2, infers type constraints from the subtyp-

ing check between the inferred result type of the function and the inherited prototype. Importantly, the  P type has been inferred from the expected type context and can be analyzed using theSLICESPTfunction that analyzes the source of the prototype (Sec-

tion 3.6).

Figure 3.23 defines the algorithm that locates the source of used type constraints, based on the above observations. Aconstraint-to-slicepartial function of type



(P,Γ wE : T ), T,ψ±,Θ→ ν3is implemented in terms of two auxiliary partial functions,

Chapter 3. Guided-analysis for type derivation trees

parametrized by the function application inference judgment, a type variable which instan- tiation is to be analyzed, variance information indicating which kind of type bounds where used to infer the optimal solution, and a TypeFocus. The purpose of the TypeFocus value will be discussed later in the section. Both functions return the sequence of Typing Slices, which explain the origin of type constraints that instantiate the requested type variable.

We will now delve into the details of the two functions in order to explain how they analyze the two subtyping derivations.

Theconstraint-to-slicear g function

Theconstraint-to-slicear g function relies on the fact that the type of the argument, S, is

inferred through a regular type inference judgment and can be directly explained with a Type- Focus-basedSLICESalgorithm.

Given the type selectionΘirepresenting the individual type constraint, the TypeFocus-based analysis can explain the source of the type constraint. This implies that the result will also explain the origin of the complete type variable instantiation. The SLICES(([?/

a] S,Γ w E : S), Θi) application would reflect such a correct semantics but it would also ignore the need for a more precise analysis, where we want to find the origin of only the part of the inferred type variable instantiation.

Explaining the source of only the fragment of the type variable instantiation

Theconstraint-to-slicear g function triggers the analysis with anormalize(Θi ::: Θa, S,) TypeFocus. To illustrate the need for the normalization we consider two possible values ofΘa, representing the partial type selection on the type variable instantiation:

• Case Θa == [ ] :

normalize(Θi ::: [ ], S,) =

normalize(Θi, S,) = (by definition of the application of the [ ] TypeFocus)

Θi (by Lemma 3.9 and the definition ofnormalize)

• Case Θa!= [ ] :

normalize(Θi ::: Θa, S,) =

normalize(Θa, S,) (by Lemma 3.9 andΘi(S)=inlS) Θa’ (for someΘa’such thatΘa’, WFS)

The first case illustrates the scenario when the TypeFocus provided to theconstraint-to-slice function is structurally equivalent to the identity type selection. The composition is equiva- lent to theΘiTypeFocus, and is well-formed with respect to the type of the argument. This in turn means that it satisfies the pre-condition of theSLICES function and can be used to analyze the inferred type of the argument.

The second case illustrates the scenario when the TypeFocus provided to the 94

3.7. On understanding the type variable instantiation

constraint-to-slicefunction will extract some part of the type variable instantiation. Since the type selectionΘadoes not guarantee the well-formedness with respect to the type of the argument, we have to apply thenormalizefunction to it.

Example: Representing partial type variable instantiations

To illustrate the challenges of explaining type variable instantiations through their type con- straints, we consider an example of the { a }-constraint set inferred from the type of the ar- gument, S, and type of the formal parameter of the function, S, in the constraint generation judgment:

a(I nt→ ) → ((Int → (Int → Int)) → Int) <: a → (a → Int) ⇒

{<:a<:I nt→ (Int → Int)}

The inferred { a }-constraint set had to calculate the greatest lower bound between the two upper bounds: {a <:I nt → }and{a <:I nt → (Int → Int)}. Using the inferred type constraints, we let the inferred type substitution beσ = [a ⇒ Int → (Int → Int)], and for simplicity assume that the target type is part of the instantiated type variable a.

The type selections inferred for the upper bound of the type variable a are then: a, -g en (I nt→ ) → ((Int → (Int → Int)) → Int) <:a→ (a → Int) 

[φfun-param], [φfun-res,φfun-param]  We consider two potential cases of the target type Tt ar g et:

• ForΘa= [ ], Tt ar g et= Θa(σa) = Θa( I nt→ (Int → Int) ) =inlI nt→ (Int → Int):

The target type refers to the complete type variable instantiation.

Locating the source of the target type Tt ar g et resolves to understanding the source of

its two type constraints represented by the [φfun-param] and [φfun-res,φfun-param] type selection. The two values can guide the TypeFocus-base analysis of the argument of type S, which was part of the subtyping derivation, because ([φfun-param], WFS) and ([φfun-res,φfun-param], WFS).

• ForΘa= [φ

fun-res,φfun-param], Tt ar g et= Θa(σa) = Θa(I nt→ (Int → Int )) =inlI nt :

The target type refers to a part of the type variable instantiation.

Locating the source of the target type Tt ar g etresolves to understanding the source of its

two type constraints represented by the ([φfun-param] :::Θa) and ([φfun-res,φfun-param] ::: Θa) type selection. The straightforward composition comes at a cost of not necessarily being safe with respect to the inferred type of the argument. For our particular subcase we notice that ([φfun-param] ::: Θa, WFS) and ([φfun-res,φfun-param] ::: Θa, WFS), meaning that the former TypeFocus composition cannot guide the TypeFocus-based analysis.

Chapter 3. Guided-analysis for type derivation trees

The comparison shows the need for precision, meaning that we want to debug parts of the type variable instantiations, and completeness, meaning that we want to be able to debug the origin of the involved type constraints. The definition of theconstraint-to-slicefunction (Figure 3.23), expresses the former through the TypeFocus composition, while the normaliza- tion ensures that the TypeFocus-based analysis still applies, without any loss in its precision.

Theconstraint-to-sliceptfunction

Theconstraint-to-sliceptfunction explains the source of the part of the prototype used in

the subtyping derivations. It uses a similar methodology as in theconstraint-to-slicear g

function, except that it cannot trigger the TypeFocus-based analysis. Rather, we explain the source of the prototype directly, with the appropriately constructed type selection, by return- ing the Prototype Typing Slice.

Final remarks

The algorithm realized by theconstraint-to-slicefunction highlights the advantages of separating the TypeFocus-based analysis and its related Typing Slices; by considering the in- dividual type constraints and their source we can delegate their analysis to the previously de- fined TypeFocus-based algorithms. Theconstraint-to-slicefunction is generic, in a sense that it is parametrized by the type variable and variance information, and can be applied to any inference judgment where the last type inference rule used was(app). The separation of the analysis of the lower and upper type bounds of the type variable is crucial for explaining different specifications of the minimal substitution that can be used to infer the type of the variable.

In document Decrypting Local Type Inference (Page 106-110)