• No results found

Conclusions

In document Decrypting Local Type Inference (Page 125-131)

The Type Signature Typing Slice explains that the target type⊥ has been inferred as a result of lack of type constraints in the function application with elided type arguments. The identity of the type variable that is instantiated to the⊥ type can trivially be recov- ered using the included TypeFocus value: given ( ?, Γ wF : ∀a.S → T ) for some S and T ,Θ(T ) =inlx and x∈ a. Lack of type constraints only indirectly corresponds to the function application program location, therefore a more elaborate explanation of the target type would have to be put in place.

• Case νTSIG, (P,Γ wF(E):σC1,C2,TT P), Θ



(in theSLICESTVAR-function): The case is analogous to theslicesTVARAux+function, except for the inferred type vari- able instantiation,.

The Type Signature Typing Slice represents a final step in the analysis of the source of the target type. This means that any type debugging mechanism that implements the TypeFocus- based analysis has to provide a detailed description for every kind of Type Signature Typing Slice, e.g., explaining the link of Typing Slices, their typing judgments and TypeFocusvalue with the source code. As we have shown in the above cases, the included TypeFocus value is sufficient to extract fragments of the explicit type annotations that determine the source of the target type. We also notice that while the number of possible Type Signature Typing Slices is not small, it is tractable and can be trivially defined for any implementation of our type debugging technique.

3.9 Conclusions

We have presented a new approach to understanding the decisions of Local Type Inference, and its variants. We assume the existence of a type derivation tree representing the type checking of the program and provide means to navigate its decisions in a controlled way. De- pending on which type element of the inferred type of the term we want to explain, there are potentially many different combinations of the nodes of the type derivation tree that intro- duce the type for the first time. We provide a systematic and a deterministic way of stepping through the adjacent nodes of the type derivation tree based on a concept of type selection. While simple, the type selection was shown to be sufficient to direct the analysis of for exam- ple non-trivial type variable instantiations that involve the analysis of subtype checking as well.

The formal approach illustrates how the analysis of some selected fragment of the inferred type of the term can be continued among the different type checking decisions that can influ- ence it. In other words the inputs and outputs of the algorithm and the specialized functions always explain the same initial type selection that triggered the analysis in the first place. As part of the analysis of the initial inference judgment, each of the explored nodes of the type derivation is associated with a unique TypeFocus type selection. This in turn means that the

Chapter 3. Guided-analysis for type derivation trees

final nodes of the TypeFocus-based analysis remain loosely connected with the initial infer- ence judgment, and its type selection, without maintaining an expensive and complex data structure on top of the type derivation tree.

Apart from being able to separate the analysis of different kinds of the type checking deci- sions, the approach mimics the mechanism of local type inference; the local type inference approximates types and propagates the type information in multiple steps, between the ad- jacent nodes. Similarly, the exploration of the nodes of the type derivation tree is based on the type selection that is constructed only from the previously visited, adjacent nodes.

Chapter 4

Foundations of type mismatch errors

The core TypeFocus-based algorithm (Section 3.5.3) analyzes typing decisions of type deriva- tion trees. The algorithm is defined for type derivation trees, or their fragments, that are derivable, i.e., no errors were encountered during the application of type inference rules. In this section we show that the non-derivable parts of type derivation trees, i.e., the branch of the type derivation that failed to infer the type of the term, can be reduced to a TypeFocus value and we can use it to trigger the TypeFocus-based analysis techniques from the previous chapter. Indirectly, the translation also shows how to find the initial inputs for the TypeFocus- based analysis functions for any type mismatch error.

(var) ?,  wCons: (app) (type-mismatch) (var) (app) (app) ...,  wf (app) w Typechecking application of

Typechecking function argumentfun(x,y) Cons(x + 1,y)

foldRight(xs)(Nil())(f): ?,  wfoldRight(xs): ?,  ((Int,b)b)b <:   ?  C6 List[]<: b  C5 foldRight(xs)(Nil())(f) wNil(): {a}List[a]? [?/b]b,  wNil: a.()List[a]? ?,  List[a] <:   ?  C4 1 = , x: Int, y: List[]

a.((a, List[a]) List[a]) (app) [?/a]a, 1 w(x+1): Int  ? w

(var) [?/a]List[a], 1 List[]  List[?] List[] <:   List[a]  C3 Int <: a  C1 List[] <: List[a]  C2 b.(b((Int,b)b)b) wfoldRight(xs)(Nil())(f): ?,  1 1 2 2 3 3 2 2 2 wfoldRight(xs)(Nil()): {bList[]}((Int,b)b)b? ?, 

Cons(x+1, y): {aInt}List[a]  List[] w

List[], , x: Int, y: List[] (abs)

...,  wf

wfun (x,y) Cons(x + 1,y): (Int, List[])List[], 

Figure 4.1: Fragment of a type derivation tree for the applicationfoldRight(xs)(Nil())( f ), where xs=Cons(1,Nil()) and f =fun(x,y)Cons(x + 1,y). This section provides the analysis and the translation of the highlighted elements of the tree.

Chapter 4. Foundations of type mismatch errors

We show in this section that the problem of explaining a type mismatch error in a type deriva- tion tree constructed using the rules of Colored Local Type Inference consists of three parts. For clarity, we illustrate each of them on the familiarfoldRightfunction application in Figure 4.1:

• We translate the conflicting types that failed the subtyping relation into TypeFocus in- stances (Section 4.2, the highlighted box 1 in Figure 4.1).

• We translate the non-derivable parts of type derivation trees into TypeFocus instances (Section 4.1, the highlighted box 2 in Figure 4.1). The non-derivable tree refers to a fragment of the complete type derivation tree that failed to infer the type of the term but nevertheless retained the structure of the derivation, including the kind of type inference rules applied and their prototype elements.

• We locate the error-free type inference judgment which introduced the conflicting ex- pected type, or part of it, for the first time (Section 4.1, the highlighted box 3 in Figure 4.1). The located inference judgment and the reconstructed TypeFocus value allows us to trigger a regular TypeFocus-based analysis algorithm in search of the source of the expected type.

The type inference rules of Colored Local Type Inference precisely define typing decisions where a type mismatch error can occur. The errors materialize due to a failed adaptation attempt between the synthesized type of the term and the inherited expected type. In Section 4.3 we define a complete set of steps necessary to explain the source of the two types that participate in a type mismatch.

We conclude with a complete example of a non-trivial type mismatch conflict that is ex- plained formally using only our TypeFocus-based approach (Section 4.4).

4.1 Inference of a Propagation Root

We recall that the conflicting expected type, in a failed adaptation process, is propagated in the non-derivable fragments of type derivation trees in an identical way as for the error-free type derivation trees, i.e., it is driven by the prototype component in the type inference rules. The observation implies that the propagation of the conflicting prototype is just a special case of the analysis of the propagation of the expected type that we formalized in Section 3.6. TheProprules (Figure 3.18 in Section 3.6.1), that realize the search for the Propagation Root, use the prototype information in order to infer the equivalent TypeFocus values. Because none of the rules utilize the information about the inferred types of terms, and are only- driven by the kind of the type inference rule used, the search for the Propagation Root in a non-derivable inference judgment is just a special case of thep prototype propagation 114

4.1. Inference of a Propagation Root

judgment. That is why we define a propagation judgment for the erroneous type derivation trees in an almost identical way to its derivable counterpart from Section 3.6.1:

(Θip

e (PiiwEi: Ti)〈(PoowEo: To),Θo〉)

Thepe propagation judgment takes a TypeFocus instance (Θi) and a failed inference judg-

ment ((Pi, Γi w Ei : Ti)), such that (Θi, WFPi) and (Θi(Pi)

tpe = ?). The propagation judgment infers a tuple consisting of the inference judgment (PoowEo: To) and a Type- FocusΘo. The returned inference judgment represents the Propagation Root of Pi and the

returned TypeFocus value reduces the Prototype Propagation Path of Pi to a type selection, such thatΘo(Pf)tpe == Θi(Pi)tpe. The lack of the inferred type information is represented through a grayed-out part in the propagation judgment and can be simply ignored.

For easier understanding, thepe propagation judgment is realized in the algorithmic fashion

using thePrototypeBacktrackErrorfunction in Figure 4.2, similarly to its error-free counter- part (Figure 3.19). ThePrototypeBacktrackErrorfunction differs in two aspects:

• The inferred type component is missing.

• The cases for the (abst p,), (rec), (appt p,⊥), (app) rules and a subcase of the (rec)

rule are omitted because they propagate the top type. From the definition of the operation,∀T. (T  ) = , therefore type  will never lead to a type mismatch error.

The algorithm pattern matches on the kind of the last type inference rule used in the parent of the input inference judgment. Pattern matching either backtracks through the nodes of the type derivation tree on the prototype propagation in a recursive manner (the type infer- ence rules (abs), (abst p) and (rec)), or returns the Propagation Root when the prototype value

is freshly introduced from one of its typing decisions (the type inference rules (app), (appt p)

and (sel)). The individual recursive invocations reduce the prototype propagation to the ap- propriate type selections, based on the kind of the type inference rule. The grayed-out type elements indicate the failure to infer the type of the term.

Using the above argument, we notice that all properties of theppropagation judgment for the error-free type derivation trees apply directly to the pe propagation judgment for the

erroneous type derivation trees. We refer the reader to Section 3.6.1 for details.

Analysis of the Propagation Root (for non-derivable inference judgments)

ThePrototypeBacktrackErrorfunction from Figure 4.2 identifies three type inference rules as a potential Propagation Root for a non-? in a partially derivable type derivation tree. Sim- ilarly as in their error-free counterparts, the typing decisions that infer the fresh prototype, Pf, in the Propagation root may differ significantly from rule to rule.

Chapter 4. Foundations of type mismatch errors

FUNCTIONPrototypeBacktrackError(Θi, (Pi,ΓiwEi: Ti))= ((PiiwEi: Ti))↓ = wparent

MATCH (wparent)OF

CASE(abs) : PrototypeBacktrackError(φfun-res::Θi,wparent) CASE(abst p) : PrototypeBacktrackError(φfun-res::Θi,wparent) CASE(rec) :

(wparent) == (rec) {x1: P1, ..., xm: Pm},Γ w{x1= F1, ..., xn= Fn}: {x1: T1, ..., xm: Tm} (PiiwEi: Ti) == (Pk,Γ wFk: Tk) for 1≤ k ≤ m PrototypeBacktrackError(φselxk::Θi,wparent)

CASE(app) :  w parent,Θ i CASE(appt p) :  w parent,Θ i CASE(sel) :  w parent,Θ i

Figure 4.2: The algorithmic definition of the Θi ep (Pi, Γi w Ei : Ti)  〈(Po,ΓowEo: To),Θo〉 prototype propagation judgment for erroneous type derivation trees.

The search for the source of the fresh prototype introduced in a non-derivable inference judg- ment is realized by theSLICESPTERRORpartial function. Similarly as in the case of its error- free counterpart ( theslicesPtRootfunction in Section 3.6.1), theSLICESPTERRORfunction is of type ( (P, Γ wE: T),Θ ) → ν3; the function takes the inference judgment representing

the inferred Propagation Root, and the TypeFocus that expresses a well-formed type selec- tion on a freshly introduced prototype Pf, where Pf belongs to the premise of the provided Propagation Root judgment, and returns the source of theΘ(Pf)tpeprototype in the form of Typing Slices. The grayed-out part of the inferred types indicates that the function accepts judgments that failed to infer the type of the term.

TheSLICESPTERRORfunction is realized through a set of type inference rule-specialized par- tial functions in Figure 4.3. Each of the possible type inference rules is considered separately, as indicated through the rule subscript in the function nameSLICESPTERRORrule. For clarity,

we highlight the position of the fresh prototype Pf in Figure 4.3 with gray boxes. The defini- tion of the algorithm assumes thatΘ,fv(Pf)WFPf, where the Pf prototype is type inference rule-specific.

TheSLICESPTERRORandslicesPtRootfunctions differ only in the interpretation of the de- cisions of the(sel)type inference rule that infers the type of record member selection. Un- like the error-free counterpart, we cannot report the intermediate Prototype Typing Slice to represent the source of the conflicting prototype because Typing Slices require a derivable in- ference judgment. Instead, the function inlines the analysis of the implicit Prototype Typing Slice that is reported in theslicesPtRootfunction.

In document Decrypting Local Type Inference (Page 125-131)