Without these annotations, Lean will timeout when trying to synthesize
the type class instance `decidable_eq uint32`. The type class resolution
problem will produce the unification problem:
```
decidable (@eq uint32 a b) =?= decidable (@eq usize ?x ?y)
```
which Lean tries to solve by assigning `?x := a`.
During the assignment, the types of `?x` and `a` are unified with "full
force". Thus, we get the constraint
```
usize_sz =?= uint32_sz
```
which will take forever to be solved when peforming the computation in
unary arithmetic.
Remark: this commit also makes sure that `type_context` will not unfold
irreducible definitions when trying to unify/match the types.
The new test `type_class_performance1.lean` exposes the problem fixed
by this commit.
The tactic mk_dec_eq_instance constructs a function using the brec_on
recursor. The compiler generates horrible code for this kind of
definition. It creates a closure for each recursive call.
Moreover, `brec_on` accumulates all intermediate results.
To generate efficient code, we need to generate a collection of
recursive equations, and then invoke the equation compiler.
cc @kha
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.
The tactic_state object will contain a name_generator for creating fresh
names. `tactic_state.mk_empty` is bad because it does not have sufficient
information to create this name_generator.
Moreover `tactic_state.mk_empty` was only being used to convert
`tactic A` into a `parser A`.
We implement this primitive now in C++. In C++, we will be able
to use the parser name generator to initialize a fresh `tactic_state`.
The tactic `mk_fresh_name` is used to create internal unique ids.
We should not use them to create (temporary) user facing
names. Reasons:
1- They are "cryptic".
2- They are not very stable. Minor changes in Lean may change the
value returned and may break proofs that rely on these fresh names.
We also document the problem to make sure we don't spend time again
trying to understand the workaround. This is an instance of a bigger
problem that should be addressed later.
- An new simp attribute may depend on other existing attributes
- Add `[norm]` simp attribute. It is an extension of the default `[simp]` attribute.
It should be used to add extra rules for normalizing goals.
These extra rules are used to produce normal forms and/or reduce the
number of constants used in a goal. Here is an example coming from a
discussion with @kha. When working with monads, we may want to
eliminate `<$>` by using the lemma `f <$> x = x >>= pure ∘ f`.
This lemma is in the `[norm]` simp set, but it is not in `[simp]`