[Rd] Disabling S4 primitive dispatch during method resolution affects namespace load actions
Martin Maechler
m@ech|er @end|ng |rom @t@t@m@th@ethz@ch
Mon Sep 30 13:26:47 CEST 2024
>>>>> Martin Maechler
>>>>> on Fri, 27 Sep 2024 18:47:06 +0200 writes:
>>>>> Ivan Krylov via R-devel
>>>>> on Fri, 27 Sep 2024 13:32:27 +0300 writes:
>> Hello,
>> This problem originally surfaced as an interaction between 'brms',
>> 'rstan' and 'Rcpp' [1]: a call to dimnames() from the 'brms' package on
>> an object of an S4 class owned by the 'rstan' package tried to load its
>> namespace. rstan:::.onLoad needs to load Rcpp modules, which uses load
>> actions and reference classes. Since methods:::.findInheritedMethods
>> temporarily disables primitive S4 dispatch [2], reference classes break
>> and the namespace fails to load. I have prepared a small reproduction
>> package [3], which will need to be installed to show the problem:
>> R -q -s -e "saveRDS(repro::mk_external(), 'foo.rds')"
>> R -q -s -e "readRDS('foo.rds')"
>> # Loading required package: repro
>> # Error: package or namespace load failed for ‘repro’ in
>> # .doLoadActions(where, attach):
>> # error in load action .__A__.1 for package repro: bar$foo(): attempt
>> # to apply non-function
>> # Error in .requirePackage(package) : unable to find required package
>> # ‘repro’
>> # Calls: <Anonymous> ... .findInheritedMethods -> getClass ->
>> # getClassDef -> .requirePackage
>> # Execution halted
>> (Here it has to be a show() call to trigger the package load, not just
>> dimnames().)
>> I have verified that the following patch prevents the failure in
>> loading the namespace, but which other problems could it introduce?
>> Index: src/library/methods/R/RClassUtils.R
>> ===================================================================
>> --- src/library/methods/R/RClassUtils.R (revision 87194)
>> +++ src/library/methods/R/RClassUtils.R (working copy)
>> @@ -1812,6 +1812,9 @@
>> ## real version of .requirePackage
>> ..requirePackage <- function(package, mustFind = TRUE) {
>> + # we may be called from .findInheritedMethods, which disables S4 primitive dispatch
>> + primMethods <- .allowPrimitiveMethods(TRUE)
>> + on.exit(.allowPrimitiveMethods(primMethods))
>> value <- package
>> if(nzchar(package)) {
>> ## lookup as lightning fast as possible:
>> The original change to disable S4 primitive dispatch during method
>> resolution was done in r50609 (2009); this may be the first documented
>> instance of it causing a problem. The comment says "At the moment, this
>> is just for efficiency, but in principle it could be needed to avoid
>> recursive calls to findInheritedMethods."
>> --
>> Best regards,
>> Ivan
> Thank you, Ivan.
> Your patch makes sense indeed, given your previous findings on
> the R-package-devel list ([1]). It is short and looks ok.
> As you mention, speed loss may still be an issue, for S4/methods
> (including reference classes) - using R code.
> I was additionally interested to see your 'repro' package ([3]) and
> try if it does reproduce the problem ... and then if the patch
> resolves it.... and confirm that it does this nicely.
> I think we will get some speed if your new code is replaced by
> if(!.allowPrimitiveMethods(TRUE))
> on.exit(.allowPrimitiveMethods(FALSE))
> which is correct as we know that the argument and return value
> are both either TRUE or FALSE.
> Martin
A version of that has now been committed to "R-devel" (the
development version of R, in svn rev 87202 .
... with thanks to Ivan.
... I expect that the CRAN checks for broom.mixed (e.g.) will no
longer give 'ERROR' once the checks will use svn rev >= 87202.
Martin
More information about the R-devel
mailing list