Skip to content

The unification algorithm

Tomer Libal edited this page Apr 24, 2017 · 4 revisions

Documentation of the Unification Algorithm

General Description

The algorithm is defined in the file typechecker/FStar.TypeChecker.Rel.fs

During type checking a guard containing all constraints is being built. When the guard is to be discharged, one calls discharge_guard. This method first tries to apply unification and if SMT is allowed, it then sends the updated obligation to SMT.

Before we try to apply unification, we translate the guard into a list of unification constraints (working list) in wl_of_guard. The unification problem might allow deferred problems or not (the working list defer_ok switch).

Then we can call the algorithm on the problem by recursing on the problems in the list.

Problems can be either computation constraints or typing constraints

Typing constraints

In case deferring constraints is not allowed and the problem is not rigid-rigid or flex-flex, we try one of solve_flex_rigid_join and solve_rigid_flex_meet. Otherwise, we apply the main solving function solve_t'.

Unification Cases (solve_t' in Rel, lines 1531 - 2231)

Unification applies different rules according to the two types we try to unify. In this section we describe the different possible cases.

Identity

Checked first.

In case both sides are syntactically identical (using BU.physical_equality), we remove this problem and continue

From some reason, we check it twice! Remove one case.

Rigid-rigid cases

This cases are dealt with first.

Comparing two universes

We call solve_one_universe_eq

Arrows

Abstractions

Refinements

Flex-rigid cases

In these cases, we have a variable (or an application with a variable head - HO variable) on one side and a term on the other.

Flex-rigid cases are the most interesting ones. In FO, patterns and FCU, we just replace the variable with a version of the term on the other side.

In the other cases, a non-determinism exists in the problem since we might be able to unify the problem with two different substitutions. The imitate one tries to replace the variable with a term whose head is the same as the head of the other term (which is either a constant of a bvar). The project case tries to project one of the arguments into head position.

Equalities

This is the standard case where we compare them syntactically. We apply solve_t_flex_rigid.

Simple sub-typing

Covers when we have a variable on one side and a universe or an arrow type on the other. According to the comments:

this case is so common, that even though we could delay, it is almost always ok to solve it immediately as an equality besides, in the case of arrows, if we delay it, the arity of various terms built by the unifier goes awry so, don't delay!

These problems are treated as syntactical equality

General sub-typing

If we can defer these problems, we do so. Otherwise,

Flex-flex cases

Cases where we have variables on both sides. They have most general unifiers in patterns and FCU but might have inifinite minimal complete unifiers set otherwise.

Therefore, first-order, patterns and FCU should be applied eagerly, the rest should be deferred.

We call the flex_flex function

Clone this wiki locally