[R-pkg-devel] tryCatch() doesn't capture errors due to && or || with R CMD check --as-cran
Etienne Bacher
et|enne@b@cher @end|ng |rom protonm@||@com
Thu Sep 1 15:55:15 CEST 2022
Dear all,
Calling && or || with LHS or (if evaluated) RHS of length greater than one gives an error in the devel version of R and a warning since R 4.2.0. With R 4.2.1, I can capture this warning with tryCatch(). However, R CMD check with R-devel fails because of this new behavior, meaning that tryCatch() doesn't work. For example, take this function:
foo <- function() {
tryCatch(
if (c(TRUE, TRUE) || c(TRUE, TRUE)) 1,
warning = function(w) {
print(w)
NULL
},
error = function(e) {
print(e)
NULL
}
)
}
With R 4.2.1, this correctly gives a warning and returns NULL when I run this locally:
> foo()
<simpleWarning in c(TRUE, TRUE) || c(TRUE, TRUE): 'length(x) = 2 > 1' in coercion to 'logical(1)'>
NULL
And if I change the environment variables to return an error instead of the warning, it correctly gives an error and returns NULL:
> Sys.setenv(
`_R_CHECK_LENGTH_1_CONDITION_` = "true",
`_R_CHECK_LENGTH_1_LOGIC2_` = "true"
)
>foo()
<simpleError in c(TRUE, TRUE) || c(TRUE, TRUE): 'length(x) = 2 > 1' in coercion to 'logical(1)'>
NULL
This behavior is expected. But if I put this function in a package, add a test for it, and run R CMD check "." --as-cran (or rcmdcheck::rcmdcheck(args = "--as-cran")), then I get an error that I paste at the end of this email because it's quite long. I thought that tryCatch() would capture this error, even when using R CMD check with R-devel, but this is not the case. Is this an expected behavior or a bug?
If you want to reproduce this error, I made a tiny package here: https://github.com/etiennebacher/testpackage. You can simply clone the repo and run R CMD check on it.
If it matters, I'm using R 4.2.1 on Windows 10.
Thanks in advance,
Etienne
----------- FAILURE REPORT --------------
--- failure: length > 1 in coercion to logical ---
--- srcref ---
:
--- package (from environment) ---
compiler
--- call from context ---
do.call(ffun, args)
--- call from argument ---
.Primitive("||")(c(TRUE, TRUE), c(TRUE, TRUE))
--- R stacktrace ---
where 1: do.call(ffun, args)
where 2: mode(e)
where 3: mode(e) %in% constModes
where 4: checkConst(do.call(ffun, args))
where 5: doTryCatch(return(expr), name, parentenv, handler)
where 6: tryCatchOne(expr, names, parentenv, handlers[[1L]])
where 7: tryCatchList(expr, names[-nh], parentenv, handlers[-nh])
where 8: doTryCatch(return(expr), name, parentenv, handler)
where 9: tryCatchOne(tryCatchList(expr, names[-nh], parentenv, handlers[-nh]),
names[nh], parentenv, handlers[[nh]])
where 10: tryCatchList(expr, classes, parentenv, handlers)
where 11: tryCatch(checkConst(do.call(ffun, args)), error = function(e) NULL,
warning = function(w) NULL)
where 12: constantFoldCall(e, cntxt)
where 13: constantFold(test, cntxt, loc = cb$savecurloc())
where 14: h(e, cb, cntxt)
where 15: tryInline(call, cb, cntxt)
where 16: cmpCall(e, cb, cntxt)
where 17: cmp(e, cb, cntxt, setloc = FALSE)
where 18: genCode(a, pcntxt, loc = cb$savecurloc())
where 19: cb$putconst(genCode(a, pcntxt, loc = cb$savecurloc()))
where 20: cmpCallArgs(args, cb, cntxt, nse)
where 21: cmpCallSymFun(fun, args, call, cb, cntxt)
where 22: cmpCall(e, cb, cntxt)
where 23: cmp(subexp, cb, cntxt, setloc = FALSE)
where 24: h(e, cb, cntxt)
where 25: tryInline(call, cb, cntxt)
where 26: cmpCall(e, cb, cntxt)
where 27: cmp(e, cb, cntxt, setloc = FALSE)
where 28: genCode(body(f), ncntxt, loc = loc)
where 29: cmpfun(f)
where 30: doTryCatch(return(expr), name, parentenv, handler)
where 31: tryCatchOne(expr, names, parentenv, handlers[[1L]])
where 32: tryCatchList(expr, classes, parentenv, handlers)
where 33: tryCatch(cmpfun(f), error = function(e) {
notifyCompilerError(paste(e$message, "at", deparse(e$call)))
f
})
where 34: compiler:::tryCmpfun(function ()
{
tryCatch(if (c(TRUE, TRUE) || c(TRUE, TRUE))
1, warning = function(w) {
print(w)
NULL
}, error = function(e) {
print(e)
NULL
})
})
where 35: lazyLoadDBinsertVariable(vars[i], from, datafile, ascii, compress,
envhook)
where 36: makeLazyLoadDB(ns, dbbase, compress = compress, set.install.dir = set.install.dir)
where 37: code2LazyLoadDB(package, lib.loc = lib.loc, keep.source = keep.source,
keep.parse.data = keep.parse.data, compress = compress, set.install.dir = set.install.dir)
where 38: tools:::makeLazyLoading("testpackage", "C:/Users/etienne/AppData/Local/Temp/Rtmp8QXtOL/file41b43ee61605/testpackage.Rcheck/00LOCK-TESTPA~1/00new",
keep.source = FALSE, keep.parse.data = FALSE, set.install.dir = "C:/Users/etienne/AppData/Local/Temp/Rtmp8QXtOL/file41b43ee61605/testpackage.Rcheck/testpackage")
--- value of length: 2 type: logical ---
[1] TRUE TRUE
--- function from context ---
function (what, args, quote = FALSE, envir = parent.frame())
{
if (!is.list(args))
stop("second argument must be a list")
if (quote)
args <- lapply(args, enquote)
.Internal(do.call(what, args, envir))
}
<bytecode: 0x0000021b0a155e20>
<environment: namespace:base>
--- function search by body ---
Function do.call in namespace base has this body.
----------- END OF FAILURE REPORT --------------
Fatal error: length > 1 in coercion to logical
More information about the R-package-devel
mailing list