Skip to content

chore: Merge upstream main into the fork - #12

Closed
krlmlr wants to merge 12 commits into
mainfrom
claude/merge-upstream-42ve6t
Closed

krlmlr wants to merge 12 commits into
mainfrom
claude/merge-upstream-42ve6t

Conversation

@krlmlr

@krlmlr krlmlr commented Sep 12, 2026

Copy link
Copy Markdown
Owner

Merges r-lib/cpp11@7d0e4ac (upstream main) into the fork's main. The merge base was adfb240 (usethis::use_claude_code() (r-lib#485)); upstream has since added the Air formatter, cpp_source() multi-file support (r-lib#492), the tag-type ODR fix for cpp11::stop()/cpp11::warning() (r-lib#493), the removal of non-API R_NamespaceRegistry usage (r-lib#488), and two releases. The guiding principle was to keep the fork's intent while taking upstream's advances.

Three files conflicted.

R/vendor.R — the fork adds date and overwrite arguments to cpp_vendor(); upstream reformatted the function with Air. Resolved by re-applying the fork's overwrite branch and as.Date(date) on top of upstream's Air-formatted shape, rather than reverting the reformatting.

R/source.R — resolved by taking upstream's version wholesale. Upstream's multi-file cpp_source() (r-lib#492) is a strict superset of the fork's "vectorize file" change: it uses vcapply(file, generate_cpp_name) for the per-file names and a freshly generated random generate_package_name() for the shared library, which avoids the name collisions the fork's tools::file_path_sans_ext(name[[1]]) approach could hit. Upstream also already carries the fork's fix to report the first missing file in the "Can't find file" error. The merged R/source.R is byte-identical to upstream's.

inst/include/cpp11/protect.hpp — resolved by taking upstream's version wholesale. See "Dropped as superseded" below.

Two other fork changes merged cleanly but are worth noting: R/register.R's sub()gsub() fix for package names with multiple dots survived upstream's large refactor of that file untouched, and the fork-only headers (declarations.hpp, external_pointer.hpp, r_vector.hpp, sexp.hpp) plus cpp11test/src/test-external_pointer.cpp were not touched upstream at all.

Dropped as superseded

The fork's protect.hpp change — "Copy strings before calling Rf_warningcall() to avoid weird unwind behavior", which removed the warning(const char*, ...) overloads and changed warning(const std::string&, ...) to take the format string by value — has been dropped. That was a workaround for r-lib#295, where cpp11::warning(const char*) crashes but cpp11::warning(const std::string&) does not. Upstream's r-lib#493 fixes the root cause: Rf_errorcall() and Rf_warningcall() have the same function type, so cpp11::stop() and cpp11::warning() were instantiating one and the same detail::closure / detail::apply() template, and under ODR the [[noreturn]]-flavoured instantiation could win and make the return path in warning() unreachable. Upstream adds detail::return_tag / detail::no_return_tag to the template parameters so the two get distinct instantiations, and ships a regression test (cpp11test/src/template-1-stop.cpp, template-2-warn.cpp, cpp11test/tests/testthat/test-template.R) that reproduces the original crash. Keeping the fork's workaround on top would have needlessly removed the const char* overloads from the public API and pessimised the remaining ones, so upstream's version is taken unchanged and that test now passes here.

Other changes

inst/include/cpp11/sexp.hpp was reformatted with clang-format. The fork's three [[deprecated]] conversion operators were written on single lines well past the project's 90 column limit and already failed clang-format --dry-run -Werror on main before this merge; only whitespace changed, the attributes and bodies are untouched.

Verification

air format . leaves the tree unchanged. clang-format --dry-run -Werror is clean on all five .hpp/.cpp files that differ from upstream/main. The R suite passes (testthat::test_dir("tests/testthat"), 0 failures; also re-run with NOT_CRAN=true so the six skip_on_cran() tests actually execute — still 0 failures). The C++ suite passes after devtools::install() + devtools::clean_dll("./cpp11test"), 0 failures, including both the fork's external_pointer-C++ context and upstream's new template regression test.

🤖 Generated with Claude Code

https://claude.ai/code/session_01K8MneV8KqHYUuC8fWV3X5Q


Generated by Claude Code

DavisVaughan and others added 12 commits April 3, 2026 13:09
* Don't rely on transitive include of `"fmt/core.h"`

We got it through `cpp11/protect.hpp`, but we should not rely on that

* Correctly use `fmt::runtime()` on runtime strings passed to `fmt::format()`

In fmt, there is a `FMT_CONSTEVAL` macro that resolves to `consteval` on "new enough" C++ (otherwise it doesn't do anything). For R 4.6+, the default C++ used is finally "new enough" (`__cplusplus > 201703L`).

This causes all `fmt::format()` calls to require a constant expression for `const char*` and `std::string&` input, which we are not currently doing via `fmt_arg`.

We have a runtime provided string, which must now be wrapped in `fmt::runtime()`, which is what we should have been doing all along.

* Add `r_ns_env()` and use in `get_namespace()`

Throwing an informative (and tested!) error when we can't find the package namespace

* Define `RCPP_NO_R_HEADERS_CHECK` before all `#include <Rcpp.h>` usage

`#include <cpp11/R.hpp>` sets everything up the right way, and otherwise we get a warning from Rcpp which doesn't seem to end up being relevant for this use case

* Use `r_env_has()` + `r_env_get()`

To avoid triggering a NOTE about usage of `Rf_findVarInFrame3()` on R 4.5, where technically we had the tools to avoid that
* Teach `cpp_source()` how to source multiple files

* NEWS bullet

* Link to PR
…violations (r-lib#493)

* Add failing test

* Use tag types to generate attribute specific internals

* NEWS bullet

* Formatting
* Update `cran-comments.md`

* Increment version number to 0.5.5
Bring the fork up to date with r-lib/cpp11, keeping the fork's
fork-local changes and taking upstream's advances.

Conflicts resolved:

* R/vendor.R: kept the fork's `date` and `overwrite` arguments to
  `cpp_vendor()`, re-applied on top of upstream's Air-formatted shape.

* R/source.R: took upstream's version wholesale. Upstream's multi-file
  `cpp_source()` (r-lib#492) supersedes the fork's vectorization of `file`,
  and already carries the fork's "report the first missing file" fix.

* inst/include/cpp11/protect.hpp: took upstream's version wholesale.
  Upstream's tag-type ODR fix (r-lib#493) addresses the root cause of the
  `cpp11::warning()` unwind crash (r-lib#295) that the fork worked around by
  dropping the `const char*` overloads and copying the format string.

Also reformatted the fork's `[[deprecated]]` conversion operators in
inst/include/cpp11/sexp.hpp with clang-format; they were over the
90 column limit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K8MneV8KqHYUuC8fWV3X5Q
@krlmlr krlmlr closed this Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants