Releases: r-lib/rlang
rlang 1.0.2
-
Backtraces of parent errors are now reused on rethrow. This avoids
capturing the same backtrace twice and solves consistency problems
by making sure both errors in a chain have the same backtrace. -
Fixed backtrace oversimplification when
cnd
is a base error in
abort(parent = cnd)
. -
Internal errors thrown with
abort(.internal = TRUE)
now mention
the name of the package the error should be reported to. -
Backtraces are now separated from error messages with a
---
ruler
line (#1368). -
The internal bullet formatting routine now ignores unknown names
(#1364). This makes it consistent with the cli package, increases
resilience against hard-to-detect errors, and increases forward
compatibility. -
abort()
and friends no longer calls non-existent functions
(e.g.cli::format_error()
orcli::format_warning
) when the
installed version of cli is too old (#1367, tidyverse/dplyr#6189). -
Fixed an OOB subsetting error in
abort()
.
rlang 1.0.1
-
New
rlang_call_format_srcrefs
global option (#1349). Similar to
rlang_trace_format_srcrefs
, this option allows turning off the
display of srcrefs in error calls. This can be useful for
reproducibility but note that srcrefs are already disabled
within testthat by default. -
abort(parent = NA)
is now supported to indicate an unchained
rethrow. This helpsabort()
detect the condition handling context
to create simpler backtraces where this context is hidden by
default. -
When
parent
is supplied,abort()
now loops over callers to
detect the condition handler frame. This makes it easier to wrap or
extract condition handlers in functions without supplying.frame
. -
When
parent
is supplied andcall
points to the condition setup
frame (e.g.withCallingHandlers()
ortry_fetch()
),call
is
replaced with the caller of that setup frame. This provides a more
helpful default call. -
is_call()
is now implemented in C for performance. -
Fixed performance regression in
trace_back()
. -
Fixed a partial matching issue with
header
,body
, andfooter
condition fields. -
eval_tidy()
calls are no longer mentioned in error messages.
rlang 1.0.0
Major changes
This release focuses on the rlang errors framework and features
extensive changes to the display of error messages.
-
abort()
now displays errors as fully bulleted lists. Error headers
are displayed with a!
prefix. See
https://rlang.r-lib.org/reference/topic-condition-customisation.html
to customise the display of error messages. -
abort()
now displays a full chain of messages when errors are
chained with theparent
argument. Following this change, you
should update dplyr to version 1.0.8 to get proper error messages. -
abort()
now displays function calls in which a message originated
by default. We have refrained from showing these calls until now to
avoid confusing messages when an error is thrown from a helper
function that isn't relevant to users.To help with these cases,
abort()
now takes acall
argument that
you can set tocaller_env()
orparent.frame()
when used in a
helper function. The function call corresponding to this environment
is retrieved and stored in the condition. -
cli formatting is now supported. Use
cli::cli_abort()
to get
advanced formatting of error messages, including indented bulleted
lists. See https://rlang.r-lib.org/reference/topic-condition-formatting.html. -
New
try_fetch()
function for error handling. We recommend to use
it for chaining errors. It mostly works liketryCatch()
with a few
important differences.-
Compared to
tryCatch()
,try_fetch()
preserves the call
stack. This allows full backtrace capture and allowsrecover()
to reach the error site. -
Compared to
withCallingHandler()
,try_fetch()
is able to
handle stack overflow errors (this requires R 4.2, unreleased at
the time of writing).
-
-
The tidy eval documentation has been fully rewritten to reflect
current practices. Access it through the "Tidy evaluation" and
"Metaprogramming" menus on https://rlang.r-lib.org.
Breaking changes
-
The
.data
object exported by rlang now fails when subsetted
instead of returningNULL
. This new error helps you detect when
.data
is used in the wrong context.We've noticed several packages failing after this change because
they were using.data
outside of a data-masking context. For
instance theby
argument ofdplyr::join()
is not data-masked.
Previouslydplyr::join(by = .data$foo)
would silently be
interpreted asdplyr::join(by = NULL)
. This is now an error.Another issue is using
.data
insideggplot2::labs(...)
. This is
not allowed sincelabs()
isn't data-masked. -
call_name()
now returnsNULL
instead of"::"
for calls of the
formfoo::bar
.We've noticed some packages do not check for
NULL
results from
call_name()
. Note that many complex calls such asfoo()()
,
foo$bar()
don't have a "name" and cause aNULL
result. This is
why you should always check forNULL
results when using
call_name()
.We've added the function
is_call_simple()
to make it easier to
work safely withcall_name()
. The invariant is thatcall_name()
always returns a string whenis_call_simple()
returnsTRUE
.
Conversely it always returnsNULL
whenis_call_simple()
retuns
FALSE
. -
is_expression()
now returnsFALSE
for manually constructed
expressions that can't be created by the parser. It used to return
TRUE
for any calls, including those that contain injected objects.Consider using
is_call()
or just remove the expression check. In
many cases it is fine letting all objects go through when an
expression is expected. For instance you can inject objects directly
inside dplyr arguments:x <- seq_len(nrow(data)) dplyr::mutate(data, col = !!x)
-
If a string is supplied to
as_function()
instead of an object
(function or formula), the function is looked up in the global
environment instead of the calling environment. In general, passing
a function name as a string is brittle. It is easy to forget to pass
the user environment toas_function()
and sometimes there is no
obvious user environment. The support for strings should be
considered a convenience for end users only, not for programmers.Since environment forwarding is easy to mess up, and since the
feature is aimed towards end users,as_function()
now defaults to
the global environment. Supply an environment explicitly if that is
not correct in your case. -
with_handlers()
,call_fn()
, andfriendly_type()
are deprecated. -
The
action
argument ofcheck_dots_used()
,check_dots_unnamed()
,
andcheck_dots_empty()
is deprecated in favour of the newerror
argument which takes an error handler. -
Many functions deprecated deprecated in rlang 0.2.0 and 0.3.0 have
been removed from the package.
Fixes and features
tidyeval
-
New
englue()
operator to allow string-embracing outside of dynamic
dots (#1172). -
New
data_sym()
anddata_syms()
functions to create calls of the
form.data$foo
. -
.data
now fails early when it is subsetted outside of a data mask
context. This provides a more informative error message (#804, #1133). -
as_label()
now better handles calls to infix operators (#956,
r-lib/testthat#1432). This change improves auto-labelled expressions
in data-masking functions liketibble()
,mutate()
, etc. -
The
{{
operator is now detected more strictly (#1087). If
additional arguments are supplied through{
, it is no longer
interpreted as an injection operator. -
The
.ignore_empty
argument ofenexprs()
andenquos()
no longer
treats named arguments supplied through...
as empty, consistently
withexprs()
andquos()
(#1229). -
Fixed a hang when a quosure inheriting from a data mask is evaluated
in the mask again. -
Fixed performance issue when splicing classes that explicitly
inherit from list with!!!
(#1140, r-lib/vctrs#1170). -
Attributes of quosure lists are no longer modified by side effect
(#1142). -
enquo()
,enquos()
and variants now support numbered dots like
..1
(#1137). -
Fixed a bug in the AST rotation algorithm that caused the
!!
operator to unexpectedly mutate injected objects (#1103). -
Fixed AST rotation issue with
!!
involving binary operators (#1125).
rlang errors
-
try_fetch()
is a flexible alternative to bothtryCatch()
and
withCallingHandlers()
(#503). It is also more efficient than
tryCatch()
and creates leaner backtraces. -
New
cnd_inherits()
function to detect a class in a chain of errors
(#1293). -
New
global_entrace()
function, a user-friendly helper for
configuring errors in your RProfile. Call it to enrich all base
errors and warnings with an rlang backtrace. This enables
last_error()
,last_warnings()
,last_messages()
, and
backtrace_on_error
support for all conditions. -
New
global_handle()
function to install a default configuration of
error handlers. This currently callsglobal_entrace()
and
global_prompt_install()
. Expect more to come. -
The "Error:" part of error messages is now printed by rlang instead
of R. This introduces several cosmetic and informative changes in
errors thrown byabort()
:-
The
call
field of error messages is now displayed, as is the
default inbase::stop()
. The call is only displayed if it is a
simple expression (e.g. no inlined function) and the arguments are
not displayed to avoid distracting from the error message. The
message is formatted with the tidyverse style (code
formatting
by the cli package if available). -
The source location is displayed (as in
base::stop()
) ifcall
carries a source reference. Source locations are not displayed
when testthat is running to avoid brittle snapshots. -
Error headers are always displayed on their own line, with a
"!"
bullet prefix.
See https://rlang.r-lib.org/reference/topic-condition-customisation.html
to customise this new display. -
-
The display of chained errors created with the
parent
argument of
abort()
has been improved. Chains of errors are now displayed at
throw time with the error prefix "Caused by error:". -
The
print()
method of rlang errors (commonly invoked with
last_error()
) has been improved:- Display calls if present.
- Chained errors are displayed more clearly.
-
inform()
andwarn()
messages can now be silenced with the global
optionsrlib_message_verbosity
andrlib_warning_verbosity
. -
abort()
now outputs error messages tostdout
in interactive
sessions, following the same approach asinform()
. -
Errors, warnings, and messages generated from rlang are now
formatted with cli. This means in practice that long lines are
width-wrapped to the terminal size and user themes are applied.
This is currently only the case for rlang messages.This special formatting is not applied when
abort()
,warn()
, and
inform()
are called from another namespace than rlang.
See https://rlang.r-lib.org/reference/topic-condition-formatting.html
if you'd like to use cli to format condition messages in your
package. -
format_error_bullets()
(used as a fallback instead of cli) now
treats:- Unnamed elements as unindented line breaks (#1130)
- Elements named
"v"
as green ticks (@rossellhayes) - Elements named
" "
as indented line breaks - Elements named
"*"
as normal bullets - Elements named
"!"
as warning bullets
For convenience, a fully unnamed vector is interpreted as a vector
of"*"
bullets. -
abort()
gains a.internal
argument. When set toTRUE
, a footer
bullet is added tomessage
to let the user know that the error is
inter...
rlang 0.4.11
-
Fix for CRAN checks.
-
Fixed a gcc11 warning related to
hash()
(#1088).
rlang 0.4.10
-
New
hash()
function to generate 128-bit hashes for arbitrary R objects
using the xxHash library. The implementation is modeled after
xxhashlite, created
by @coolbutuseless. -
New
check_installed()
function. Unlikeis_installed()
, it asks
the user whether to install missing packages. If the user accepts,
the packages are installed withpak::pkg_install()
if available,
orutils::install.packages()
otherwise. If the session is non
interactive or if the user chooses not to install the packages, the
current evaluation is aborted (#1075). -
rlang is now licensed as MIT (#1063).
-
Fixed an issue causing extra empty lines in
inform()
messages with
.frequency
(#1076, @schloerke). -
expr_deparse()
now correctly wraps code using::
and:::
(#1072, @krlmlr).
rlang 0.4.9
Breaking changes
- Dropped support for the R 3.2 series.
New features
-
inject()
evaluates its argument with!!
,!!!
, and{{
support. -
New
enquo0()
andenquos0()
operators for defusing function
arguments without automatic injection (unquotation). -
format_error_bullets()
is no longer experimental. Themessage
arguments ofabort()
,warn()
, andinform()
are automatically
passed to that function to make it easy to create messages with
regular, info, and error bullets. See?format_error_bullets
for
more information. -
New
zap_srcref()
function to recursively remove source references
from functions and calls. -
A new compat file for the zeallot operator
%<-%
is now available
in the rlang repository. -
New
%<~%
operator to define a variable lazily. -
New
env_browse()
andenv_is_browsed()
functions.env_browse()
is equivalent to evaluatingbrowser()
within an environment. It
sets the environment to be persistently browsable (or unsets it if
value = FALSE
is supplied). -
Functions created from quosures with
as_function()
now print in a
more user friendly way. -
New
rlang_print_backtrace
C callable for debugging from C
interpreters (#1059).
Bugfixes and improvements
-
The
.data
pronoun no longer skips functions (#1061). This solves a
dplyr issue involving rowwise data frames and list-columns of
functions (tidyverse/dplyr#5608). -
as_data_mask()
now intialises environments of the correct size to
improve efficiency (#1048). -
eval_bare()
,eval_tidy()
(#961), andwith_handlers()
(#518)
now propagate visibility. -
cnd_signal()
now ignoresNULL
inputs. -
Fixed bug that prevented splicing a named empty vector with the
!!!
operator (#1045). -
The exit status of is now preserved in non-interactive sessions when
entrace()
is used as anoptions(error = )
handler (#1052,
rstudio/bookdown#920). -
next
andbreak
are now properly deparsed as nullary operators.
rlang 0.4.8
-
Backtraces now include native stacks (e.g. from C code) when the
winch package is installed and
rlang_trace_use_winch
is set toTRUE
(@krlmlr). -
Compatibility with upcoming testthat 3 and magrittr 2 releases.
-
get_env()
now returns the proper environment with primitive
functions, i.e. the base namespace rather than the base environment
(r-lib/downlit#32). -
entrace()
no longer handles non-rlang errors that carry a
backtrace. This improves compatibility with packages like callr. -
Backtraces of unhandled errors are now displayed without truncation
in non-interactive sessions (#856). -
is_interactive()
no longer consults "rstudio.notebook.executing"
option (#1031).
rlang 0.4.7
-
cnd_muffle()
now returnsFALSE
instead of failing if the
condition is not mufflable (#1022). -
warn()
andinform()
gain a.frequency
argument to control how
frequently the warning or message should be displayed. -
New
raw_deparse_str()
function for converting a raw vector into a
string of hexadecimal characters (@krlmlr, #978). -
The backtraces of chained errors are no longer decomposed by error
context. Instead, the error messages are displayed as a tree to
reflect the error ancestry, and the deepest backtrace in the ancestry
is displayed.This change simplifies the display (#851) and makes it possible to
rethow errors from a calling handler rather than an exiting handler,
which we now think is more appropriate because it allows users to
recover()
into the error. -
env_bind()
,env_bind_active()
,env_bind_lazy()
,env_get()
,
andenv_get_list()
have been rewritten in C. -
env_poke()
now supportszap()
sentinels for removing bindings
(#1012) and has better support for characters that are not
representable in the local encoding. -
env_poke()
has been rewritten in C for performance. -
The unicode translation warnings that appeared on Windows with R 4.0
are now fixed. -
env_unbind(inherit = TRUE)
now only removes a binding from the
first parent environment that has a binding. It used to remove the
bindings from the whole ancestry. The new behaviour doesn't
guarantee that a scope doesn't have a binding but it is safer. -
env_has()
is now rewritten in C for performance. -
dots_list()
gains a.named
argument for auto-naming dots (#957). -
It is now possible to subset the
.data
pronoun with quosured
symbols or strings (#807). -
Expressions like
quote(list("a b" = 1))
are now properly deparsed
byexpr_deparse()
(#950). -
parse_exprs()
now preserves names (#808). When a single string
produces multiple expressions, the names may be useful to figure out
what input produced which expression. -
parse_exprs()
now supports empty expressions (#954). -
list2(!!!x)
no longer evaluatesx
multiple times (#981). -
is_installed()
now properly handles apkg
argument of length > 1.
Before this it silently tested the first element ofpkg
only
and thus always returnedTRUE
if the first package was installed
regardless of the actual length ofpkg
. (#991, @salim-b) -
arg_match0()
is a faster version ofarg_match()
for use when performance
is at a premium (#997, @krlmlr).
rlang 0.4.6
!!!
now uses a combination oflength()
,names()
, and[[
to splice
S3 and S4 objects. This produces more consistent behaviour thanas.list()
on a wider variety of vector classes (#945, tidyverse/dplyr#4931).
rlang 0.4.5
-
set_names()
,is_formula()
, andnames2()
are now implemented in
C for efficiency. -
The
.data
pronoun now accepts symbol subscripts (#836). -
Quosure lists now explicitly inherit from
"list"
. This makes them
compatible with the vctrs package (#928). -
All rlang options are now documented in a centralised place, see
?rlang::faq-options
(#899, @smingerson). -
Fixed crash when
env_bindings_are_lazy()
gets improper arguments (#923). -
arg_match()
now detects and suggests possible typos in provided
arguments (@jonkeane, #798). -
arg_match()
now gives an error if argument is of length greater
than 1 and doesn't exactly match the values input, similar to base
match.arg
(#914, @AliciaSchep)