-
-
Notifications
You must be signed in to change notification settings - Fork 218
Rcpp::Language
appears to deep-clone arguments
#1386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thanks for opening a bug report, and I can confirm. With a slightly modified version of your script also showing the package version I have e.g. (in a container after installing 1.0.13-1) root@a5a6d7fb905b:/work# Rscript -e 'Rcpp::sourceCpp("issue1386.cpp")'
> test_call(sum)
1000
1000
> packageVersion("Rcpp")
[1] ‘1.0.13.1’
root@a5a6d7fb905b:/work# yet 1.0.14 releases last January shows the effect you isolated. I may have a go at bisecting the repo. |
The most probable change is this one: dfb530d |
Confirmed!! Good call, @Enchufa2 ! Bad at dfb530droot@7b5e5fd39ae1:/work# git checkout dfb530d7
Note: switching to 'dfb530d7'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at dfb530d7 avoid using SET_TYPEOF (#1315)
root@7b5e5fd39ae1:/work# install.r
* installing *source* package found in current working directory ...
* installing *source* package ‘Rcpp’ ...
** this is package ‘Rcpp’ version ‘1.0.13.0.2’
** using staged installation
** libs
using C++ compiler: ‘g++ (Debian 14.2.0-19) 14.2.0’
g++ -std=gnu++17 -I"/usr/share/R/include" -DNDEBUG -I../inst/include/ -fpic -g -O2 -ffile-prefix-map=/build/reproducible-path/r-base-4.5.0=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection -Wdate-time -D_FORTIFY_SOURCE=2 -c api.cpp -o api.o
g++ -std=gnu++17 -I"/usr/share/R/include" -DNDEBUG -I../inst/include/ -fpic -g -O2 -ffile-prefix-map=/build/reproducible-path/r-base-4.5.0=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection -Wdate-time -D_FORTIFY_SOURCE=2 -c attributes.cpp -o attributes.o
g++ -std=gnu++17 -I"/usr/share/R/include" -DNDEBUG -I../inst/include/ -fpic -g -O2 -ffile-prefix-map=/build/reproducible-path/r-base-4.5.0=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection -Wdate-time -D_FORTIFY_SOURCE=2 -c barrier.cpp -o barrier.o
g++ -std=gnu++17 -shared -L/usr/lib/R/lib -Wl,-z,relro -o Rcpp.so api.o attributes.o barrier.o date.o module.o rcpp_init.o -L/usr/lib/R/lib -lR
installing to /usr/local/lib/R/site-library/00LOCK-work/00new/Rcpp/libs
** R
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** installing vignettes
** testing if installed package can be loaded from temporary location
** checking absolute paths in shared objects and dynamic libraries
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (Rcpp)
root@7b5e5fd39ae1:/work# Rscript -e 'Rcpp::sourceCpp("issue1386.cpp")'
> test_call(sum)
1
1000
> packageVersion("Rcpp")
[1] ‘1.0.13.0.2’
root@7b5e5fd39ae1:/work# Good at c1699a0root@7b5e5fd39ae1:/work# git checkout c1699a01
Note: switching to 'c1699a01'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at c1699a01 Roll micro-release, update NEWS [ci ski]
root@7b5e5fd39ae1:/work# ./cleanup
root@7b5e5fd39ae1:/work# install.r
* installing *source* package found in current working directory ...
* installing *source* package ‘Rcpp’ ...
** this is package ‘Rcpp’ version ‘1.0.13.0.1’
** using staged installation
** libs
using C++ compiler: ‘g++ (Debian 14.2.0-19) 14.2.0’
g++ -std=gnu++17 -I"/usr/share/R/include" -DNDEBUG -I../inst/include/ -fpic -g -O2 -ffile-prefix-map=/build/reproducible-path/r-base-4.5.0=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werr
or=format-security -fcf-protection -Wdate-time -D_FORTIFY_SOURCE=2 -c api.cpp -o api.o
g++ -std=gnu++17 -I"/usr/share/R/include" -DNDEBUG -I../inst/include/ -fpic -g -O2 -ffile-prefix-map=/build/reproducible-path/r-base-4.5.0=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werr
or=format-security -fcf-protection -Wdate-time -D_FORTIFY_SOURCE=2 -c attributes.cpp -o attributes.o
g++ -std=gnu++17 -I"/usr/share/R/include" -DNDEBUG -I../inst/include/ -fpic -g -O2 -ffile-prefix-map=/build/reproducible-path/r-base-4.5.0=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werr
or=format-security -fcf-protection -Wdate-time -D_FORTIFY_SOURCE=2 -c barrier.cpp -o barrier.o
g++ -std=gnu++17 -I"/usr/share/R/include" -DNDEBUG -I../inst/include/ -fpic -g -O2 -ffile-prefix-map=/build/reproducible-path/r-base-4.5.0=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werr
or=format-security -fcf-protection -Wdate-time -D_FORTIFY_SOURCE=2 -c date.cpp -o date.o
g++ -std=gnu++17 -I"/usr/share/R/include" -DNDEBUG -I../inst/include/ -fpic -g -O2 -ffile-prefix-map=/build/reproducible-path/r-base-4.5.0=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werr
or=format-security -fcf-protection -Wdate-time -D_FORTIFY_SOURCE=2 -c module.cpp -o module.o
g++ -std=gnu++17 -I"/usr/share/R/include" -DNDEBUG -I../inst/include/ -fpic -g -O2 -ffile-prefix-map=/build/reproducible-path/r-base-4.5.0=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werr
or=format-security -fcf-protection -Wdate-time -D_FORTIFY_SOURCE=2 -c rcpp_init.cpp -o rcpp_init.o
g++ -std=gnu++17 -shared -L/usr/lib/R/lib -Wl,-z,relro -o Rcpp.so api.o attributes.o barrier.o date.o module.o rcpp_init.o -L/usr/lib/R/lib -lR
installing to /usr/local/lib/R/site-library/00LOCK-work/00new/Rcpp/libs
** R
** inst ** byte-compile and prepare package for lazy loading
** help *** installing help indices
** building package indices ** installing vignettes
** testing if installed package can be loaded from temporary location
** checking absolute paths in shared objects and dynamic libraries
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (Rcpp)
root@7b5e5fd39ae1:/work# Rscript -e 'Rcpp::sourceCpp("issue1386.cpp")'
> test_call(sum)
1000
1000
> packageVersion("Rcpp")
[1] ‘1.0.13.0.1’
root@7b5e5fd39ae1:/work# And those two were adjacent:
|
Thanks for the quick response! Based on the discussion so far, I think I may have found the root cause of the issue. When a Rcpp/inst/include/Rcpp/Language.h Line 112 in d8c084a
which then forwards it to the update method
Within Rcpp/inst/include/Rcpp/Language.h Line 163 in d8c084a
which eventually calls Rcpp/inst/include/Rcpp/r_cast.h Line 171 in d8c084a
However, Rcpp/inst/include/Rcpp/r_cast.h Line 154 in d8c084a
which, based on a small test I just ran, seems to perform a deep copy when converting a pairlist into a function call.
Here's the code I used: Rcpp::cppFunction('
void test_R_as_call(Function f) {
auto v = NumericVector::create(0.0, 1.0);
Rcpp::Shield<SEXP> p_lst(pairlist(f, v));
Rcpp::Function R_as_call("as.call");
Rcpp::Shield<SEXP> call(R_as_call(p_lst));
v[0] = 999.0;
Rcpp::Rcout << as<double>(Rcpp_fast_eval(call, R_GlobalEnv)) << std::endl;
}
')
test_R_as_call(sum)
#> 1 |
Nice work. While you are in the weeds, can you see a way to treat pairlist objects differently? |
It seems the deep clone occurs here The Given the complexity of converting a |
I agree with this as well; this would be the most appropriate fix.
Can you elaborate on what you mean here? As I understand it, I guess it's not a "cast" in the way we think of it in C++, where we might reinterpret an existing object as another object -- it's really just a "coerce" or "convert" kind of method? |
The issue we observed with
Thanks to your explanation. It seems my earlier concern may not actually apply. Cases where |
Really nice work by both of you on the initial report and the follow-up, and the cleanup PR. |
I've observed a difference in behavior between
Rcpp::Language
and the lower-levelRf_lang*
functions when constructing function calls.To my understanding, function calls in R are essentially pairlists (
LANGSXP
) that holdSEXP
— that is, pointers to R objects. As such, if an argument is modified after the call is constructed, the change should be visible during evaluation, since the call stores only pointers, not copies.However, calls created using
Rcpp::Language
do not reflect such modifications. It appears that the arguments are deep-copied during the construction of the call. This behavior did not occur in Rcpp 1.0.13, but it does appear in Rcpp 1.0.14.Here is a minimal reproducible example:
I'm wondering whether this change in behavior was intentional, or if it might be an unintended consequence of recent updates?
The text was updated successfully, but these errors were encountered: