lean4-htt/tests/elab/9463.lean
Kyle Miller eee2909c9d
fix: deriving Inhabited for structures should inherit Inhabited instances (#13395)
This PR makes the `deriving Inhabited` handler for `structure`s be able
to inherit `Inhabited` instances from structure parents, using the same
mechanism as for class parents. This fixes a regression introduced by
#9815, which lost the ability to apply `Inhabited` instances for parents
represented as subobject fields. With this PR, now it works for all
parents in the hierarchy.

Implementation detail: adds `struct_inst_default%` for synthesizing a
structure default value using `Inhabited` instances for parents and
fields.

Closes #13372
2026-04-14 02:46:07 +00:00

156 lines
3.6 KiB
Text
Raw Permalink 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.

module
/-!
# `deriving Inhabited` uses structure field defaults
https://github.com/leanprover/lean4/issues/9463
-/
/-!
This used to use `false` in the `default` instance.
-/
structure Config where
iota := true
deriving Inhabited
/-- info: true -/
#guard_msgs in #eval (default : Config).iota
/-- info: instInhabitedConfig : Inhabited Config -/
#guard_msgs in #check instInhabitedConfig
/-!
We don't require that every field have a default value.
-/
structure Config' where
iota := true
n : Nat
deriving Inhabited
/-- info: true -/
#guard_msgs in #eval (default : Config').iota
/-- info: 0 -/
#guard_msgs in #eval (default : Config').n
/-- info: instInhabitedConfig' : Inhabited Config' -/
#guard_msgs in #check instInhabitedConfig'
/-!
It still includes an `[Inhabited _]` parameter when needed.
-/
structure Config'' (α : Type) where
iota := true
n : α
deriving Inhabited
/-- info: true -/
#guard_msgs in #eval (default : Config'' Nat).iota
/-- info: 0 -/
#guard_msgs in #eval (default : Config'' Nat).n
/-- info: instInhabitedConfig'' {a✝ : Type} [Inhabited a✝] : Inhabited (Config'' a✝) -/
#guard_msgs in #check instInhabitedConfig''
/-!
In this example we can see that it adds an inhabited parameter.
-/
structure Config''' (α : Type) where
n : αα
deriving Inhabited
/-- info: instInhabitedConfig''' {a✝ : Type} [Inhabited a✝] : Inhabited (Config''' a✝) -/
#guard_msgs in #check instInhabitedConfig'''
/-!
Providing a default value inhibits adding an inhabited parameter.
-/
structure Config'''' (α : Type) where
n : αα := id
deriving Inhabited
/-- info: instInhabitedConfig'''' {a✝ : Type} : Inhabited (Config'''' a✝) -/
#guard_msgs in #check instInhabitedConfig''''
/-!
Mixed needs for `Inhabited` parameters.
-/
structure S (α β : Type) where
f : αα := id
g : β
deriving Inhabited
/-- info: instInhabitedS {a✝ a✝¹ : Type} [Inhabited a✝¹] : Inhabited (S a✝ a✝¹) -/
#guard_msgs in #check instInhabitedS
/-!
When there are structure field default value cycles, those defaults can be ignored.
-/
structure A (α : Type) where
(x y : α)
deriving Inhabited
structure B extends A Nat where
n : Nat := 2
x := y + 1
y := x + 1
deriving Inhabited
/-- info: 2 -/
#guard_msgs in #eval (default : B).n
/-- info: 0 -/
#guard_msgs in #eval (default : B).x
/-- info: 0 -/
#guard_msgs in #eval (default : B).y
/-!
Regression test: take `meta` into account.
-/
public meta section
inductive AliasInfo where
| plain (n : Nat)
deriving Inhabited, Repr
/-- info: AliasInfo.plain 0 -/
#guard_msgs in #eval repr (default : AliasInfo)
end
/-!
Regression test: take namespace into account.
-/
structure MyNS.MyStruct where
x : Nat
deriving Inhabited
/-- info: MyNS.instInhabitedMyStruct.default : MyNS.MyStruct -/
#guard_msgs in #check MyNS.instInhabitedMyStruct.default
/-- info: MyNS.instInhabitedMyStruct : Inhabited MyNS.MyStruct -/
#guard_msgs in #check MyNS.instInhabitedMyStruct
/-!
Fix for https://github.com/leanprover/lean4/issues/13372
Should inherit parent structures' Inhabited instances.
-/
structure Foo where
n : Nat
m : Nat
h : n ≤ m
instance : Inhabited Foo where
default := ⟨5, 5, Nat.le.refl⟩
-- Was: "failed to generate Inhabited instance for Bar"
structure Bar extends Foo where
extra : Bool := true
a : Nat
deriving Inhabited
/-- info: 5 -/
#guard_msgs in #eval (default : Bar).n
/-- info: true -/
#guard_msgs in #eval (default : Bar).extra
/-- info: 0 -/
#guard_msgs in #eval (default : Bar).a
/-- info: Bar.mk default true default : Bar -/
#guard_msgs in
set_option pp.structureInstances false in
#check (struct_inst_default% : Bar)