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>
108 lines
2.2 KiB
Text
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
|