-
Notifications
You must be signed in to change notification settings - Fork 150
Description
Reading help("condition"), there's nothing saying that a condition object should be a list. For example, there's in nothing in the R documentation that says the following is a invalid condition object:
cnd2 <- structure(42, class = "condition")My interpretation of the help page is that it is written such that carefully avoids declaring what type a condition object should be. In contrast, other help pages are often explicit about the type, e.g. a "a list" or "a named list", etc. I asked about this in the R-devel thread "Is structure(NA, class = c("def", "condition")) a valid 'condition' object?" on 2025-10-07 (https://stat.ethz.ch/pipermail/r-devel/2025-October/084184.html) - there's only one reply thus far, which seems to agree with my interpretation.
Looking at the implementation of rlang::cnd_entrace(), it appears that it assumes that condition:s are of type list, or possible, environment, because it makes use of [[ and .subset2(). For example, this works:
cnd <- structure(list(), class = "condition")
cnd <- rlang::cnd_entrace(cnd)but not:
cnd <- structure(42, class = "condition")
cnd <- rlang::cnd_entrace(cnd)
#> Error in x[["trace"]] : subscript out of bounds
#>
#> 1: rlang::cnd_entrace(cnd)
#> 2: cnd_some(cnd, function(x) !is_null(x[["trace"]]))Workaround
I think names() is defined for all types in R. This could be used to gate-keep the assumptions made by rlang, e.g.
diff --git a/R/cnd-entrace.R b/R/cnd-entrace.R
index 50ab54ea9..f64188e83 100644
--- a/R/cnd-entrace.R
+++ b/R/cnd-entrace.R
@@ -239,7 +239,7 @@ has_recover <- function() {
cnd_entrace <- function(cnd, ..., top = NULL, bottom = NULL) {
check_dots_empty0(...)
- if (cnd_some(cnd, function(x) !is_null(x[["trace"]]))) {
+ if (cnd_some(cnd, function(x) "trace" %in% names(x) && !is_null(x[["trace"]]))) {
return(cnd)
}
diff --git a/R/cnd.R b/R/cnd.R
index 6b9286020..fb3d88494 100644
--- a/R/cnd.R
+++ b/R/cnd.R
@@ -381,7 +381,8 @@ cnd_some <- function(cnd, fn, ...) {
return(TRUE)
}
- inherit <- .subset2(.subset2(cnd, "rlang"), "inherit")
+ inherit <- ("rlang" %in% names(cnd)) &&
+ .subset2(.subset2(cnd, "rlang"), "inherit")
if (is_false(inherit)) {
return(FALSE)
}There might be more instances in rlang where using $, [[, and .subset2() on condition need to be conditioned as above.
Background
FWIW, my R.oo package has an Exception class that inherits from error and condition is for this discussion effectively defined as:
cnd <- structure(NA, class = c("Exception", "error", "condition"))This Exception class is how many of the error have been thrown in R.oo, R.utils, R.filesets, aroma.affymetrix, ... since ~2001. I became aware of this problem after a recent issue report (HenrikBengtsson/R.utils#161).