lean4-htt/tests/lean/run/structInst.lean
Leonardo de Moura b668a18a9d
refactor: rename instance_reducible to implicit_reducible (#12567)
This PR renames `instance_reducible` to `implicit_reducible` and adds a
new
`backward.isDefEq.implicitBump` option to prepare for treating all
implicit
arguments uniformly during definitional equality checking.

## Changes

**Rename `instance_reducible` → `implicit_reducible`:**
- Rename `ReducibilityStatus.instanceReducible` constructor to
`implicitReducible`
- Register new `[implicit_reducible]` attribute, keep
`[instance_reducible]` as alias
- Rename `isInstanceReducible` → `isImplicitReducible` (with deprecated
aliases)
- Update all references across src/ and tests/

The rename reflects that this reducibility level is used not just for
instances
but for any definition that needs unfolding during implicit argument
resolution
(e.g., `Nat.add`, `Array.size`).

**Add `backward.isDefEq.implicitBump` option:**
- When `true` (+ `respectTransparency`), bumps transparency to
`.instances` for
ALL implicit arguments in `isDefEqArgs`, not just instance-implicit ones
- Defaults to `false` for staging compatibility — will be flipped to
`true` after
  stage0 update
- Adds `// update me!` to `stage0/src/stdlib_flags.h` to trigger CI
stage0 update

## Follow-up (after stage0 update)
- Flip `backward.isDefEq.implicitBump` default to `true`
- Fix resulting test/module failures

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 22:19:16 +00:00

387 lines
7.5 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.

/-!
# Tests for structure instance notation
-/
-- Make sure defaults pretty print so we can see what they elaborate to.
set_option pp.structureInstances.defaults true
namespace Ex1
structure A where
(x : Nat)
structure B extends A where
(y : Nat := x + 2) (x := y + 1)
structure C extends B where
(z : Nat) (x := z + 10)
/-- info: { x := 1 + 1, y := 1 } : B -/
#guard_msgs in #check { y := 1 : B }
/-- info: { x := 1 + 10, y := 1 + 10 + 2, z := 1 } : C -/
#guard_msgs in #check { z := 1 : C }
/-! Make sure `z` is parsed as an abbreviation: -/
/-- info: fun z => { x := z + 10, y := z + 10 + 2, z := z } : Nat → C -/
#guard_msgs in #check fun z : Nat => { z : C }
def test1 : B where
y := 1
def test2 : C where
z := 1
end Ex1
namespace Ex2
structure A where
(x : Nat) (y : Nat)
structure B extends A where
(z : Nat := x + 1) (y := z + x)
/-- info: { x := 1, y := 1 + 1 + 1, z := 1 + 1 } : B -/
#guard_msgs in #check { x := 1 : B }
def test1 : B where
x := 1
end Ex2
namespace Ex3
structure A where
(x : Nat)
structure B extends A where
(y : Nat := x + 2) (x := y + 1)
structure C extends B where
(z : Nat := 2*y) (x := z + 2) (y := z + 3)
-- This first example does not work because the default values at `C` are the only ones considered.
/--
error: Fields missing: `y`, `z`
Hint: Add missing fields:
̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲y̲ ̲:̲=̲ ̲_̲
̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲z̲ ̲:̲=̲ ̲_̲
---
info: { x := 1, y := sorry, z := sorry } : C
-/
#guard_msgs in #check { x := 1 : C }
/-- info: { x := 2 * 1 + 2, y := 1, z := 2 * 1 } : C -/
#guard_msgs in #check { y := 1 : C }
/-- info: { x := 1 + 2, y := 1 + 3, z := 1 } : C -/
#guard_msgs in #check { z := 1 : C }
-- This first example does not work because the default values at `C` are the only ones considered.
/-- error: Fields missing: `y`, `z` -/
#guard_msgs in
def test1 : C where
x := 1
def test2 : C where
y := 1
def test3 : C where
z := 1
end Ex3
namespace Ex4
structure A where
(x : Nat)
structure B extends A where
(y : Nat := x + 1) (x := y + 1)
structure C extends B where
(z : Nat := 2*y) (x := z + 3)
/-- info: { x := 1, y := 1 + 1, z := 2 * (1 + 1) } : C -/
#guard_msgs in #check { x := 1 : C }
/-- info: { x := 2 * 1 + 3, y := 1, z := 2 * 1 } : C -/
#guard_msgs in #check { y := 1 : C }
/-- info: { x := 1 + 3, y := 1 + 3 + 1, z := 1 } : C -/
#guard_msgs in #check { z := 1 : C }
/-- info: { x := 2, y := 2 + 1, z := 1 } : C -/
#guard_msgs in #check { z := 1, x := 2 : C }
/-- info: { x := 1 + 1, y := 1 } : B -/
#guard_msgs in #check { y := 1 : B }
def test1 : C where
x := 1
def test2 : C where
y := 1
def test3 : C where
z := 1
def test4 : C where
z := 1
x := 2
def test5 : C where
y := 1
end Ex4
/-!
Binders example
-/
structure PosFun where
f : Nat → Nat
pos : ∀ n, 0 < f n
def p : PosFun :=
{ f n := n + 1
pos := by simp }
def p_where : PosFun where
f n := n + 1
pos := by simp
/-!
Equations
-/
def p' : PosFun :=
{ f
| 0 => 1
| n + 1 => n + 1
pos := by rintro (_|_) <;> simp }
def p'_where : PosFun where
f
| 0 => 1
| n + 1 => n + 1
pos := by rintro (_|_) <;> simp
/-!
Binders and type ascriptions
-/
namespace Ex5
structure A (α : Type) (β : Type) where
x : α
f : β → β
z : α
/-- info: fun z => { x := 1, f := fun n => n + 1, z := z } : Int → A Int Int -/
#guard_msgs in #check fun z => { x : Int := 1, f n : Int := n + 1, z : A _ _ }
def test1 (z : Int) : A Int Int where
x : Int := 1
f n : Int := n + 1
z
end Ex5
/-!
Default instances are applied before analyzing default values.
Without this, `α` would be reported as being a missing field.
-/
namespace Ex6
structure MyStruct where
{α : Type u}
{β : Type v}
a : α
b : β
/-- info: { α := Nat, β := Bool, a := 10, b := true } : MyStruct -/
#guard_msgs in #check { a := 10, b := true : MyStruct }
end Ex6
/-!
Make sure we have the Lean 3 behavior, where field projections are unfolded.
https://github.com/leanprover-community/mathlib4/issues/12129#issuecomment-2056134533
-/
namespace Mathlib12129
structure Foo where
toFun : Nat → Nat
structure Bar extends Foo where
prop : toFun 0 = 0
/-
Rather than `(fun x => x) 0 = 0` or `{ toFun := fun x => x }.toFun 0 = 0`
-/
/-- trace: ⊢ 0 = 0 -/
#guard_msgs in
def bar : Bar where
toFun x := x
prop := by
trace_state
rfl
end Mathlib12129
/-!
Explicit fields must be provided, even if they can be inferred.
-/
namespace Ex7
structure S where
n : Nat
m : Fin n
variable (x : Fin 3)
/--
error: Fields missing: `n`
Field `n` must be explicitly provided; its synthesized value is
3
Hint: Add missing fields:
̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲ ̲n̲ ̲:̲=̲ ̲3̲
---
info: { n := 3, m := x } : S
-/
#guard_msgs in #check { m := x : S }
/-- info: { n := 3, m := x } : S -/
#guard_msgs in #check { n := _, m := x : S }
/-- info: { n := 3, m := x } : S -/
#guard_msgs in #check { m := x, .. : S }
/-- info: { n := 3, m := x } : S -/
#guard_msgs in #check { n := 3, m := x : S }
end Ex7
/-!
Diamond inheritance, acquire field values from parent classes.
https://github.com/leanprover/lean4/issues/6046
-/
namespace Issue6046
set_option structure.strictResolutionOrder true
class A
class B extends A where
b : Unit
structure B' where
b : Unit
class C extends B', B, A
instance : A where
instance : B where
b := ()
instance : C where
/--
info: @[implicit_reducible] def Issue6046.instC : C :=
{ b := B.b }
-/
#guard_msgs in #print Issue6046.instC
end Issue6046
/-!
Make sure parent fields still work if one parent depends on another.
-/
namespace Ex8
class A (α : Type) where
val : α → Nat
class B (α : Type) [A α] where
val' : α → Nat
h : ∃ x : α, A.val x = val' x
class C (α : Type) extends A α, B α
instance : A Nat where
val := id
instance : B Nat where
val' _ := 0
h := by exists 0
/-
This was "fields missing: 'val'', 'h'" at some point during testing.
To succeed, this relies on being able to compute the type of the `B` parent,
which depends on fields of the structure instance being elaborated.
-/
/-- info: { toA := instANat, toB := instBNat } : C Nat -/
#guard_msgs in #check { : C Nat }
end Ex8
/-!
Autoparams are elaborated eagerly. Here we see that `a` is printed before `b`.
-/
namespace Ex9
structure A where
n : Nat := by trace "a"; exact 1
m : Fin n
/--
trace: a
---
trace: b
-/
#guard_msgs in
example : A where
m := by trace "b"; exact 0
end Ex9
/-!
Issues with mixing optParams and autoParams.
https://github.com/leanprover/lean4/issues/6769
-/
namespace Ex6769_1
class Foo where
x : Nat := by fail
class Bar extends Foo where
x := 0
instance instBar : Bar where
/--
info: @[implicit_reducible] def Ex6769_1.instBar : Bar :=
{ x := 0 }
-/
#guard_msgs in #print instBar
end Ex6769_1
namespace Ex6769_2
class Foo where
x : Nat
hx : x = x
class Bar extends Foo where
hx' : x = x := by rfl
hx := hx'
instance instBar : Bar where
x := 0
/--
info: @[implicit_reducible] def Ex6769_2.instBar : Bar :=
{ x := 0, hx := Mathlib12129.bar._proof_1, hx' := Mathlib12129.bar._proof_1 }
-/
#guard_msgs in #print instBar
end Ex6769_2
namespace Ex6769_3
class Foo where
x : Nat
hx : x = x
class Bar extends Foo where
hx' : x = x := rfl
hx := hx'
instance instBar : Bar where
x := 0
/--
info: @[implicit_reducible] def Ex6769_3.instBar : Bar :=
{ x := 0, hx := Mathlib12129.bar._proof_1, hx' := Mathlib12129.bar._proof_1 }
-/
#guard_msgs in #print instBar
end Ex6769_3