0.10.0 - 2026-09-15
Release Notes
This release adds three Linux targets, improves package and function lookup,
bounds serialized-data parsing, and refreshes the vendored typeshed to
r-typeshed 0.5.1. Core and the VS Code extension are 0.10.0.
Changed
- Treat 0.10.0 as the crates.io-publication boundary for the public
Scope
collection types (FxMap/FxSet), first changed at 0.9.2 (#340): no ry
crate has been published to crates.io at all, so no released consumer has
seen theHashMap/HashSetspellings. Rust consumers assigning standard
maps directly must convert their entries withinto_iter().collect()or
use the exposed types (#432). - Update sha2, serde, toml, and flate2 while retaining tree-sitter 0.26 and the
Rust 1.88 minimum. The tree-sitter 0.27 update remains separate (#404). - Document the remaining scalar-guard limits. The
assertion/alias/loop flow work remains open (#351).
Added
- Release binaries and VS Code extensions for 32-bit ARM Linux and Alpine Linux
on x64 and ARM64. The release matrix now covers nine platforms. - Explain source discovery with
ry check --explain-files. Use
include-build-ignoredinry.tomlto include selected build-ignored files
in both CLI checks and editor indexing (#363). - Refresh the vendored typeshed to r-typeshed 0.5.1 (base 0.0.18, tibble and
vctrs 0.0.2): new export inventories for tibble, scales, readr, checkmate,
httr, jsonlite, lifecycle, magrittr, stringr, and glue, so wholesale
imports and bare names from those packages resolve without installed
copies. Resolving the scales inventory clears the ggplot2 RY010
false-positive batch from both committed ecosystem ledgers.
Fixed
- Isolate the bodies of testthat's
test_that(),describe(), andit()
blocks in their own scope, matching their per-test evaluation
environment. Bindings in one block no longer shadow call heads in
sibling blocks, removing RY070 false positives in test files (#368). - Suppress RY020/RY021 for data.table select subscripts such as
dt[, -c("col")]and not-join forms likedt[!"key"]ordt[!list()]
when the receiver is not provably a base object. The selector role
follows the argument tag (j =,.SDcols =) rather than the
positional slot, and function or deferred bodies nested in a subscript
argument (callbacks,foreachbodies, data-mask walks) no longer
inherit the select-form license. Negative or negated
character subscripts on plain vectors, lists, and base data frames,
on non-selector arguments such asdrop =or a positionalby, and
outside subscript positions, still error (#367). - Resolve
x[i, j]index arguments against a data.table receiver's columns
before scope functions, covering data.table'si/j,:=targets,by,
.SDcols, and.SDpronouns. Unknown columns keep bare names opaque
instead of borrowing a function's type. Only data.table's[masks its
arguments: receivers classeddata.tableand opaque values (where unstubbed
data.table calls land). Base data frames, plain lists, and atomic vectors
evaluate their[arguments eagerly, as in R (#369). - Bundle set6 and dictionar6 export inventories so wholesale imports resolve
their R6 objects and functions without installed copies of those packages
(#366). Keep unrelated unknown names reportable. - Report invalid character conditions through literal assignments and aliases.
Discard literal facts across calls, forced promises, method effects, writes,
loops, and branch merges (#425). - Return RY001 warnings from the checker API, matching the rule table and CLI.
Keep RY002 length warnings when the condition also contains RY100 (#415). - Widen parameter defaults on the paths proved by compound
&&and||
type guards. This avoids false atomic$errors for caller-supplied lists
while preserving errors on paths the guard does not prove (#408). - Preserve possible function bindings from enclosing frames when an inner
assignment uses the same name. This avoids RY070 for outer constructors,
parameters, and unknown values that may be callable (#381). - Report failed top-level calls even when a later function definition has the
same name. Preserve outward package lookup and deferred function bodies
(#410). - Bind named data arguments before checking data-mask and tidy-select
expressions, regardless of their position in a call. Quoting helpers without
a data argument keep an unknown mask (#417). - Bound serialized-data parser nesting and materialized collection storage,
including metadata loaded in lazy mode. Keep cycle-safe deduplication and
the static liblzma build while updating the pinned parser to its 0.2.1 base
(#412, #433). Over-cap inventories still produce degraded scope notices;
unsupported or parser-limited files return empty, unflagged inventories. - Read literal C and C++ routine registration tables so registered symbols
also resolve through wrappers such as cleancall. Unknown registration forms
keep the existing fallback (#379). Refresh editor bindings when registration
sources change. - Discard forwarded-default facts after writes before wrapped or nested calls,
including replacement assignments, loop variables, and literalassign()
targets. Match backticked parameter and argument names consistently
(#407, #409, #411, #423, #424). Preserve local parameter defaults across
<<-and->>writes to enclosing bindings. - Retain provable union lengths through
c()and one-dimensional subsets of
classless members, including positive colon indices. Keep class information
unknown for opaque union members (#405, #416, #434). - Reject
max-serialized-bytesvalues outside 1 byte through 256 MiB. Bound the
serialized-inventory cache to 1,024 entries and refresh it after same-size,
same-mtime file replacements, including symlink aliases (#413, #427). - Report degraded serialized scopes in the language-server log. Honor positive
RAYON_NUM_THREADSvalues up to eight and parse inline if the index pool
cannot start (#414, #430). - Link liblzma statically so distributed binaries run without a system liblzma
library (#431). - Build and upload only the selected VSIX registry variant (#419).
- Keep RY105's dead-guard claims on sound length facts:
file.path()recycles
its arguments instead of always returning one path — and returns an empty
vector when any argument has zero length, unlikepaste(learnr, blogdown,
pkgload) — and the result length ofseq_len(n)is the value ofnrather
than its vector length (brulee). The paklength(sum(...)) > 0true
positive is retained (#377). - Honor
length(x) == 1 && ...guards inside packages, where the bare
lengthsymbol resolves through the package search path and the guard
exclusion was previously dead code; the 0.9.0 472-package audit measured
46 such guard warnings, all false positives, and both committed ecosystem
ledgers drop 14 reviewed false-positive identities of this shape. The
guard is proven before it is honored: a provably classed parameter, a
scalar parameter default (which only describes the omitted-argument call
shape), any project-registered, defined, or importedlength.*S3
method, or a reassignment inside the guarded operand keeps the warning
(#372). - Demote lexical value bindings under the data.table
[columns-first mask,
the value-binding analogue of #369: a column shadows a same-named enclosing
value at runtime, sodat[month == "a"]no longer types the comparison
against the lexicalmonth. Callback formals,jargument names, and the
mask pronouns bind inside the mask and keep their typing (#457). - Keep
!!!splice and!!name :=injection sites RY021-clean through
resolvable dynamic-dots constructors: the vendored tibble and vctrs
inventories declareinjectionmetadata for their quos()- and
list2()-based constructors (r-typeshed 0.5.1). A resolvable entry without
dots-semantics metadata is strictly worse than no entry — it suppresses
the unresolved-callee injection fallback — so ggplot2's
data_frame0 <- function(...)forwarder turned five previously clean
splice sites into false RY021 once the tibble inventory resolved the name
(found in this release's vendor-sync corpus run). - Type leading-dot magrittr chains (
. %>% f,. %T>% f) as functional
sequences: the dot is the chain's parameter, so the chain types as a
function value instead of flagging the placeholder as unbound, and%<>%
no longer rebinds the placeholder. The native pipe has no such form:_
left of|>stays an ordinary unbound name.
Install ry-cli 0.10.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/sims1253/ry/releases/download/v0.10.0/ry-cli-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/sims1253/ry/releases/download/v0.10.0/ry-cli-installer.ps1 | iex"Download ry-cli 0.10.0
| File | Platform | Checksum |
|---|---|---|
| ry-cli-aarch64-apple-darwin.tar.gz | Apple Silicon macOS | checksum |
| ry-cli-x86_64-apple-darwin.tar.gz | Intel macOS | checksum |
| ry-cli-aarch64-pc-windows-msvc.zip | ARM64 Windows | checksum |
| ry-cli-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| ry-cli-aarch64-unknown-linux-gnu.tar.gz | ARM64 Linux | checksum |
| ry-cli-x86_64-unknown-linux-gnu.tar.gz | x64 Linux | checksum |
| ry-cli-armv7-unknown-linux-gnueabihf.tar.gz | ARMv7 Linux | checksum |
| ry-cli-aarch64-unknown-linux-musl.tar.gz | ARM64 MUSL Linux | checksum |
| ry-cli-x86_64-unknown-linux-musl.tar.gz | x64 MUSL Linux | checksum |