Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Init/Data/Range/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,4 @@ theorem Membership.get_elem_helper {i n : Nat} {r : Std.Range} (h₁ : i ∈ r)
i < n := h₂ ▸ h₁.2.1

macro_rules
| `(tactic| get_elem_tactic_trivial) => `(tactic| apply Membership.get_elem_helper; assumption; rfl)
| `(tactic| get_elem_tactic_extensible) => `(tactic| apply Membership.get_elem_helper; assumption; rfl)
4 changes: 2 additions & 2 deletions src/Init/GetElem.lean
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ proof in the context using `have`, because `get_elem_tactic` tries

The proof side-condition `valid xs i` is automatically dispatched by the
`get_elem_tactic` tactic; this tactic can be extended by adding more clauses to
`get_elem_tactic_trivial` using `macro_rules`.
`get_elem_tactic_extensible` using `macro_rules`.

`xs[i]?` and `xs[i]!` do not impose a proof obligation; the former returns
an `Option elem`, with `none` signalling that the value isn't present, and
Expand Down Expand Up @@ -281,7 +281,7 @@ instance [GetElem? cont Nat elem dom] [h : LawfulGetElem cont Nat elem dom] :
@[simp, grind =] theorem getElem!_fin [GetElem? Cont Nat Elem Dom] (a : Cont) (i : Fin n) [Inhabited Elem] : a[i]! = a[i.1]! := rfl

macro_rules
| `(tactic| get_elem_tactic_trivial) => `(tactic| (with_reducible apply Fin.val_lt_of_le); get_elem_tactic_trivial; done)
| `(tactic| get_elem_tactic_extensible) => `(tactic| (with_reducible apply Fin.val_lt_of_le); get_elem_tactic_extensible; done)

end Fin

Expand Down
29 changes: 17 additions & 12 deletions src/Init/Tactics.lean
Original file line number Diff line number Diff line change
Expand Up @@ -1917,30 +1917,35 @@ syntax "‹" withoutPosition(term) "›" : term
macro_rules | `(‹$type›) => `((by assumption : $type))

/--
`get_elem_tactic_trivial` is an extensible tactic automatically called
`get_elem_tactic_extensible` is an extensible tactic automatically called
by the notation `arr[i]` to prove any side conditions that arise when
constructing the term (e.g. the index is in bounds of the array).
The default behavior is to just try `trivial` (which handles the case
where `i < arr.size` is in the context) and `simp +arith` and `omega`
The default behavior is to try `simp +arith` and `omega`
(for doing linear arithmetic in the index).

(Note that the core tactic `get_elem_tactic` has already tried
`done` and `assumption` before the extensible tactic is called.)
-/
syntax "get_elem_tactic_extensible" : tactic

/-- `get_elem_tactic_trivial` has been deprecated in favour of `get_elem_tactic_extensible`. -/
syntax "get_elem_tactic_trivial" : tactic

macro_rules | `(tactic| get_elem_tactic_trivial) => `(tactic| omega)
macro_rules | `(tactic| get_elem_tactic_trivial) => `(tactic| simp +arith; done)
macro_rules | `(tactic| get_elem_tactic_trivial) => `(tactic| trivial)
macro_rules | `(tactic| get_elem_tactic_extensible) => `(tactic| omega)
macro_rules | `(tactic| get_elem_tactic_extensible) => `(tactic| simp +arith; done)
macro_rules | `(tactic| get_elem_tactic_extensible) => `(tactic| trivial)

/--
`get_elem_tactic` is the tactic automatically called by the notation `arr[i]`
to prove any side conditions that arise when constructing the term
(e.g. the index is in bounds of the array). It just delegates to
`get_elem_tactic_trivial` and gives a diagnostic error message otherwise;
users are encouraged to extend `get_elem_tactic_trivial` instead of this tactic.
`get_elem_tactic_extensible` and gives a diagnostic error message otherwise;
users are encouraged to extend `get_elem_tactic_extensible` instead of this tactic.
-/
macro "get_elem_tactic" : tactic =>
`(tactic| first
/-
Recall that `macro_rules` (namely, for `get_elem_tactic_trivial`) are tried in reverse order.
Recall that `macro_rules` (namely, for `get_elem_tactic_extensible`) are tried in reverse order.
We first, however, try `done`, since the necessary proof may already have been
found during unification, in which case there is no goal to solve (see #6999).
If a goal is present, we want `assumption` to be tried first.
Expand All @@ -1953,15 +1958,15 @@ macro "get_elem_tactic" : tactic =>
If `omega` is used to "fill" this proof, we will have a more complex proof term that
cannot be inferred by unification.
We hardcoded `assumption` here to ensure users cannot accidentally break this IF
they add new `macro_rules` for `get_elem_tactic_trivial`.
they add new `macro_rules` for `get_elem_tactic_extensible`.

TODO: Implement priorities for `macro_rules`.
TODO: Ensure we have **high-priority** macro_rules for `get_elem_tactic_trivial` which are
TODO: Ensure we have **high-priority** macro_rules for `get_elem_tactic_extensible` which are
just `done` and `assumption`.
-/
| done
| assumption
| get_elem_tactic_trivial
| get_elem_tactic_extensible
| fail "failed to prove index is valid, possible solutions:
- Use `have`-expressions to prove the index is valid
- Use `a[i]!` notation instead, runtime check is performed, and 'Panic' error message is produced if index is not valid
Expand Down
16 changes: 8 additions & 8 deletions stage0/stdlib/Init/Data/Array/Basic.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading