tidyselect usage broken when new empty environment is used.
Comes from
- https://github.com/rstudio/rmarkdown/issues/2537
following report at https://community.rstudio.com/t/rmd-rendering-on-connect-fail-while-knitting-locally-works/178673/16
Minimal reprex I get is
> evaluate::evaluate(c("library(gt)", "bob <- \"carb\"", "gt(mtcars) |>", " cols_label(contains(bob)~bob)"), env = new.env(), stop_on_error = 2)
Error in `resolve_cols_i()`:
! Problem while evaluating `contains(bob)`.
Caused by error:
! objet 'bob' introuvable
Run `rlang::last_trace()` to see where the error occurred.
> rlang::last_trace()
<error/rlang_error>
Error in `resolve_cols_i()`:
! Problem while evaluating `contains(bob)`.
Caused by error:
! objet 'bob' introuvable
---
Backtrace:
▆
1. ├─evaluate::evaluate(...)
2. │ └─evaluate:::evaluate_call(...)
3. │ ├─evaluate (local) timing_fn(...)
4. │ ├─base (local) handle(...)
5. │ ├─base::withCallingHandlers(...)
6. │ ├─base::withVisible(...)
7. │ └─evaluate:::eval_with_user_handlers(expr, envir, enclos, user_handlers)
8. │ └─base::eval(expr, envir, enclos)
9. │ └─base::eval(expr, envir, enclos)
10. │ └─gt::cols_label(gt(mtcars), contains(bob) ~ bob)
11. │ └─gt:::resolve_cols_c(expr = !!cols, data = .data)
12. │ └─gt:::resolve_cols_i(...)
13. │ ├─base::suppressWarnings(...)
14. │ │ └─base::withCallingHandlers(...)
15. │ └─tidyselect::eval_select(expr = quo, data = data, strict = strict)
16. │ └─tidyselect:::eval_select_impl(...)
17. │ ├─tidyselect:::with_subscript_errors(...)
18. │ │ └─rlang::try_fetch(...)
19. │ │ └─base::withCallingHandlers(...)
20. │ └─tidyselect:::vars_select_eval(...)
21. │ └─tidyselect:::walk_data_tree(expr, data_mask, context_mask)
22. │ └─tidyselect:::eval_context(expr, context_mask, call = error_call)
23. │ ├─tidyselect:::with_chained_errors(...)
24. │ │ └─rlang::try_fetch(...)
25. │ │ ├─base::tryCatch(...)
26. │ │ │ └─base (local) tryCatchList(expr, classes, parentenv, handlers)
27. │ │ │ └─base (local) tryCatchOne(expr, names, parentenv, handlers[[1L]])
28. │ │ │ └─base (local) doTryCatch(return(expr), name, parentenv, handler)
29. │ │ └─base::withCallingHandlers(...)
30. │ └─rlang::eval_tidy(as_quosure(expr, env), context_mask)
31. └─tidyselect::contains(bob)
32. └─tidyselect:::check_match(match)
33. └─rlang::is_character(match)
Run rlang::last_trace(drop = FALSE) to see 4 hidden frames.
Real use case within R Markdown and rendering with
rmarkdown::render("test.Rmd", envir = new.env())
which is what Posit connect do.
---
title: "testing"
output: html_document
---
```{r cars}
library(gt)
bob <- "carb"
gt(mtcars) |>
cols_label(contains(bob)~bob)
```
The example is indeed not great. This one throw similar but different error backtrace as it errors in f_rhs() so earlier
> evaluate::evaluate(c("library(gt)", "bob <- \"carb\"", "bob2 <- \"HELLO\"", "gt(mtcars) |>", " cols_label(contains(bob)~bob2)"), env = new.env(), stop_on_error = 2)
Error:
! objet 'bob2' introuvable
Run `rlang::last_trace()` to see where the error occurred.
> rlang::last_trace()
<error/rlang_error>
Error:
! objet 'bob2' introuvable
---
Backtrace:
▆
1. └─evaluate::evaluate(...)
2. └─evaluate:::evaluate_call(...)
3. ├─evaluate (local) timing_fn(...)
4. ├─base (local) handle(...)
5. ├─base::withCallingHandlers(...)
6. ├─base::withVisible(...)
7. └─evaluate:::eval_with_user_handlers(expr, envir, enclos, user_handlers)
8. └─base::eval(expr, envir, enclos)
9. └─base::eval(expr, envir, enclos)
10. └─gt::cols_label(gt(mtcars), contains(bob) ~ bob2)
11. └─rlang::eval_tidy(rlang::f_rhs(label_i))
---
title: "testing"
output: html_document
---
```{r cars}
library(gt)
bob <- "carb"
bob2 <- "new-carb"
gt(mtcars) |>
cols_label(contains(bob)~bob2)
```
I had @lionel- have a look into this, and here is the diagnosis he made:
it looks like formula parts are extracted without their environment and evaluated with eval_tidy(), for instance I see what boils down to:
f <- local({
foo <- 1
~foo
})
library(rlang)
# Using `eval_tidy()` here does not help because the RHS is a bare expression
eval_tidy(f_rhs(f))
#> Error: objet 'foo' introuvable
Instead we need to extract the environment as well. The easiest way is to use as_quosure() which takes the RHS of a formula and makes it into a quosure where the expression is bundled with the environment:
f <- local({
foo <- 1
~foo
})
library(rlang)
eval_tidy(as_quosure(f))
#> [1] 1
So @rich-iannone I believe we need to adapt some usage so that the publishing to connect issue does not happen anymore.