[pull] master from ruby:master#994
Merged
pull[bot] merged 34 commits intoturkdevops:masterfrom May 8, 2026
Merged
Conversation
Previously, we kept around `PatchPoint`s after patching them for several kinds of invariants. That wasted compute since repeated invalidation with the same key patched a growing list of patchpoints each time, making it accidentally O(n^2). Retaining the patchpoints also used memory. Some invariants, such as rb_zjit_invalidate_no_singleton_class() and rb_zjit_invalidate_root_box(), already remove from the table. This commit makes all invariants remove from the table.
The ripper translator is a good resource when porting ripper usage over to prism A few places use `visit_token` when it can be more specific. A call operator for example can ever only be one of three things. A positional argument can only ever be a identifier (no constant, no global, etc.) Also removes some stale comments. There are `*_TargetNode` for these now. ruby/prism@62511d59a2
This would allow rb_gc_event_hook to run in a GC thread that is a non-Ruby thread.
…les ($! and $@) Ruby::Box fix stale cached values for exception-related global variables ($! and $@) The exception-related virtual variables $! (current exception) and $@ (its backtrace) are stored on the execution context (ec->errinfo and the rescue/ensure frame's local slot accessed via errinfo_place), not in box->gvar_tbl. Caching their values in box->gvar_tbl makes the second read return a stale value from the previous raise/rescue: ``` begin; raise "first"; rescue; p $!; end begin; raise "second"; rescue; p $!; end # before: #<RuntimeError: first> / #<RuntimeError: first> # after: #<RuntimeError: first> / #<RuntimeError: second> ``` ``` begin; raise "first"; rescue; p $@.first; end begin; raise "second"; rescue; p $@.first; end # before: same backtrace returned for both # after: distinct backtrace per raise ``` Fixes [Bug #21991](https://bugs.ruby-lang.org/issues/21991) Related PR: #16303
To the code where they are actually initialized.
…ault Add the recent developer meeting, we discussed switching from using pessimistic versioning by default to using optimistic versioning by default. This is the a step in that direction. It makes bundle add without a explicit version given to use >= (optimistic) instead of ~> (pessimistic). With this, the bundle add --optimistic option is now ignored, since the behavior is now the default. This add a --pessimistic option to set a pessimistic version. ruby/rubygems@eed378086b
Definition#apply_override_to, Definition#converge_dependencies, and Resolver#apply_overrides each duplicated the same find expression. Centralizing it on Override prepares for upcoming fields (and the :all target) without repeating the predicate in every call site. ruby/rubygems@0c4424d5f3 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…uation time Before this change, `override "rails", version: "not a version"` was accepted by Bundler::Dsl#override and only failed later when the resolver tried to instantiate Gem::Requirement. Surface the error at the Gemfile evaluation step so the user sees it on the offending line. ruby/rubygems@2ae83fbb4f Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ockfile Lock the byroot policy decision (overrides are a Gemfile concept and must not be serialized into Gemfile.lock) with a regression test, so a future change that starts emitting override metadata in the lock would fail loudly. ruby/rubygems@9524b785c5 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rsion overrides Extend the override DSL whitelist so per-gem metadata fields can be declared. The :all target is rejected for now with a "not yet supported" error so the field is purely per-gem until the next step adds :all propagation. ruby/rubygems@f9e4d7bf29 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a spec's runtime dependencies are gathered for the resolver, its required_ruby_version / required_rubygems_version metadata flow as synthetic Ruby\0 / RubyGems\0 dependencies. Rewrite those before they reach the dependency hash so per-gem overrides on those fields take effect during resolution. ruby/rubygems@853e00f778 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The per-dep loop in converge_dependencies only knows about version: overrides via apply_override_to + matches_spec?. Metadata overrides on direct deps were therefore invisible to lockfile change detection and would silently no-op against an existing lock. Extend converge_overrides_outside_dependencies to also unlock direct deps when the override targets a non-version field. ruby/rubygems@fdd4c30523 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…sion overrides Add integration coverage exercising :ignore_upper and nil overrides against per-gem metadata fields, transitive propagation, and lockfile re-resolution when a metadata override is added against an existing lockfile. The cases drive `bundle lock` so they exercise the resolver without RubyGems' install-time required_ruby_version gate, which is addressed in a later step. ruby/rubygems@ec3a549df7 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Remove the temporary "not yet supported" guard so a Gemfile may write `override :all, required_ruby_version: :ignore_upper` and similar forms. The version: ban for :all stays — version requirements are inherently per-gem. ruby/rubygems@af09f0360a Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Override.find_for now returns the per-gem entry when present and otherwise the matching :all entry on the same field. This is the single dispatch point for overrides in Definition and Resolver, so the fallback is what wires :all into resolution and lockfile change detection without further plumbing. ruby/rubygems@ef24b4eef9 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…sent An :all override applies to every gem's metadata, so we have no way to know which locked entries it affects without re-resolving. Force-unlock them all when an :all override appears so the resolver gets a fresh chance to apply the override. ruby/rubygems@4f61f6813e Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Exercise :all required_ruby_version overrides applied to multiple gems at once, the per-gem precedence rule, and re-resolution against an existing lockfile when an :all override is introduced. ruby/rubygems@81f2bfcf9b Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
matches_current_ruby? / matches_current_rubygems? now look up the current Definition's overrides via Bundler.overrides and apply them before checking against the runtime Ruby/RubyGems version. This covers Installer#ensure_specs_are_compatible! and the materialize- layer choose_compatible / SpecSet#valid? checks uniformly without plumbing overrides through every materialization site. When no Definition is set yet (e.g. RubyGems-side calls outside a Bundler.definition block), Bundler.overrides returns an empty list and the methods fall through to their original behavior. ruby/rubygems@afe9313b6e Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drive bundle install end-to-end with a gem whose required_ruby_version or required_rubygems_version excludes the current runtime, asserting that a per-gem override (and an :all override) makes the install succeed instead of erroring at the install-time compatibility gate. ruby/rubygems@dbc9f24269 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bundler::Dsl#override now records caller_locations(1, 1).first on each Override so the originating Gemfile line can be surfaced in later diagnostics. ruby/rubygems@ef73385cdc Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Append the list of currently active overrides (with Gemfile location, when known) to the SolveFailure message so a user investigating a "could not find compatible versions" error sees what override changed the constraint set instead of being misled by the resolver-reported requirement. ruby/rubygems@10b8b53270 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Update the OVERRIDE section to cover the :all target, the required_ruby_version / required_rubygems_version fields, and the diagnostic shown on resolve failure. ruby/rubygems@ac90c83b1b Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ler global Phase 2.C wired overrides into MatchMetadata via Bundler.overrides, a process-wide accessor read every time a spec answered matches_current_metadata?. That leaked the user's Gemfile overrides into Bundler-internal callers like SelfManager#remote_specs, where overrides have no business: a Gemfile override could let bundle self-update consider Bundler releases that are actually incompatible with the running Ruby/RubyGems. Revert MatchMetadata's matches_current_ruby? and matches_current_rubygems? to evaluate the spec's own metadata, and add explicit matches_current_*_with_overrides? variants. Pass overrides explicitly: Installer#ensure_specs_are_compatible! gets them from @Definition, LazySpecification#choose_compatible reads its newly-added @OVERRIDES attribute, and SpecSet#valid? reads @OVERRIDES set on the SpecSet. Definition propagates @OVERRIDES to the SpecSets it constructs and to the LazySpecs they contain. SelfManager and other callers that should keep evaluating real gemspec metadata reach the strict path unchanged. ruby/rubygems@e0ff753bbb Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously, any :all override called unlock_all_locked_specs_for_override which pushed every locked spec into @gems_to_unlock. A user adding a narrow `override :all, required_ruby_version: :ignore_upper` thus paid for a full re-resolve that could pull unrelated dependency upgrades/downgrades. Make :all overrides leave the lockfile alone at converge time. They take effect on a fresh resolution (no lockfile) or when the user opts in via `bundle update`. Per-gem overrides retain their unlock for the named gem since the user explicitly named the target. ruby/rubygems@3c95ab99e3 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…reuse paths Definition#resolve falls back to an existing lockfile when nothing about the Gemfile or the locked deps changed. The two SpecSet rebuild paths (deleted_deps subset and the redundant-platform-specific-gems fallback) constructed fresh SpecSet instances without carrying @OVERRIDES forward, so any LazySpec produced from them lost its override context. After Step G that mattered: an :all metadata override does not pre-unlock anything by design, which means it must flow through these reuse paths intact. Without it, the materialize layer either silently re-resolved (which churns the lockfile) or, on the install-time check, fell back to the spec's strict required_ruby_version metadata. Calling with_overrides on both rebuilt SpecSets keeps the install-time behavior consistent across resolve and lockfile-reuse paths. ruby/rubygems@81fb91a8b1 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tion set SpecSet#incomplete_specs_for_platform constructed a fresh self.class.new(@specs) for platform validation but never copied @OVERRIDES. Platform-validity decisions therefore evaluated strict required_ruby_version / required_rubygems_version metadata even when resolution was running with overrides, so a metadata override could allow a gem everywhere except platform validation, where the platform might be marked incomplete and pruned. Carry @OVERRIDES forward via with_overrides on the cloned SpecSet. ruby/rubygems@11b7c58a5a Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…Spec overrides SpecSet#with_overrides cascaded into each contained spec via `respond_to?(:overrides=)`. RemoteSpecification#respond_to? forwards to _remote_specification, which materializes the backing gemspec just to answer the predicate. spec/runtime/require_spec.rb verifies that Bundler does not load gemspecs it does not need by deliberately poisoning one with `raise 'broken gemspec'`; the cascade tripped that guard and made `Bundler.setup` blow up. Gate the cascade on `is_a?(LazySpecification)` instead. Only LazySpecification declares `attr_accessor :overrides` (used by `#choose_compatible`), so the predicate is equivalent for any spec we ever set overrides on, and it never triggers the lazy gemspec load. ruby/rubygems@2a1e7d5c23 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SpecSet previously kept its own @OVERRIDES and a with_overrides setter that had to be chained on every SpecSet.new(...) site (~13 sites in Definition alone). Two Codex review rounds both flagged forgotten chains in different SpecSet construction paths, which is exactly the class of bug the chain pattern invites: it is purely "remember to write" with no compiler help. Move the override list to LazySpecification#overrides instead. The LazySpec is the natural carrier — it is the value object the resolver and install paths already pass around, and choose_compatible already read overrides off it. Override.attach(specs, overrides) is added as the dual of Override.find_for so Definition (after lockfile load) and Resolver (after solve_versions) can populate the overrides on every LazySpec they hand out, and LazySpecification.from_spec carries the list forward when one LazySpec spawns another. Generic spec types (StubSpecification, plain Gem::Specification, RemoteSpecification) are intentionally ignored so generic metadata callers (SelfManager, materialize-time strict checks) keep their current strict semantics. SpecSet drops attr_accessor :overrides, the @OVERRIDES initialisation, the with_overrides cascade, and reverts SpecSet#valid? to the strict matches_current_metadata? check. Every SpecSet.new(...) site in Definition stops chaining .with_overrides — the LazySpecs already carry the context. ruby/rubygems@fc1e8d4d7e Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
complete_platform validates platform-specific candidates returned by spec.source.specs.search, which are remote specs that do not carry the override list. Borrow the override list from the LazySpec exemplar already in scope so platform-variant validation uses the same effective metadata as the install/resolve path. Also propagate the overrides onto the synthesized LazySpec built from platform_spec. Without this, the next complete_platform call could pick the synthesized variant as its exemplar (it is now in the set returned by lookup) and fall back to strict matching, dropping platforms that the user's override would otherwise allow. ruby/rubygems@205955c5b3 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )