lean4-htt/tests/elab/issue12846.lean
Sebastian Graf 490c79502b
fix: improve result type mismatch errors and locations in new do elaborator (#13404)
This PR fixes #12846, where the new do elaborator produced confusing
errors when a do element's continuation had a mismatched monadic result
type. The errors were misleading both in location (e.g., pointing at the
value of `let x ← value` rather than the `let` keyword) and in content
(e.g., mentioning `PUnit.unit` which the user never wrote).

The fix introduces `DoElemCont.ensureUnitAt`/`ensureHasTypeAt`, which
check the continuation result type early and report mismatches with a
clear message ("The `do` element has monadic result type ... but the
rest of the `do` block has monadic result type ..."). Each do-element
elaborator (`let`, `have`, `let rec`, `for`, `unless`, `dbg_trace`,
`assert!`, `idbg`, etc.) now captures its keyword token via `%$tk` and
passes it to `ensureUnitAt` so that the error points at the do element
rather than at an internal elaboration artifact. The old ad-hoc type
check in `for` and the confusing `ensureHasType` call in
`continueWithUnit` are replaced by this uniform mechanism. Additionally,
`extractMonadInfo` now calls `instantiateMVars` on the expected type,
and `While.lean`/`If.lean` macros propagate token info through their
expansions.

Closes #12846

---------

Co-authored-by: Rob23oba <robin.arnez@web.de>
2026-04-16 09:16:27 +00:00

108 lines
2.2 KiB
Text

module
set_option backward.do.legacy false
-- Original issue: `let x ← value` as last element in non-Unit do block
/--
error: Type mismatch. The `do` element has monadic result type
Unit
but the rest of the `do` block has monadic result type
Bool
-/
#guard_msgs in
def test_letArrow : IO Bool := do
let a ← pure 25
/--
error: Type mismatch. The `do` element has monadic result type
Unit
but the rest of the `do` block has monadic result type
Bool
-/
#guard_msgs in
def test_let : IO Bool := do
let a := 25
-- `have` as last element
/--
error: Type mismatch. The `do` element has monadic result type
Unit
but the rest of the `do` block has monadic result type
Bool
-/
#guard_msgs in
def test_have : IO Bool := do
have a := 25
-- `let rec` as last element
/--
error: Type mismatch. The `do` element has monadic result type
Unit
but the rest of the `do` block has monadic result type
Bool
-/
#guard_msgs in
def test_letRec : IO Bool := do
let rec f : Nat → Nat
| 0 => 0
| n + 1 => f n
-- `for` as last element
/--
error: Type mismatch. The `do` element has monadic result type
Unit
but the rest of the `do` block has monadic result type
Bool
-/
#guard_msgs in
def test_for : IO Bool := do
for _ in [1, 2, 3] do
pure ()
-- `dbg_trace` as last element
/--
error: Type mismatch. The `do` element has monadic result type
Unit
but the rest of the `do` block has monadic result type
Bool
-/
#guard_msgs in
def test_dbgTrace : IO Bool := do
dbg_trace "hello"
-- `assert!` as last element
/--
error: Type mismatch. The `do` element has monadic result type
Unit
but the rest of the `do` block has monadic result type
Bool
-/
#guard_msgs in
def test_assert : IO Bool := do
assert! true
-- `if` without else as last element
/--
error: Application type mismatch: The argument
()
has type
Unit
but is expected to have type
Bool
in the application
pure ()
---
error: Type mismatch. The `do` element has monadic result type
Unit
but the rest of the `do` block has monadic result type
Bool
-/
#guard_msgs in
def test_if_no_else : IO Bool := do
if true then
pure ()
-- `if` with else works fine when branches match the result type
#guard_msgs in
def test_if_else_ok : IO Bool := do
if true then pure true else pure false