Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rlang::last_trace() example in section 22.3.1 fails due to use of rlang::with_abort() #1740

Open
maxwellgreen opened this issue Sep 19, 2022 · 2 comments

Comments

@maxwellgreen
Copy link
Contributor

In section 22.3.1 ("Lazy evaluation") of chapter 22 ("Debugging"), there is an example intended to demonstrate the rlang traceback, but no traceback appears. I think this example fails because the code uses rlang::with_abort() to generate the error to trace back. with_abort() seems to no longer be a function in rlang (as of version 1.0.5 - the book uses 0.4.10), though I can't find in the changelog when it was removed or deprecated.

The faulty section is as follows:

rlang::with_abort(f(j()))
#> Error: Oops!
rlang::last_trace()
#> Error: Can't show last error because no error was recorded yet

@batpigandme
Copy link
Contributor

Just adding the link to the referenced section of the Debugging chapter where this example can be found:

adv-r/Debugging.Rmd

Lines 438 to 448 in dc49c38

* A function may generate an unexpected message. You can use
`rlang::with_abort()` to turn these messages into errors:
```{r, error = TRUE}
f <- function() g()
g <- function() message("Hi!")
f()
rlang::with_abort(f(), "message")
rlang::last_trace()
```

I tried to create something equivalent (and failed) by using rlang::global_handle() as suggested in r-lib/rlang#1351

Here's my attempt (n.b. must be run interactively to work)

rlang::global_handle()
f <- function() g()
g <- function() message("Hi!")
f()
#> Hi!
withCallingHandlers(
  f()
)
#> Hi!
rlang::last_messages()
#> [[1]]
#> <message/rlang_message>
#>   Message in `message()`:
#>   Hi!
#>   ---
#>   Backtrace:
#>   1. base::withCallingHandlers(f())
#>   2. global f()
#>   3. global g()

Since it's a message and not a warning, the promotion to error by way of options(warn = 2) doesn't do anything either.

@batpigandme
Copy link
Contributor

Other approach to above by modifying the warning2error() function from 8.6.3 Resignal:

adv-r/Conditions.Rmd

Lines 940 to 954 in dc49c38

```{r}
warning2error <- function(expr) {
withCallingHandlers(
warning = function(cnd) abort(conditionMessage(cnd)),
expr
)
}
```
```{r, error = TRUE}
warning2error({
x <- 2 ^ 4
warn("Hello")
})
```

library(rlang)
message2error <- function(expr) {
  withCallingHandlers(
    message = function(cnd) abort(conditionMessage(cnd)),
    expr
  )
}

message2error({
  x <- 2 ^ 4
  message("Hello")
})
#> Error:
#>   ! Hello
#> Run `rlang::last_trace()` to see where the error occurred.
rlang::last_trace()
#> <error/rlang_error>
#>   Error:
#>   ! Hello
#> ---
#>   Backtrace:
#>   ▆
#> 1. ├─global message2error(...)
#> 2. │ └─base::withCallingHandlers(...)
#> 3. ├─base::message("Hello")
#> 4. │ ├─base::withRestarts(...)
#> 5. │ │ └─base (local) withOneRestart(expr, restarts[[1L]])
#> 6. │ │   └─base (local) doWithOneRestart(return(expr), restart)
#> 7. │ └─base::signalCondition(cond)
#> 8. └─`<fn>`(`<smplMssg>`)
#> Run rlang::last_trace(drop = FALSE) to see 1 hidden frame.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants