Auxiliary elaboration functions: AKA custom elaborators #

The elaborator for binop%, binop_lazy%, and unop% terms.

It works as follows:

1- Expand macros. 2- Convert Syntax object corresponding to the binop% (binop_lazy% and unop%) term into a Tree. The toTree method visits nested binop% (binop_lazy% and unop%) terms and parentheses. 3- Synthesize pending metavariables without applying default instances and using the (mayPostpone := true). 4- Tries to compute a maximal type for the tree computed at step 2. We say a type α is smaller than type β if there is a (nondependent) coercion from α to β. We are currently ignoring the case we may have cycles in the coercion graph. If there are "uncomparable" types α and β in the tree, we skip the next step. We say two types are "uncomparable" if there isn't a coercion between them. Note that two types may be "uncomparable" because some typing information may still be missing. 5- We traverse the tree and inject coercions to the "maximal" type when needed.

Recall that the coercions are expanded eagerly by the elaborator.


a) Given n : Nat and i : Nat, it can successfully elaborate n + i and i + n. Recall that Lean 3 fails on the former.

b) The coercions are inserted in the "leaves" like in Lean 3.

c) There are no coercions "hidden" inside instances, and we can elaborate

axiom Int.add_comm (i j : Int) : i + j = j + i

example (n : Nat) (i : Int) : n + i = i + n := by
  rw [Int.add_comm]

Recall that the rw tactic used to fail because our old binop% elaborator would hide coercions inside of a HAdd instance.


In the new binop% and related elaborators the decision whether a coercion will be inserted or not is made at binop% elaboration time. This was not the case in the old elaborator. For example, an instance, such as HAdd Int ?m ?n, could be created when executing the binop% elaborator, and only resolved much later. We try to minimize this problem by synthesizing pending metavariables at step 3.

For types containing heterogeneous operators (e.g., matrix multiplication), step 4 will fail and we will skip coercion insertion. For example, x : Matrix Real 5 4 and y : Matrix Real 4 8, there is no coercion Matrix Real 5 4 from Matrix Real 4 8 and vice-versa, but x * y is elaborated successfully and has type Matrix Real 5 8.

Elaboration functionf for binrel% and binrel_no_prop% notations. We use the infrastructure for binop% to make sure we propagate information between the left and right hand sides of a binary relation.

Recall that the binrel_no_prop% notation is used for relations such as == which do not support Prop, but we still want to be able to write (5 > 2) == (2 > 1).

Instances For

    If noProp == true and e has type Prop, then coerce it to Bool.

    Instances For