diff --git a/src/Init/Tactics.lean b/src/Init/Tactics.lean index 477e55e6cc15..2e819f7133a6 100644 --- a/src/Init/Tactics.lean +++ b/src/Init/Tactics.lean @@ -354,6 +354,9 @@ macro:1 x:tactic tk:" <;> " y:tactic:2 : tactic => `(tactic| with_annotate_state $tk skip all_goals $y:tactic) +/-- `fail msg` is a tactic that always fails, and produces an error using the given message. -/ +syntax (name := fail) "fail" (ppSpace str)? : tactic + /-- `eq_refl` is equivalent to `exact rfl`, but has a few optimizations. -/ syntax (name := eqRefl) "eq_refl" : tactic @@ -365,8 +368,12 @@ for new reflexive relations. Remark: `rfl` is an extensible tactic. We later add `macro_rules` to try different reflexivity theorems (e.g., `Iff.rfl`). -/ -macro "rfl" : tactic => `(tactic| eq_refl) +macro "rfl" : tactic => `(tactic| fail "The rfl tactic failed. Possible reasons: +- The goal is not a reflexive relation (neither `=` nor a relation with a @[refl] lemma). +- The arguments of the relation are not equal. +Try using the reflexivitiy lemma for your relation explicitly, e.g. `exact Eq.rfl`.") +macro_rules | `(tactic| rfl) => `(tactic| eq_refl) macro_rules | `(tactic| rfl) => `(tactic| exact HEq.rfl) /-- @@ -907,9 +914,6 @@ example : ∀ x : Nat, x = x := by unhygienic -/ macro "unhygienic " t:tacticSeq : tactic => `(tactic| set_option tactic.hygienic false in $t) -/-- `fail msg` is a tactic that always fails, and produces an error using the given message. -/ -syntax (name := fail) "fail" (ppSpace str)? : tactic - /-- `checkpoint tac` acts the same as `tac`, but it caches the input and output of `tac`, and if the file is re-elaborated and the input matches, the tactic is not re-run and diff --git a/src/Lean/Elab/Tactic/Basic.lean b/src/Lean/Elab/Tactic/Basic.lean index 3933c022bb34..ee6f3a80c62b 100644 --- a/src/Lean/Elab/Tactic/Basic.lean +++ b/src/Lean/Elab/Tactic/Basic.lean @@ -158,8 +158,9 @@ partial def evalTactic (stx : Syntax) : TacticM Unit := do | _ => throwError m!"unexpected tactic{indentD stx}" where throwExs (failures : Array EvalTacticFailure) : TacticM Unit := do - if let some fail := failures[0]? then - -- Recall that `failures[0]` is the highest priority evalFn/macro + if h : 0 < failures.size then + -- For macros we want to report the error from the first registered / last tried rule (#3770) + let fail := failures[failures.size-1] fail.state.restore (restoreInfo := true) throw fail.exception -- (*) else diff --git a/tests/lean/run/issue3770.lean b/tests/lean/run/issue3770.lean new file mode 100644 index 000000000000..b1ba2b919d7c --- /dev/null +++ b/tests/lean/run/issue3770.lean @@ -0,0 +1,23 @@ +macro "foo" : tactic => `(tactic|fail "first") +macro_rules | `(tactic|foo) => `(tactic|exact 1) +macro_rules | `(tactic|foo) => `(tactic|fail "middle") +macro_rules | `(tactic|foo) => `(tactic|exact 2) +macro_rules | `(tactic|foo) => `(tactic|fail "last") + +def what_is_foo : Nat := by foo + +/-- info: 2 -/ +#guard_msgs in +#eval what_is_foo + + +macro "bar" : tactic => `(tactic|fail "first") +macro_rules | `(tactic|bar) => `(tactic|fail "middle") +macro_rules | `(tactic|bar) => `(tactic|fail "last") + +/-- +error: first +⊢ Nat +-/ +#guard_msgs in +def what_is_bar : Nat := by bar diff --git a/tests/lean/runTacticMustCatchExceptions.lean.expected.out b/tests/lean/runTacticMustCatchExceptions.lean.expected.out index 6c0381b82747..f8bb3afdc859 100644 --- a/tests/lean/runTacticMustCatchExceptions.lean.expected.out +++ b/tests/lean/runTacticMustCatchExceptions.lean.expected.out @@ -1,36 +1,39 @@ -runTacticMustCatchExceptions.lean:2:25-2:28: error: type mismatch - Iff.rfl -has type - ?m ↔ ?m : Prop -but is expected to have type - 1 ≤ a + b : Prop -runTacticMustCatchExceptions.lean:3:25-3:28: error: type mismatch - Iff.rfl -has type - ?m ↔ ?m : Prop -but is expected to have type - a + b ≤ b : Prop -runTacticMustCatchExceptions.lean:4:25-4:28: error: type mismatch - Iff.rfl -has type - ?m ↔ ?m : Prop -but is expected to have type - b ≤ 2 : Prop -runTacticMustCatchExceptions.lean:9:18-9:21: error: type mismatch - Iff.rfl -has type - ?m ↔ ?m : Prop -but is expected to have type - 1 ≤ a + b : Prop -runTacticMustCatchExceptions.lean:10:14-10:17: error: type mismatch - Iff.rfl -has type - ?m ↔ ?m : Prop -but is expected to have type - a + b ≤ b : Prop -runTacticMustCatchExceptions.lean:11:14-11:17: error: type mismatch - Iff.rfl -has type - ?m ↔ ?m : Prop -but is expected to have type - b ≤ 2 : Prop +runTacticMustCatchExceptions.lean:2:25-2:28: error: The rfl tactic failed. Possible reasons: +- The goal is not a reflexive relation (neither `=` nor a relation with a @[refl] lemma). +- The arguments of the relation are not equal. +Try using the reflexivitiy lemma for your relation explicitly, e.g. `exact Eq.rfl`. +a b : Nat +⊢ 1 ≤ a + b +runTacticMustCatchExceptions.lean:3:25-3:28: error: The rfl tactic failed. Possible reasons: +- The goal is not a reflexive relation (neither `=` nor a relation with a @[refl] lemma). +- The arguments of the relation are not equal. +Try using the reflexivitiy lemma for your relation explicitly, e.g. `exact Eq.rfl`. +a b : Nat +this : 1 ≤ a + b +⊢ a + b ≤ b +runTacticMustCatchExceptions.lean:4:25-4:28: error: The rfl tactic failed. Possible reasons: +- The goal is not a reflexive relation (neither `=` nor a relation with a @[refl] lemma). +- The arguments of the relation are not equal. +Try using the reflexivitiy lemma for your relation explicitly, e.g. `exact Eq.rfl`. +a b : Nat +this✝ : 1 ≤ a + b +this : a + b ≤ b +⊢ b ≤ 2 +runTacticMustCatchExceptions.lean:9:18-9:21: error: The rfl tactic failed. Possible reasons: +- The goal is not a reflexive relation (neither `=` nor a relation with a @[refl] lemma). +- The arguments of the relation are not equal. +Try using the reflexivitiy lemma for your relation explicitly, e.g. `exact Eq.rfl`. +a b : Nat +⊢ 1 ≤ a + b +runTacticMustCatchExceptions.lean:10:14-10:17: error: The rfl tactic failed. Possible reasons: +- The goal is not a reflexive relation (neither `=` nor a relation with a @[refl] lemma). +- The arguments of the relation are not equal. +Try using the reflexivitiy lemma for your relation explicitly, e.g. `exact Eq.rfl`. +a b : Nat +⊢ a + b ≤ b +runTacticMustCatchExceptions.lean:11:14-11:17: error: The rfl tactic failed. Possible reasons: +- The goal is not a reflexive relation (neither `=` nor a relation with a @[refl] lemma). +- The arguments of the relation are not equal. +Try using the reflexivitiy lemma for your relation explicitly, e.g. `exact Eq.rfl`. +a b : Nat +⊢ b ≤ 2