lean4-htt/tests/lean/run/unify_approx_bug.lean
Leonardo de Moura 28b8020995 fix(library/type_context): bug in the unifier
One of the approximations used was generating type incorrect terms.
2018-01-30 12:48:48 -08:00

275 lines
7.1 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

open tactic
/-
Given a metavariable ?m with local context
(α : Type) (a : α)
then, the following unification problem should fail
?m α =?= ((λ (α : Type) (a : α), α) α a)
type_context will try the type incorrect assignment
?m := λ α', ((λ (α : Type) (a : α), α) α' a)
-/
def ex1 (α : Type) (a : α) : Type → Type :=
by do
fail_if_success
(do
mvar1 ← mk_meta_var `(Type → Type),
alpha ← to_expr ```(α),
t ← to_expr ```((λ (α : Type) (a : α), α) α a),
unify (mvar1 alpha) t semireducible tt, -- should fail
exact mvar1),
intros, assumption
/-
Given metavariable ?m_1 and ?m_2 with local context
(α : Type) (a : α)
then, the following unification constrains should be solved
?m_1 α =?= id ?m_2
?m_2 =?= α
The first constraint is solved using first-order unification
because we cannot guarantee that the solution will be type correct
for every term we may assign to `?m_2`
?m_1 := λ α', id ?m_2[α := α']
So, we get `?m_2 := α`.
Remark: see option c) at workaround A2 described at type_context::process_assignment
-/
def ex2 (α : Type) (a : α) : Type → Type :=
by do
mvar1 ← mk_meta_var `(Type → Type),
mvar2 ← mk_meta_var `(Type),
alpha ← to_expr ```(α),
t ← to_expr ```(id %%mvar2),
unify (mvar1 alpha) t semireducible tt, -- first-order unification is used here
unify mvar2 alpha,
exact mvar1
/-
Given metavariable ?m_1 and ?m_2 with local context
(α : Type) (a : α)
then, the following unification constrains should be solved
?m_1 α =?= id ?m_2
?m_2 =?= ((λ (α : Type) (a : α), α) α a)
Again, similarly to the previous example, we use
first-order unification to process the first constraint,
and we get `?m_2 := α`. The second constraint
is satisfied because `((λ (α : Type) (a : α), α) α a)`
is definitionally equal to `α`.
-/
def ex3 (α : Type) (a : α) : Type → Type :=
by do
mvar1 ← mk_meta_var `(Type → Type),
mvar2 ← mk_meta_var `(Type),
alpha ← to_expr ```(α),
t ← to_expr ```(id %%mvar2),
unify (mvar1 alpha) t semireducible tt, -- should create an auxiliary mvar and assign it to mvar2
t ← to_expr ```((λ (α : Type) (a : α), α) α a),
unify mvar2 t semireducible tt, -- should fail `a` is not in the scope
exact mvar1
def f (α : Type) (a : α) := α
constant f' (α : Type) (a : α) : Type
/-
Given a metavariable ?m with local context
(α : Type) (a : α)
then, the following unification problem should fail
?m α =?= f α a
type_context will try the type incorrect assignment
?m := λ α', f α' a
-/
def ex4 (α : Type) (a : α) : Type → Type :=
by do
fail_if_success
(do
mvar1 ← mk_meta_var `(Type → Type),
alpha ← to_expr ```(α),
t ← to_expr ```(f α a),
unify (mvar1 alpha) t semireducible tt, -- should fail
exact mvar1),
intros, assumption
/-
Given a metavariable ?m with local context
(α : Type) (a : α)
then, the following unification problem should work
?m α a =?= f α a
type_context assigns
?m := λ α' a', f α' a'
-/
def ex5 (α : Type) (a : α) : Π A : Type, A → Type :=
by do
mvar1 ← mk_meta_var `(Π A : Type, A → Type),
alpha ← to_expr ```(α),
a ← to_expr ```(a),
t ← to_expr ```(f α a),
unify (mvar1 alpha a) t semireducible tt, -- should work
exact mvar1
def ex5b (α : Type) (a : α) : Π A : Type, A → Type :=
by do
mvar1 ← mk_meta_var `(Π A : Type, A → Type),
alpha ← to_expr ```(α),
a ← to_expr ```(a),
t ← to_expr ```(f' α a),
unify (mvar1 alpha a) t semireducible tt, -- should work
exact mvar1
/-
Given metavariable ?m_1 and ?m_2 with local context
(α : Type) (a : α)
then, the following unification constrains should be solved
?m_1 α =?= id ?m_2
?m_2 =?= f α a
The first constraint is solved using first-order unification.
See option c) at workaround A2 described at type_context::process_assignment.
Then, we get `?m_2 := α`. The second constraint succeeds
because `f α a` is definitionally equal to `α`.
-/
def ex6 (α : Type) (a : α) : Type → Type :=
by do mvar1 ← mk_meta_var `(Type → Type),
mvar2 ← mk_meta_var `(Type),
alpha ← to_expr ```(α),
t ← to_expr ```(id %%mvar2),
unify (mvar1 alpha) t semireducible tt,
t ← to_expr ```(f α a),
unify mvar2 t semireducible tt,
exact mvar1
/-
Given metavariable ?m_1 and ?m_2 with local context
(α : Type) (a : α)
then, the following unification constrains should be solved
?m_1 α =?= id ?m_2
?m_2 =?= f' α a
Similar to previous example, but this one fails because
`f' α a` is not definitionally equal to `α`.
-/
def ex6b (α : Type) (a : α) : Type → Type :=
by do
fail_if_success
(do mvar1 ← mk_meta_var `(Type → Type),
mvar2 ← mk_meta_var `(Type),
alpha ← to_expr ```(α),
t ← to_expr ```(id %%mvar2),
unify (mvar1 alpha) t semireducible tt,
t ← to_expr ```(f' α a),
unify mvar2 t semireducible tt,
exact mvar1),
intros, assumption
def g (α : Type) (a b : α) := α
/-
Given a metavariable ?m with local context
(α : Type) (a : α)
then, the following unification problem should fail
?m α =?= g α a a
type_context will try the type incorrect assignment
?m := λ α', g α' a a
-/
def ex7 (α : Type) (a : α) : Type → Type :=
by do
fail_if_success
(do
mvar1 ← mk_meta_var `(Type → Type),
alpha ← to_expr ```(α),
t ← to_expr ```(g α a a),
unify (mvar1 alpha) t semireducible tt, -- should fail
exact mvar1),
intros, assumption
constant C (α : Type) (a : α) : Type
/-
Given a metavariable ?m with local context
(α : Type) (a : α) (x : C α a)
then, the following unification problem should fail
?m α x =?= α
type_context will try the type incorrect assignment
?m := λ (α' : Type) (x' : C α' a), α'
type_context detects the problem when it tries to unify the type of `?m`
with type of (λ (α' : Type) (x' : C α' a), α')
-/
def ex8 (α : Type) (a : α) (x : C α a) : Type :=
by do
fail_if_success
(do
mvar_type ← to_expr ```(C α a → Type),
mvar_type ← to_expr ```(Type → %%mvar_type),
mvar1 ← mk_meta_var mvar_type,
alpha ← to_expr ```(α),
x ← to_expr ```(x),
unify (mvar1 alpha x) alpha semireducible tt, -- should fail
exact (mvar1 alpha x)),
assumption
/-
Given a metavariable ?m with local context
(α : Type) (a : α)
then, the following unification problem should work
?m α =?= a
type_context assigns
?m := λ α', a
The point of this example is to make sure
future modifications to type_context do not
prevent us from solving valid problems like this one.
-/
def ex9 (α : Type) (a : α) : Type → α :=
by do
mvar_type ← to_expr ```(Type → α),
mvar1 ← mk_meta_var mvar_type,
alpha ← to_expr ```(α),
t ← to_expr ```(a),
unify (mvar1 alpha) t semireducible tt, -- should work
exact mvar1