Skip to content

Support the S7 class reference of S7 > 0.2.1 - #739

Merged
moodymudskipper merged 7 commits into
mainfrom
b-s7-class-ref-env
Oct 19, 2026
Merged

moodymudskipper merged 7 commits into
mainfrom
b-s7-class-ref-env

Conversation

@moodymudskipper

@moodymudskipper moodymudskipper commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes the rcc-dev: S7 failure on #733 (segfault in test-s7-S7_generic.R).

What changed in S7: the development version (0.2.2.9000, RConsortium/S7#742) stores an object's class in a _S7_class attribute, generally a shared S7_class_ref environment (stored as .S7_class_ref in the class's environment) whose $class is the class, plus _S7_version, instead of the S7_class attribute. Classes gain S7_class_name, S7_dispatch and S7_version attributes, and new_class() wraps the constructor's environment into a new one holding .S7_class_ref.

Fix — the installed S7 version decides, through with_versions(S7 > "0.2.2"):

  • s7_class(x) reads _S7_class (dereferenced) or S7_class; s7_internal_attrs() gives the attributes to ignore
  • has_foreign_s7_attrs(x): objects/generics built by an S7 version storing the class differently are corrupted (S7_object, S7_generic, ggplot2 S7 classes, ellmer types) and fall back to low-level construction, which rebuilds them exactly
  • is_corrupted_S7_class() does the same for classes (env wrapper / S7_version); new_class construction passes the original constructor env with S7 > 0.2.2
  • New "S7_class_ref" constructor (opts_S7_class_ref()): environment(<class code>)$.S7_class_ref, instead of an environment address; corrupted with S7 <= 0.2.2

Tests: version-specific outputs split with with_versions() at 0.2.2 (current CRAN). New S7_class_ref test, and foreign-structure cases in the S7_object tests for both versions.

Tested locally, full suite: 0 failures with S7 0.2.1 and 0.2.2.9000; S7/ggplot2/ellmer tests also with 0.2.2.

🤖 Generated with Claude Code

moodymudskipper and others added 7 commits October 19, 2026 00:50
The development version of S7 (0.2.2.9000, RConsortium/S7#742) stores
an object's class in a "_S7_class" attribute, generally a shared
"S7_class_ref" environment, along with "_S7_version", instead of the
"S7_class" attribute. Classes gain "S7_class_name", "S7_dispatch" and
"S7_version" attributes, and `new_class()` wraps the constructor's
environment into a new one holding the reference.

Our S7, ggplot2 and ellmer constructors read `attr(x, "S7_class")` and
ignored only that attribute, so with dev S7 the output fell back to
low-level code, and constructing a generic repaired "_S7_class" with an
environment address, which segfaulted under testthat's placeholder
address.

* `s7_class()` gets the class from either attribute, and
  `s7_internal_attrs` lists the attributes S7 sets itself, used in the
  ignore lists that listed "S7_class"
* `new_class()` calls get the original constructor environment
* `S7_object()` doesn't repair the "_S7_version" it sets

Tests whose output legitimately differs (low level "next" constructions,
base classes redefined in S7) are split by S7 version, the snapshots for
S7 <= 0.2.1 are unchanged.
Instead of calling S7::S7_object() during construction to find out
which "_S7_version" it sets, we check the S7 version and compare to
the value set since S7 0.2.2.9000 (1L).
The class reference ("_S7_class", "_S7_version") is only in the
development version of S7 (0.2.2.9000). S7 0.2.2 is on CRAN and still
uses the "S7_class" attribute, but the tests and the version check of
the S7_object constructor used 0.2.1 as threshold, so CI (S7 0.2.2)
ran the blocks meant for the development version. Also removes the
snapshots CI committed from these runs.
The repair functions ignored "S7_class", "_S7_class" and "_S7_version"
whatever the S7 version, but each version's constructors only set one
set, so an object carrying the other version's attributes would have
lost them. s7_internal_attrs() now depends on with_versions(S7 > "0.2.2"),
and so do the class attributes ignored by the "new_class" constructor.
The arguments of S7 object constructors still drop all three.
Read the class and check attributes according to the installed S7 version
with with_versions(), consider S7 objects built by an S7 version storing the
class differently as corrupted, and construct the "S7_class_ref" of S7 > 0.2.2
from its class rather than from a memory address.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 59.18367% with 40 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.30%. Comparing base (3107494) to head (56ca584).

Files with missing lines Patch % Lines
R/s7-S7_class_ref.R 0.00% 16 Missing ⚠️
R/s7-S7-object.R 16.66% 15 Missing ⚠️
R/s7-elmer_TypeEnum.R 0.00% 3 Missing ⚠️
R/s7-S7_class.R 86.66% 2 Missing ⚠️
R/s3-ggplot2-ggplot2-labels.R 50.00% 1 Missing ⚠️
R/s3-ggplot2-ggplot2-mapping.R 50.00% 1 Missing ⚠️
R/s3-ggplot2-ggplot2-margin.R 50.00% 1 Missing ⚠️
R/s3-ggplot2-ggplot2-theme.R 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #739      +/-   ##
==========================================
- Coverage   82.53%   82.30%   -0.24%     
==========================================
  Files         230      231       +1     
  Lines        8692     8730      +38     
==========================================
+ Hits         7174     7185      +11     
- Misses       1518     1545      +27     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@moodymudskipper
moodymudskipper merged commit c4315fe into main Oct 19, 2026
6 of 8 checks passed
@moodymudskipper
moodymudskipper deleted the b-s7-class-ref-env branch October 19, 2026 09:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant