Evolution vignette and compat lab - #731
Draft
hadley wants to merge 7 commits into
Draft
Conversation
A manually-run harness (tools/evolution/) that verifies what happens to a downstream package when an upstream S7 package changes its generics or classes. Groundwork for the evolution vignette (#143).
vignette("evolution") explains how to change S7 generics and classes
without breaking downstream packages, from the perspective of an upstream
author. Every claim is verified by the compat lab in tools/evolution/,
which now covers 20 scenarios including generic moves, deprecating
wrappers, and NAMESPACE re-export vs binding-copy re-exports.
release_bullets() reminds us to re-run the lab before each release.
Spun off during verification: #726, #727, #728, #729, and the
abstract-parent gap reported on #717.
…s.Rmd Designing for evolution now leads the evolution vignette, since it's the part every upstream author should read even if they never change anything. The new_external_class() bullet moves to packages.Rmd: it's advice for the downstream package, not for the upstream author.
hadley
marked this pull request as draft
July 27, 2026 22:57
# Conflicts: # .Rbuildignore # .gitignore
Regenerates tools/evolution/results.md against the merged fixes and rewrites the affected sections: * Consistency checks between generic and method now only run in development contexts (#726, #728), so pkgB's users no longer see the warnings, and the two error cases surface at run time rather than blocking installation. * Moving a generic to another package now works for an already-installed pkgB (#729). * An abstract external parent can be subclassed (#717), so making a class abstract no longer breaks downstream subclasses. Also corrects the claim that a method's default wins over the generic's: dispatch passes on the generic's formals, so the generic's default is what methods actually receive.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #143.
Adds
vignette("evolution"): how to change your S7 generics and classes without breaking downstream packages, written from the perspective of the upstream author. It covers the design rules that make evolution cheap (leading section), how S7 couples packages (what runs at install vs load vs run time, and the generic–method formals contract), then works change-by-change through generics (add/remove argument, change default, rename, change dispatch, move to another package) and classes (add/remove/rename property, narrow a type, rename, make abstract), with a transition recipe for each.Every claim is verified by a new manually-run compat lab in
tools/evolution/: 20 scenarios that build real evoA/evoB package pairs, upgrade evoA, and record what breaks at evoB's install, load, test, andR CMD checkstages (results committed inresults.md, tempdir-scrubbed for clean diffs). Arelease_bullets()entry reminds us to re-run it before each release and reconcile the vignette.Notes for review:
...to parent constructor #717: subclassing scenarios usenew_external_class()asparent, and the lab results were generated against thedots-constructorbranch (--s7=flag). This shouldn't merge before Pass...to parent constructor #717 does.> **TODO:**linking the issue: Allow a package to be re-sourced while methods are out of sync with a changed generic #726 (graceful re-sourcing), Can't rename classes #727 (external-class alias resolution), Can't change default arguments #728 (default-change transition), Can't move generics to another package #729 (resolve_generic_opt()stale-load failure and re-export blindness), Can't deprecate generics #730 (deprecated_generic()), plus the abstract-parent gap reported in Pass...to parent constructor #717's review. Until those land,tools/evolution/results.mdrecords current behavior and the TODO'd passages record intent.gen <- pkgAcore::gen) splits a cross-package generic's methods table while a NAMESPACE re-export is transparent; test-time deprecation warnings leave downstreamR CMD checkclean.🤖 Generated with Claude Code