This PR fixes a bug where the monad lift coercion elaborator would partially unify expressions even if they were not monads. This could be taken advantage of to propagate information that could help elaboration make progress, for example the first `change` worked because the monad lift coercion elaborator was unifying `@Eq _ _` with `@Eq (Nat × Nat) p`: ```lean example (p : Nat × Nat) : p = p := by change _ = ⟨_, _⟩ -- used to work (yielding `p = (p.fst, p.snd)`), now it doesn't change ⟨_, _⟩ = _ -- never worked ``` As such, this is a breaking change; you may need to adjust expressions to include additional implicit arguments.
148 lines
2.3 KiB
Text
148 lines
2.3 KiB
Text
/-!
|
|
Tests that definitions by well-founded recursion are irreducible.
|
|
-/
|
|
|
|
set_option pp.mvars false
|
|
|
|
def foo : Nat → Nat
|
|
| 0 => 0
|
|
| n+1 => foo n
|
|
termination_by n => n
|
|
|
|
/--
|
|
error: type mismatch
|
|
rfl
|
|
has type
|
|
?_ = ?_ : Prop
|
|
but is expected to have type
|
|
foo 0 = 0 : Prop
|
|
-/
|
|
#guard_msgs in
|
|
example : foo 0 = 0 := rfl
|
|
|
|
/--
|
|
error: type mismatch
|
|
rfl
|
|
has type
|
|
?_ = ?_ : Prop
|
|
but is expected to have type
|
|
foo (n + 1) = foo n : Prop
|
|
-/
|
|
#guard_msgs in
|
|
example : foo (n+1) = foo n := rfl
|
|
|
|
-- also for closed terms
|
|
/--
|
|
error: tactic 'rfl' failed, the left-hand side
|
|
foo 0
|
|
is not definitionally equal to the right-hand side
|
|
0
|
|
⊢ foo 0 = 0
|
|
-/
|
|
#guard_msgs in
|
|
example : foo 0 = 0 := by rfl
|
|
|
|
-- It only works on closed terms:
|
|
/--
|
|
error: tactic 'rfl' failed, the left-hand side
|
|
foo (n + 1)
|
|
is not definitionally equal to the right-hand side
|
|
foo n
|
|
n : Nat
|
|
⊢ foo (n + 1) = foo n
|
|
-/
|
|
#guard_msgs in
|
|
example : foo (n+1) = foo n := by rfl
|
|
|
|
section Unsealed
|
|
|
|
unseal foo
|
|
|
|
example : foo 0 = 0 := rfl
|
|
example : foo 0 = 0 := by rfl
|
|
|
|
example : foo (n+1) = foo n := rfl
|
|
example : foo (n+1) = foo n := by rfl
|
|
|
|
end Unsealed
|
|
|
|
--should be sealed again here
|
|
|
|
/--
|
|
error: type mismatch
|
|
rfl
|
|
has type
|
|
?_ = ?_ : Prop
|
|
but is expected to have type
|
|
foo 0 = 0 : Prop
|
|
-/
|
|
#guard_msgs in
|
|
example : foo 0 = 0 := rfl
|
|
|
|
|
|
def bar : Nat → Nat
|
|
| 0 => 0
|
|
| n+1 => bar n
|
|
termination_by n => n
|
|
|
|
-- Once unsealed, the full internals are visible. This allows one to prove, for example
|
|
|
|
/--
|
|
error: type mismatch
|
|
rfl
|
|
has type
|
|
?_ = ?_ : Prop
|
|
but is expected to have type
|
|
foo = bar : Prop
|
|
-/
|
|
#guard_msgs in
|
|
example : foo = bar := rfl
|
|
|
|
|
|
unseal foo bar in
|
|
example : foo = bar := rfl
|
|
|
|
|
|
-- Attributes on the definition take precedence
|
|
@[semireducible] def baz : Nat → Nat
|
|
| 0 => 0
|
|
| n+1 => baz n
|
|
termination_by n => n
|
|
|
|
example : baz 0 = 0 := rfl
|
|
|
|
seal baz in
|
|
/--
|
|
error: type mismatch
|
|
rfl
|
|
has type
|
|
?_ = ?_ : Prop
|
|
but is expected to have type
|
|
baz 0 = 0 : Prop
|
|
-/
|
|
#guard_msgs in
|
|
example : baz 0 = 0 := rfl
|
|
|
|
example : baz 0 = 0 := rfl
|
|
|
|
@[reducible] def quux : Nat → Nat
|
|
| 0 => 0
|
|
| n+1 => quux n
|
|
termination_by n => n
|
|
|
|
example : quux 0 = 0 := rfl
|
|
|
|
set_option allowUnsafeReducibility true in
|
|
seal quux in
|
|
/--
|
|
error: type mismatch
|
|
rfl
|
|
has type
|
|
?_ = ?_ : Prop
|
|
but is expected to have type
|
|
quux 0 = 0 : Prop
|
|
-/
|
|
#guard_msgs in
|
|
example : quux 0 = 0 := rfl
|
|
|
|
example : quux 0 = 0 := rfl
|