Skip to content

Consider masking definition of Rf_error()? #1247

Open

Description

@kevinushey

Somewhat related to a recent post on R-devel, some users will still try to use Rf_error() in C++ code using Rcpp. However, (as is documented) C++ destructors won't run when a longjmp occurs in cases like this. For example:

#include <Rcpp.h>
using namespace Rcpp;

struct A {
    A() { Rprintf("A()\n"); }
    ~A() { Rprintf("~A()\n"); }
};

// [[Rcpp::export]]
SEXP uhoh() {
    A a;
    Rf_error("Oops!");
}

/*** R
uhoh()
*/

In this example, ~A() is never printed.

We could consider masking the definition of Rf_error() in these contexts. For example, something like:

#define Rf_error(...) \
    static_assert(false, "Use of Rf_error() in C++ contexts is unwise: consider using Rcpp::stop() instead.");

There might also be a way to provide our own definition of Rf_error() that "masks" the version provided by R, but I wasn't able to find something immediately obvious.

Pinned by Enchufa2

Activity

  1. kevinushey commented on Oct 9, 2024

    @kevinushey
    ContributorAuthor

    Nice -- I very much like the idea of using a pragma here. Including a warning could also have other unexpected side effects (e.g. if the function calling Rf_error happened to be called with a condition handler active).

    Is it worth considering a way for users to opt-out, in case they really do need to use Rf_error in some specific context?

  2. Enchufa2 commented on Oct 9, 2024

    @Enchufa2
    Member

    Is it worth considering a way for users to opt-out, in case they really do need to use Rf_error in some specific context?

    #undef is the way out. This of course should be documented.

  3. eddelbuettel commented on Oct 9, 2024

    @eddelbuettel
    Member

    We can also have the definition itself inside an #ifndef Rcpp_Leave_Rf_Error_Alone (or equivalent). I think that would be more in line with common practice.

  4. github-actions commented on Oct 11, 2025

    @github-actions

    This issue is stale (365 days without activity) and will be closed in 31 days unless new activity is seen. Please feel free to re-open it is still a concern, possibly with additional data.

  5. Enchufa2 commented on Oct 28, 2025

    @Enchufa2
    Member

    Pinging the bot over here so that the issue is not closed. I'll propose something soon.

  6. Enchufa2 commented on Oct 28, 2025

    @Enchufa2
    Member
    • 88 revdeps contain autogenerated Rf_error calls in RcppExports.cpp: attributes.txt
    • 181 revdeps contain other manual calls to Rf_error: other.txt

    Total: 263 unique packages, because a few of them have them both.

  7. eddelbuettel commented on Oct 28, 2025

    @eddelbuettel
    Member

    We could warn now, warn with deprecation after January in 1.1.1, and remove next July in 1.1.2 ?

    We could move faster too. For RcppArmadillo I am currently in the middle of two transitions (no more C++11, plus deprecations) and CRAN was on board with both (in fact did 'no more C++11' on its own). A hint from @kurthornik was to rank order by reverse dependency. I ended up preparing PRs or emailed patches for all with 'n_rev_dep > 0'. Sixty-plus packages.

    Thoughts?

  8. Enchufa2 commented on Oct 28, 2025

    @Enchufa2
    Member

    A hint from @kurthornik was to rank order by reverse dependency.

    Updated above.

    We could warn now, warn with deprecation after January in 1.1.1, and remove next July in 1.1.2 ?

    So you mean

    1. warn now = just warn but without masking Rf_error?
    2. warn with deprecation = warn and mask?
    3. not sure what you mean by "remove". Or you mean mask here, and then I'm not getting the "with deprecation" part?

    I'm ok with moving fast. Most of them are fixed by just calling compileAttributes(). The issue is that if we send PRs for those, the work will be undone unless they develop their packages with a development version of Rcpp.

  9. eddelbuettel commented on Oct 28, 2025

    @eddelbuettel
    Member

    Correction: There is indeed no 'remove'. We are adding a warning.

  10. eddelbuettel commented on Oct 28, 2025

    @eddelbuettel
    Member

    So then the "softer" approach would be message() now instead of warning but we may also want to go for it. (After doing some more homework first, rev.deps, check with CRAN etc.)

  11. added a commit that references this issue on Jan 6, 2026
  12. Enchufa2 commented on Feb 27, 2026

    @Enchufa2
    Member

    I've filled a bunch of issues from the other.txt file above. Pending (leading number is the number of downstream deps):

    • These are yours, @eddelbuettel, but I didn't fill issues to avoid bombarding you. I can do that of course if you prefer to have these issues open to remind you about this.
    n_deps  package
    ===============
    28      RcppGSL              [ fixed version 0.3.14 on CRAN ][ was half a false positive but fix pushed ]
    6       nanotime             [ fixed version 0.3.13 on CRAN ][ fix in PR, merged ]
    4       RProtoBuf            [ fixed version 0.4.26 on CRAN ][ fix committed and pushed ]
    2       RcppDE               [ fixed version 0.1.9 on CRAN ][ fix committed and pushed ]
    1       RcppBDT              [ fixed version 0.2.8 on CRAN ][ fix committed and pushed ]
    1       RInside              [ false positive ][1]
    0       RcppCNPy             [ fixed version 0.2.15 on CRAN ][ fix committed and pushed ]
    0       RcppClassicExamples  [ fixed version 0.1.4 on CRAN ][ fix committed and pushed ]
    
    
    [1]  one match in plain C helper file used only in Windows case at startup 
    
    • I haven't found a public repo for these, so we should email the maintainers. [UPDATE: email sent]
    Details
    n_deps  package
    ===============
    28      minqa
    25      interp
    21      geiger
    12      kohonen
    12      gRbase
    11      cellWise
    7       gaston
    7       ecp
    4       diversitree
    4       GSE
    2       GMMAT
    2       cccp
    2       RCSF
    2       tokenbrowser
    2       steadyICA
    1       factorstochvol
    1       stepR
    1       DLMtool
    1       blackbox
    1       mrfDepth
    1       POSetR
    0       CompositionalRF
    0       FRESA.CAD
    0       MinTriadic
    0       GENLIB
    0       eseis
    0       simRestore
    0       STAREG
    0       missSOM
    0       ganGenerativeData
    0       dfmta
    0       textreg
    0       MAGEE
    0       bfp
    0       ganDataModel
    0       PoweR
    0       revealedPrefs
    0       fdaMixed
    0       fiberLD
    0       jmvconnect
    0       geeVerse
    0       ernm
    0       pompp
    0       essHist
    0       psgp
    0       ReAD
    0       ndl
    0       RScelestial
    0       Rmalschains
    0       HDclust
    0       RcppHMM
    0       dfcomb
    0       JUMP
    0       zic
    
  13. eddelbuettel commented on Feb 27, 2026

    @eddelbuettel
    Member

    I can definitely deal with mine, but it may also be that your numbers are inflated between looking at CRAN releases and git repos. E.g. I just picked nanotime and I only have this one left (which may want to become (Rf_error(...)). Ditto for RcppGSL where I expected more. Care to share how you greped and counted?

  14. Enchufa2 commented on Feb 27, 2026

    @Enchufa2
    Member

    These are number of downstream deps (to order by importance, as you suggested), not number of Rf_error calls.

    BTW, in cases like the one in nanotime, this try then forward_exception_to_r construction is obsolete. C++ exceptions are correctly handled nowadays (i.e. catched and forwarded to R via Rcpp::stop automatically).

  15. eddelbuettel commented on Feb 27, 2026

    @eddelbuettel
    Member

    Ack re count, just maybe make it more explicit. I was about to ask you about that; RcppGSL has one instance of the same. Easy to fix.

  16. Enchufa2 commented on Feb 27, 2026

    @Enchufa2
    Member

    Email sent to the rest of the maintainers (in bcc).

  17. eddelbuettel commented on Feb 27, 2026

    @eddelbuettel
    Member

    Did you point to public issue as a resource for them to consult, step to take to reproduce what you found to guide their development, other tips and tricks? (NM got the email now.)

  18. Enchufa2 commented on Feb 27, 2026

    @Enchufa2
    Member

    Yes, in the same way as the issues above. I sent the email to you, with everyone else in bcc.

  19. eddelbuettel commented on Feb 27, 2026

    @eddelbuettel
    Member

    He did not link back by @t-kalinowski is already done as well: rstudio/reticulate#1888

  20. Enchufa2 commented on Mar 4, 2026

    @Enchufa2
    Member

    Repository with weekly updates on the status of afected packages: https://github.com/Enchufa2/Rcpp-mask-Rf_error

  21. Enchufa2 commented on Mar 5, 2026

    @Enchufa2
    Member

    I emailed the remaining ones with calls in RcppExports.cpp that can be solved by running compileAttributes() with a current version of Rcpp, and updated the repo above. Three cases are yours, @eddelbuettel:

    RcppQuantuccia  [ fixed on GitHub ]
    RcppSpdlog      [ fixed on GitHub ][ version 0.0.28 on CRAN ]
    RQuantLib       [ fixed on GitHub ][ ... regular April release expected... ]
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions