lean4-htt/tests/elab/inferInstanceAs.lean
Sebastian Ullrich 06ac472859
feat: detect further sub-instances in wrapInstance (#13536)
This PR extends the procedure behind `inferInstanceAs`/`def ...
deriving` to continue recursion through the class graph even when a
(local) instance to wrap was found in order to re-use already-wrapped
instance of subclasses.
2026-05-02 11:55:04 +00:00

141 lines
3.3 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.

module
class C (α : Type) where
c : αα
/-! Trivial data wrapper -/
axiom I : Type
instance : C I where
c x := x
def D := I
instance : C D := inferInstanceAs (C I)
-- We can still use it as an `inferInstance` synonym in the old mode
set_option backward.inferInstanceAs.wrap false in
/-- info: «inferInstanceAs» (C D) : C D -/
#guard_msgs in
#check inferInstanceAs (C D)
/--
info: @[implicit_reducible] private def instCD : C D :=
{ c := instCD._aux_1 }
-/
#guard_msgs in
#print instCD
/--
info: private def instCD._aux_1 : D → D :=
fun x => x
-/
#guard_msgs in
#print instCD._aux_1
/-! Irreducible instances are wrapped as is. -/
axiom I2 : Type
@[instance] opaque instCI2 : C I2 := { c := fun x => x }
def D2 := I2
instance : C D2 := inferInstanceAs (C I2)
/--
info: @[implicit_reducible] private def instCD2 : C D2 :=
instCD2._aux_1
-/
#guard_msgs in
#print instCD2
/--
info: private def instCD2._aux_1 : C D2 :=
instCI2
-/
#guard_msgs in
#print instCD2._aux_1
/-! Flattened inheritance test. -/
class Base (α : Type) where
b : α
class Foo (α : Type) extends Base α where
a : α
class Bar (α : Type) extends Base α where
c : α
class FooBar (α : Type) extends Foo α, Bar α
instance : FooBar Nat where
a := 0
b := 1
c := 2
def MyNat := Nat
deriving Foo, Bar, FooBar
theorem zou : instFooBarMyNat.toBar = instBarMyNat := by
with_reducible_and_instances rfl
/-! Non-constructor instances should be used as is. -/
@[macro_inline, implicit_reducible]
def dite' {α : Sort u} (c : Prop) [h : Decidable c] (t : c → α) (e : Not c → α) : α :=
h.casesOn e t
instance Nat.decLe' (n m : @& Nat) : Decidable (LE.le n m) :=
dite' (Eq (Nat.ble n m) true) (fun h => isTrue (Nat.le_of_ble_eq_true h)) (fun h => isFalse (Nat.not_le_of_not_ble_eq_true h))
#guard_msgs in
instance (x y : BitVec w) : Decidable (LE.le x y) :=
(inferInstance : Decidable (LE.le x.toNat y.toNat))
instance (x y : BitVec w) : Decidable (LE.le x y) :=
inferInstanceAs (Decidable (LE.le x.toNat y.toNat))
/-! Universes can be introduced by synth and need to be unified with the expected type properly. -/
structure MyStruct where
x : PUnit.{u + 1} := ⟨⟩
y : PUnit.{v + 1} := ⟨⟩
instance : Zero MyStruct.{u, max u v} := ⟨{}⟩
instance : Zero MyStruct.{u, max u v} := inferInstanceAs <| Zero MyStruct.{u, max u v}
/-! Test reusing subinstances not encountered directly. -/
class Base2 (α : Type) where
a : α
class Main0 (α : Type) extends Base2 α where
b : α
class Main1 (α : Type) extends Base2 α where
c : α
class Super (α : Type) extends Main0 α, Main1 α where
def MyCopy (α : Type) : Type := α
instance iBase2 (α : Type) [Base2 α] : Base2 (MyCopy α) :=
inferInstanceAs <| Base2 α
instance iMain0 (α : Type) [Main0 α] : Main0 (MyCopy α) :=
inferInstanceAs <| Main0 α
instance iMain1 (α : Type) [Main1 α] : Main1 (MyCopy α) :=
inferInstanceAs <| Main1 α
instance iSuper (α : Type) [Super α] : Super (MyCopy α) :=
inferInstanceAs <| Super α
example (α : Type) [Super α] :
(iSuper α).toMain1 = iMain1 α := by
with_reducible_and_instances rfl
/--
info: @[implicit_reducible] private def iSuper : (α : Type) → [Super α] → Super (MyCopy α) :=
fun α [Super α] => { toMain0 := iMain0 α, c := Main1.c }
-/
#guard_msgs in
#print iSuper