Closed
Description
Using defer()
in the execution env causes a self-reference that may cause undefined behaviour (may just need a documentation note to recommend deferring expressions in private environments):
local({
withr::defer(NULL)
print(environment())
})
#> *infloop*
local_
functions cause side effects in arbitrary environments:
local(envir = asNamespace("rlang"), {
withr::local_options(list())
})
names(attributes(asNamespace("rlang")))
#> [1] "handlers"
Deferring expressions in a non-top-level global frame causes the message about deferred events to be printed, even though the on-exit expressions are correctly unwound.
options(foo = FALSE)
local(envir = globalenv(), {
withr::local_options(list(foo = TRUE))
})
#> Setting deferred event(s) on global environment.
#> * Execute (and clear) with `deferred_run()`.
#> * Clear (without executing) with `deferred_clear()`.
getOption("foo")
#> [1] FALSE
The handler attributes lingers around despite the handler having been called:
attr(globalenv(), "handler")
#> [[1]]
#> [[1]]$expr
#> reset_options(old)
#>
#> [[1]]$envir
#> <environment: 0x7fc2d2fa98c0>
I would expect no message in this case and the handler attribute to be cleaned up after execution. A non-top-level global frame can be detected with:
is_global_frame <- sys.parents() == 0
# TRUE if top-level
sum(is_global_frame) == 1
Metadata
Metadata
Assignees
Labels
No labels