fix: expose `Array.back`, `back!`, and `back?` This PR marks `Array.back`, `Array.back!`, and `Array.back?` as `@[expose]`, so that in a downstream module their bodies are available for definitional reduction. Previously `decide` (and even `decide +kernel`) could not evaluate goals such as `#[1, 2, 3].back? = some 3` from another module, even though the `getElem?`/`size` accessors these functions are defined in terms of, and the neighbouring `Array.singleton`, are already exposed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
diff --git a/src/Init/Data/Array/Basic.lean b/src/Init/Data/Array/Basic.lean index 3104770..b38a623 100644 --- a/src/Init/Data/Array/Basic.lean +++ b/src/Init/Data/Array/Basic.lean
@@ -380,7 +380,7 @@ Safer alternatives include `Array.back`, which requires a proof the array is non-empty, and `Array.back?`, which returns an `Option`. -/ -@[inline] +@[inline, expose] def back! [Inhabited α] (xs : Array α) : α := xs[xs.size - 1]! @@ -390,7 +390,7 @@ See `Array.back!` for the version that panics if the array is empty, or `Array.back?` for the version that returns an option. -/ -@[inline] +@[inline, expose] def back (xs : Array α) (h : 0 < xs.size := by get_elem_tactic) : α := xs[xs.size - 1]'(Nat.sub_one_lt_of_lt h) @@ -400,7 +400,7 @@ See `Array.back!` for the version that panics if the array is empty, or `Array.back` for the version that requires a proof the array is non-empty. -/ -@[inline] +@[inline, expose] def back? (xs : Array α) : Option α := xs[xs.size - 1]?
diff --git a/tests/elab/exposeArrayBack.lean b/tests/elab/exposeArrayBack.lean new file mode 100644 index 0000000..6543247 --- /dev/null +++ b/tests/elab/exposeArrayBack.lean
@@ -0,0 +1,19 @@ +module + +/-! +`Array.back`, `Array.back!`, and `Array.back?` are `@[expose]`, so a +downstream `module` can reduce them under `decide` (and the kernel), exactly +like the `getElem?`/`size` accessors they are defined in terms of. Without +the attribute their bodies do not cross the module boundary and the `decide` +calls below get stuck on the unreduced application. +-/ + +-- Baseline: the accessors `back?` is built from already reduce. +example : (#[1, 2, 3] : Array Nat)[2]? = some 3 := by decide +example : (#[1, 2, 3] : Array Nat).size = 3 := by decide + +-- The `back` family must reduce too. +example : (#[1, 2, 3] : Array Nat).back? = some 3 := by decide +example : (#[1, 2, 3] : Array Nat).back? = some 3 := by decide +kernel +example : (#[1, 2, 3] : Array Nat).back! = 3 := by decide +example : (#[1, 2, 3] : Array Nat).back = 3 := by decide