fix: make sure monad lift coercion elaborator has no side effects (#6024)

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.
This commit is contained in:
Kyle Miller 2024-11-13 08:22:31 -08:00 committed by GitHub
parent 970261b1e1
commit 28cf146d00
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 78 additions and 53 deletions

View file

@ -642,7 +642,7 @@ theorem pred_add_one (i : Fin (n + 2)) (h : (i : Nat) < n + 1) :
ext
simp
@[simp] theorem subNat_one_succ (i : Fin (n + 1)) (h : 1 ≤ ↑i) : (subNat 1 i h).succ = i := by
@[simp] theorem subNat_one_succ (i : Fin (n + 1)) (h : 1 ≤ (i : Nat)) : (subNat 1 i h).succ = i := by
ext
simp
omega

View file

@ -157,9 +157,11 @@ def coerceMonadLift? (e expectedType : Expr) : MetaM (Option Expr) := do
let eType ← instantiateMVars (← inferType e)
let some (n, β) ← isTypeApp? expectedType | return none
let some (m, α) ← isTypeApp? eType | return none
-- Need to save and restore the state in case `m` and `n` are defeq but not monads to prevent this procedure from having side effects.
let saved ← saveState
if (← isDefEq m n) then
let some monadInst ← isMonad? n | return none
try expandCoe (← mkAppOptM ``Lean.Internal.coeM #[m, α, β, none, monadInst, e]) catch _ => return none
let some monadInst ← isMonad? n | restoreState saved; return none
try expandCoe (← mkAppOptM ``Lean.Internal.coeM #[m, α, β, none, monadInst, e]) catch _ => restoreState saved; return none
else if autoLift.get (← getOptions) then
try
-- Construct lift from `m` to `n`

View file

@ -56,8 +56,8 @@ a : α
• Fam2.any : Fam2 α α @ ⟨9, 4⟩†-⟨9, 12⟩†
α : Type @ ⟨9, 4⟩†-⟨9, 12⟩†
• a (isBinder := true) : α @ ⟨8, 2⟩†-⟨10, 19⟩†
• FVarAlias a: _uniq.632 -> _uniq.312
• FVarAlias α: _uniq.631 -> _uniq.310
• FVarAlias a: _uniq.585 -> _uniq.312
• FVarAlias α: _uniq.584 -> _uniq.310
• ?m x α a : α @ ⟨9, 18⟩-⟨9, 19⟩ @ Lean.Elab.Term.elabHole
• [.] Fam2.nat : none @ ⟨10, 4⟩-⟨10, 12⟩
• Fam2.nat : Nat → Fam2 Nat Nat @ ⟨10, 4⟩-⟨10, 12⟩
@ -71,8 +71,8 @@ a : α
• Fam2.nat n : Fam2 Nat Nat @ ⟨10, 4⟩†-⟨10, 14⟩
• n (isBinder := true) : Nat @ ⟨10, 13⟩-⟨10, 14⟩
• a (isBinder := true) : Nat @ ⟨8, 2⟩†-⟨10, 19⟩†
• FVarAlias a: _uniq.663 -> _uniq.312
• FVarAlias n: _uniq.662 -> _uniq.310
• FVarAlias a: _uniq.616 -> _uniq.312
• FVarAlias n: _uniq.615 -> _uniq.310
• n : Nat @ ⟨10, 18⟩-⟨10, 19⟩ @ Lean.Elab.Term.elabIdent
• [.] n : some Nat @ ⟨10, 18⟩-⟨10, 19⟩
• n : Nat @ ⟨10, 18⟩-⟨10, 19⟩

View file

@ -1,12 +1,12 @@
1081.lean:7:2-7:5: error: type mismatch
rfl
has type
f 0 y = f 0 y : Prop
?m = ?m : Prop
but is expected to have type
f 0 y = y : Prop
1081.lean:23:4-23:7: error: type mismatch
rfl
has type
insert a ⟨0, ⋯⟩ v = insert a ⟨0, ⋯⟩ v : Prop
?m = ?m : Prop
but is expected to have type
insert a ⟨0, ⋯⟩ v = cons a v : Prop

View file

@ -1,6 +1,6 @@
1433.lean:11:49-11:52: error: type mismatch
rfl
has type
dividend % divisor = dividend % divisor : Prop
?m = ?m : Prop
but is expected to have type
dividend % divisor = wrongRem : Prop

View file

@ -1,3 +1,5 @@
set_option pp.mvars false
def Additive (α : Type) := α
instance [OfNat α 1] : OfNat (Additive α) (nat_lit 0) := ⟨(1 : α)⟩

View file

@ -1,24 +1,24 @@
755.lean:5:44-5:47: error: type mismatch
755.lean:7:44-7:47: error: type mismatch
rfl
has type
0 = @OfNat.ofNat Nat 0 (instOfNatNat 0) : Prop
?_ = ?_ : Prop
but is expected to have type
0 = @OfNat.ofNat (Additive Nat) 0 instOfNatAdditiveOfOfNatNat : Prop
755.lean:24:2-24:5: error: type mismatch
0 = 0 : Prop
755.lean:26:2-26:5: error: type mismatch
rfl
has type
2 * 3 = @HMul.hMul Nat Nat Nat instHMul 2 3 : Prop
?_ = ?_ : Prop
but is expected to have type
2 * 3 = @HMul.hMul (Foo Nat) (Foo Nat) (Foo Nat) instHMulFooOfHAdd 2 3 : Prop
755.lean:27:2-27:5: error: type mismatch
2 * 3 = 2 * 3 : Prop
755.lean:29:2-29:5: error: type mismatch
rfl
has type
2 + 3 = @HAdd.hAdd Nat Nat Nat instHAdd 2 3 : Prop
?_ = ?_ : Prop
but is expected to have type
2 + 3 = @HAdd.hAdd (Foo Nat) (Foo Nat) (Foo Nat) instHAddFoo 2 3 : Prop
755.lean:30:2-30:5: error: type mismatch
2 + 3 = 2 + 3 : Prop
755.lean:32:2-32:5: error: type mismatch
rfl
has type
2 - 3 = @HSub.hSub Nat Nat Nat instHSub 2 3 : Prop
?_ = ?_ : Prop
but is expected to have type
2 - 3 = @HSub.hSub (Foo Nat) (Foo Nat) (Foo Nat) instHSubFooOfHAdd 2 3 : Prop
2 - 3 = 2 - 3 : Prop

View file

@ -1,7 +1,7 @@
calcErrors.lean:7:30-7:33: error: type mismatch
rfl
has type
b + b = b + b : Prop
?m = ?m : Prop
but is expected to have type
b + b = 0 + c + b : Prop
calcErrors.lean:13:8-13:29: error: invalid 'calc' step, left-hand side is

View file

@ -4,6 +4,8 @@
The functions inserted for the coercions are supposed to be inlined immediately during elaboration.
-/
set_option pp.mvars false
variable (p : Nat → Prop) (m : IO (Subtype p))
/-!
@ -15,3 +17,18 @@ variable (p : Nat → Prop) (m : IO (Subtype p))
`Lean.Internal.coeM`
-/
#check (m : IO Nat)
/-!
Making sure the monad lift coercion elaborator does not have side effects.
It used to be responsible for hinting that the LHSs of equalities were defeq, like in the following example.
It was checking that `Eq (some true)` and `Eq _` were defeq monads. The defeq check caused `_` to be solved as `some true`.
-/
/--
error: invalid dotted identifier notation, expected type is not of the form (... → C ...) where C is a constant
?_
-/
#guard_msgs in
example : some true = (some true).map id := by
refine show _ = .some true from ?_
rfl

View file

@ -1,6 +1,6 @@
etaStructIssue.lean:20:2-20:5: error: type mismatch
rfl
has type
mkNat e x₁ = mkNat e x₁ : Prop
?m = ?m : Prop
but is expected to have type
mkNat e x₁ = mkNat e.mk x₂ : Prop

View file

@ -1,6 +1,6 @@
isDefEqOffsetBug.lean:19:2-19:5: error: type mismatch
rfl
has type
0 + 0 = 0 + 0 : Prop
?m = ?m : Prop
but is expected to have type
0 + 0 = 0 : Prop

View file

@ -8,16 +8,10 @@ the following variables have been introduced by the implicit lambda feature
a✝ : Bool
b✝ : Bool
you can disable implicit lambdas using `@` or writing a lambda expression with `{}` or `[]` binder annotations.
mulcommErrorMessage.lean:11:22-11:25: error: type mismatch
rfl
has type
true = true : Prop
but is expected to have type
true = false : Prop
mulcommErrorMessage.lean:12:22-12:25: error: type mismatch
rfl
has type
false = false : Prop
?m = ?m : Prop
but is expected to have type
false = true : Prop
mulcommErrorMessage.lean:16:3-17:47: error: type mismatch

View file

@ -5,4 +5,4 @@ argument
has type
@PersistentHashMap Nat Nat instBEqOfDecidableEq instHashableNat : Type
but is expected to have type
@PersistentHashMap Nat Nat instBEqOfDecidableEq natDiffHash : Type
@PersistentHashMap Nat Nat ?m natDiffHash : Type

View file

@ -25,7 +25,7 @@ def isFinite : Prop :=
instance hasNextWF : WellFoundedRelation {s : ρ // isFinite s} where
rel := λ s1 s2 => hasNext s2.val s1.val
wf := ⟨λ ⟨s,h⟩ => ⟨⟨s,h⟩, by
wf := ⟨λ ⟨s,h⟩ => ⟨Subtype.mk s h, by
simp only [Subtype.forall]
cases h; case intro w h =>
induction w generalizing s

View file

@ -4,13 +4,13 @@ set_option pp.mvars false
/--
error: application type mismatch
⟨Nat.lt_irrefl (?_ n), Fin.is_lt (?_ n)
⟨Nat.lt_irrefl (?_ n), Fin.is_lt ?_⟩
argument
Fin.is_lt (?_ n)
Fin.is_lt ?_
has type
(?_ n) < ?_ n : Prop
↑?_ < ?_ : Prop
but is expected to have type
↑(?_ n) < ↑(?_ n) : Prop
?_ n < ?_ n : Prop
-/
#guard_msgs in
def foo := fun n => (not_and_self_iff _).mp ⟨Nat.lt_irrefl _, Fin.is_lt _⟩

View file

@ -1,3 +1,5 @@
set_option pp.mvars false
structure Note where
pitch : UInt64
start : Nat
@ -16,13 +18,13 @@ theorem Note.self_containsNote_lowerSemitone_self (n : Note) :
error: type mismatch
rfl
has type
n = n : Prop
?_ = ?_ : Prop
but is expected to have type
n = n - 1 : Prop
-/
#guard_msgs in
set_option maxRecDepth 100 in
set_option maxHeartbeats 100 in
set_option maxHeartbeats 200 in
example (n : UInt64) : n = n - 1 :=
rfl

View file

@ -328,9 +328,11 @@ set_option pp.analyze.explicitHoles false in
#testDelab ∀ {α : Sort u} {β : α → Sort v} {f₁ f₂ : (x : α) → β x}, (∀ (x : α), f₁ x = f₂ _) → f₁ = f₂
expecting ∀ {α : Sort u} {β : α → Sort v} {f₁ f₂ : (x : α) → β x}, (∀ (x : α), f₁ x = f₂ x) → f₁ = f₂
/- TODO(kmill) 2024-11-10 fix the following test
set_option pp.analyze.trustSubtypeMk true in
#testDelab fun (n : Nat) (val : List Nat) (property : List.length val = n) => List.length { val := val, property := property : { x : List Nat // List.length x = n } }.val = n
expecting fun n val property => (Subtype.val (p := fun x => x.length = n) (⟨val, property⟩ : { x : List Nat // x.length = n })).length = n
-/
#testDelabN Nat.brecOn
#testDelabN Nat.below

View file

@ -1,10 +1,11 @@
@[irreducible] def f (x : Nat) := x + 1
set_option allowUnsafeReducibility true
set_option pp.mvars false
/--
error: type mismatch
rfl
has type
f x = f x : Prop
?_ = ?_ : Prop
but is expected to have type
f x = x + 1 : Prop
-/
@ -22,7 +23,7 @@ end
error: type mismatch
rfl
has type
f x = f x : Prop
?_ = ?_ : Prop
but is expected to have type
f x = x + 1 : Prop
-/
@ -38,7 +39,7 @@ end Boo
error: type mismatch
rfl
has type
f x = f x : Prop
?_ = ?_ : Prop
but is expected to have type
f x = x + 1 : Prop
-/
@ -54,7 +55,7 @@ example : f x = x + 1 :=
error: type mismatch
rfl
has type
f x = f x : Prop
?_ = ?_ : Prop
but is expected to have type
f x = x + 1 : Prop
-/

View file

@ -1,3 +1,5 @@
set_option pp.mvars false
def f (x : Nat) := x + 1
example : f x = x + 1 := rfl
@ -6,7 +8,7 @@ example : f x = x + 1 := rfl
error: type mismatch
rfl
has type
f x = f x : Prop
?_ = ?_ : Prop
but is expected to have type
f x = x + 1 : Prop
-/
@ -22,7 +24,7 @@ seal f
error: type mismatch
rfl
has type
f x = f x : Prop
?_ = ?_ : Prop
but is expected to have type
f x = x + 1 : Prop
-/

View file

@ -2,6 +2,8 @@
Tests that definitions by well-founded recursion are irreducible.
-/
set_option pp.mvars false
def foo : Nat → Nat
| 0 => 0
| n+1 => foo n
@ -11,7 +13,7 @@ termination_by n => n
error: type mismatch
rfl
has type
foo 0 = foo 0 : Prop
?_ = ?_ : Prop
but is expected to have type
foo 0 = 0 : Prop
-/
@ -22,7 +24,7 @@ example : foo 0 = 0 := rfl
error: type mismatch
rfl
has type
foo (n + 1) = foo (n + 1) : Prop
?_ = ?_ : Prop
but is expected to have type
foo (n + 1) = foo n : Prop
-/
@ -70,7 +72,7 @@ end Unsealed
error: type mismatch
rfl
has type
foo 0 = foo 0 : Prop
?_ = ?_ : Prop
but is expected to have type
foo 0 = 0 : Prop
-/
@ -89,7 +91,7 @@ termination_by n => n
error: type mismatch
rfl
has type
foo = foo : Prop
?_ = ?_ : Prop
but is expected to have type
foo = bar : Prop
-/
@ -114,7 +116,7 @@ seal baz in
error: type mismatch
rfl
has type
baz 0 = baz 0 : Prop
?_ = ?_ : Prop
but is expected to have type
baz 0 = 0 : Prop
-/
@ -136,7 +138,7 @@ seal quux in
error: type mismatch
rfl
has type
quux 0 = quux 0 : Prop
?_ = ?_ : Prop
but is expected to have type
quux 0 = 0 : Prop
-/

View file

@ -5,11 +5,12 @@ import UserAttr.BlaAttr
attribute [local irreducible] myFun
set_option pp.mvars false
/--
error: type mismatch
rfl
has type
myFun x = myFun x : Prop
?_ = ?_ : Prop
but is expected to have type
myFun x = x + 1 : Prop
-/