fix: fixes #2011
In Lean 4, we have support for typing constraints of the form ``` (?m ...).1 =?= v ``` where the type of `?m ...` is a structure with a single field. This kind of constraint is reduced to `?m ... =?= ⟨v⟩` This feature is implemented by the function `isDefEqSingleton`. As far as I remember, Lean 3 does not implement this feature. This commit disables this feature if the structure is a class. The goal is to avoid the generation of counterintuitive instances by typing inference. For example, in the example at issue #2011, the following weird instance was being generated for `Zero (f x)` ``` (@Zero.mk (f x✝) ((@instZero I (fun i => f i) fun i => inst✝¹ i).1 x✝) ``` where `inst✝¹` is the local instance `[∀ i, Zero (f i)]` Note that this instance is definitinally equal to the expected nicer instance `inst✝¹ x✝`. However, the nasty instance trigger nasty unification higher order constraints later. Note that a few tests broke because different error messages were produced. The new error messages seem better. I do not expect this change to affect Mathlib4 since Lean 3 does not have this feature.
This commit is contained in:
parent
b9f0062a58
commit
fedf235cba
4 changed files with 39 additions and 20 deletions
|
|
@ -1640,6 +1640,24 @@ private def isDefEqProj : Expr → Expr → MetaM Bool
|
|||
where
|
||||
/-- If `structName` is a structure with a single field and `(?m ...).1 =?= v`, then solve contraint as `?m ... =?= ⟨v⟩` -/
|
||||
isDefEqSingleton (structName : Name) (s : Expr) (v : Expr) : MetaM Bool := do
|
||||
if isClass (← getEnv) structName then
|
||||
/-
|
||||
We disable this feature is `structName` is a class. See issue #2011.
|
||||
The example at issue #2011, the following weird
|
||||
instance was being generated for `Zero (f x)`
|
||||
```
|
||||
(@Zero.mk (f x✝) ((@instZero I (fun i => f i) fun i => inst✝¹ i).1 x✝)
|
||||
```
|
||||
where `inst✝¹` is the local instance `[∀ i, Zero (f i)]`
|
||||
Note that this instance is definitinally equal to the expected nicer
|
||||
instance `inst✝¹ x✝`.
|
||||
However, the nasty instance trigger nasty unification higher order
|
||||
constraints later.
|
||||
|
||||
We say this behavior is defensible because it is more reliable to use TC resolution to
|
||||
assign `?m`.
|
||||
-/
|
||||
return false
|
||||
let ctorVal := getStructureCtor (← getEnv) structName
|
||||
if ctorVal.numFields != 1 then
|
||||
return false -- It is not a structure with a single field.
|
||||
|
|
|
|||
|
|
@ -1,17 +1,16 @@
|
|||
1870.lean:21:2-21:5: error: tactic 'rfl' failed, equality lhs
|
||||
Zero.ofOfNat0
|
||||
is not definitionally equal to rhs
|
||||
{ zero := 1 }
|
||||
⊢ Zero.ofOfNat0 = { zero := 1 }
|
||||
1870.lean:26:2-26:11: error: tactic 'apply' failed, failed to unify
|
||||
?a = ?a
|
||||
1870.lean:20:2-20:35: error: type mismatch
|
||||
congrArg (@OfNat.ofNat Nat 0) (congrArg (@Zero.toOfNat0 Nat) ?m)
|
||||
has type
|
||||
OfNat.ofNat 0 = OfNat.ofNat 0 : Prop
|
||||
but is expected to have type
|
||||
OfNat.ofNat 0 = OfNat.ofNat 1 : Prop
|
||||
1870.lean:24:2-24:16: error: tactic 'apply' failed, failed to unify
|
||||
?f ?a₁ = ?f ?a₂
|
||||
with
|
||||
Zero.ofOfNat0 = { zero := 1 }
|
||||
case h.h
|
||||
⊢ Zero.ofOfNat0 = { zero := 1 }
|
||||
1870.lean:31:2-31:11: error: tactic 'apply' failed, failed to unify
|
||||
?a = ?a
|
||||
OfNat.ofNat 0 = OfNat.ofNat 1
|
||||
⊢ OfNat.ofNat 0 = OfNat.ofNat 1
|
||||
1870.lean:29:2-29:16: error: tactic 'apply' failed, failed to unify
|
||||
?f ?a₁ = ?f ?a₂
|
||||
with
|
||||
Zero.ofOfNat0 = { zero := 1 }
|
||||
case h.h
|
||||
⊢ Zero.ofOfNat0 = { zero := 1 }
|
||||
OfNat.ofNat 0 = OfNat.ofNat 1
|
||||
⊢ OfNat.ofNat 0 = OfNat.ofNat 1
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ have.lean:4:0: error: expected term
|
|||
have.lean:2:18-2:19: error: don't know how to synthesize placeholder
|
||||
context:
|
||||
⊢ False
|
||||
have.lean:6:15-6:16: error: synthesized type class instance is not definitionally equal to expression inferred by typing rules, synthesized
|
||||
instOfNatNat 6
|
||||
inferred
|
||||
{ ofNat := 3 }
|
||||
have.lean:7:2-7:3: error: type mismatch
|
||||
f
|
||||
has type
|
||||
5 = 6 : Prop
|
||||
but is expected to have type
|
||||
5 = 3 : Prop
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ open Nat
|
|||
theorem zero_add (n : Nat) : 0 + n = n :=
|
||||
Nat.recOn (motive := fun x => 0 + x = x)
|
||||
n
|
||||
(show 0 + 0 = 0 from rfl)
|
||||
rfl
|
||||
(fun (n : Nat) (ih : 0 + n = n) =>
|
||||
show 0 + succ n = succ n from
|
||||
calc
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue