Most efficient hash functions use uint32/uint64 and produce values
that do not fit in out small nat representation. Thus, GMP big numbers
would have to be created.
Before this commit, given `x n : nat` the expression
```
to_bool (n <= x)
```
where `n` is a numeral <= 1024 was being elaborated as
```
@decidable.to_bool (@has_le.le.{0} nat nat.has_le n x) (nat.decidable_lt n' x)
```
where `n'` denotes the numeral `n-1`
Example:
```
to_bool (800 <= x)
```
was elaborated as
```
@decidable.to_bool (@has_le.le.{0} nat nat.has_le 800 x) (nat.decidable_lt 799 x)
```
Reason: `nat.lt` and `nat.le` were reducible. The module `type_context`
has support for solving "offset constraints" for small numerals.
These constraints include:
- `succ ?x =?= n` ===> `?x := n - 1`
For elaborating `to_bool (800 <= x)`, we need to synthesize
```
decidable (@has_le.le.{0} nat nat.has_le 800 x)
```
using type class resolution.
The instance `nat.decidable_lt` is tried before `nat.decidable_le`. For
this instance, we need to solve the unification problem.
```
decidable (@has_lt.lt.{0} nat nat.has_lt ?n ?x) =?= decidable (@has_le.le.{0} nat nat.has_le 800 x)
```
which reduces to:
```
nat.less_than_or_equal (succ ?n) ?x =?= nat.less_than_or_equal 800 x
```
because `nat.le` and `nat.lt` are marked as `[reducible]`.
This constraint reduces to
```
succ ?n =?= 800
```
which is solved using the offset constraint support as
```
?n := 799
```
The kernel does not have support for offset constraints, and may take
a considerable amount of time to check that `succ 799` is definitionally
equal to `800`. This is particularly expensive when trust level 0 is
used.
It was taking almost 1 minute to execute the leanchecker test before
this commit because we add the new predicates for checking which
characters can be used in a Lean identifier.
This commit fixes the problem by removing the annotation `[reducible]`
from `nat.lt` and `nat.le`. This performance issue may be triggered
by any reducible instance that may create offset constraints during
type class resolution.
cc @kha
We use the same approach used to define rbtree:
1- Structure with minimal number of invariants, AND
2- well_formed inductive predicate
We can use the well_formed predicate to prove auxiliary invariants later.
Example: the keys stored in every bucket have the correct hash code.
This implementation does not depend on the tactic framework,
and it is not a mess like the one in mathlib.
All theorems are proved without using the tactic framework.
Thus, we can define `fin/uint32/uint64` types and their operations
before we define the tactic framework.
With the current elaboration scheme, out_params and coercions do not mix well,
as evidenced by the following example by @digama:
```
variables {α : Type*} [group α]
def gpow : α → ℤ → α := sorry
instance group.has_pow : has_pow α ℤ := ⟨gpow⟩
example (a : α) : a ^ 0 = 1 := sorry -- failed to synth ⊢ has_pow α ℕ
example (a : α) : a ^ (0:ℕ) = 1 := sorry -- ok, coerces
example (a : α) : a ^ (0:ℤ) = 1 := sorry -- ok
```
The issue is that
* we first try to solve `has_pow ?α ?β`, which is postponed
* then infer `?α = nat` from `a`
* then at some point call `elaborator::synthesize()` and default `β` to `nat`
* then try to solve `has_pow nat nat`, which fails at `int =?= nat`
for ordered_cancel_comm_monoid. The change to partial_order, with a derived lt relation, makes the lt axioms of ordered groups derivable with no additional assumptions.
To make the equation compiler more convenient to use, we will add a
couple of preprocessing steps.
This commit adds the first one of them. In this step, we use
type inference to refine pattern variables, and we relax the
restrictions on inaccessible annotations.
We will also add a preprocessing step that implements the "complete
transition" step before we execute the elim_match step.
@digama0 I moved bitvec back to the main repo, and many nat lemmas.
I want these lemmas here for now. I will need some of them for future
decision procedures.