Skip to content

[pull] master from ruby:master#1213

Merged
pull[bot] merged 47 commits into
turkdevops:masterfrom
ruby:master
Jul 15, 2026
Merged

[pull] master from ruby:master#1213
pull[bot] merged 47 commits into
turkdevops:masterfrom
ruby:master

Conversation

@pull

@pull pull Bot commented Jul 15, 2026

Copy link
Copy Markdown

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 : )

tekknolagi and others added 30 commits July 14, 2026 13:05
The first version of the inliner used the "high water mark" of HIR
instructions ever allocated. This PR estimates the number of live
instructions that we care about in `infer_types`. When inlining, it
also bumps the estimate by the delta of new HIR instructions from
inlining the callee.

`infer_types` is somewhat arbitrarily chosen because it runs
frequently between other passes and I don't want a whole other
pass.

Result: slightly different inlining behavior. On Lobste.rs, we go from
~5400 inlining rejected due to budget down to ~3900.
When gc_move relocates an object to a different slot size,
rb_gc_obj_changed_slot_size may re-embed it: the fields move from the
fields_obj into the object itself and the object references them
directly.  The write-barrier history for those (possibly young) values
lived on the discarded fields_obj, so an old unremembered object then
violates the O->Y invariant, which gc_verify_internal_consistency
reports as a WB miss.  Remember the object on such moves.

Remembering inside rb_gc_obj_changed_slot_size (as #17866 tried) does
not work for this path: gc_move calls it before the destination's age
bits are restored, so RVALUE_OLD_P is false there, and gc_move
overwrites the destination's remembered bits afterwards anyway.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ZJIT: Fold defined?(yield) when inlining method with blockiseq

We know this statically.

* ZJIT: Fold negative case of defined?(yield) too

Leave handling non-blockiseq arguments for later (right now they should
never appear in SendDirect instructions).
It tells you total size per symbol, average size per instance of symbol,
and total count per symbol.

Can be used with `--zjit-perf=hir`:

```
plum% ruby ../tool/zjit_analyze_perf_map_size.rb /tmp/perf-16653.map
12.1 MB total; 277.5 B each side-exit
2.2 MB total; 16.9 B each PatchPoint
2.1 MB total; 197.4 B each SendDirect
1.3 MB total; 10.7 B each PadPatchPoint
973.6 KB total; 56.5 B each GuardType
952.6 KB total; 97.7 B each HasType
910.4 KB total; 111.2 B each Send
705.0 KB total; 218.0 B each CCallWithFrame
689.9 KB total; 149.0 B each PushInlineFrame
559.8 KB total; 247.5 B each CCallVariadic
440.4 KB total; 32.0 B each EntryPoint
387.9 KB total; 17.8 B each CheckInterrupts
356.8 KB total; 66.7 B each GetIvar
326.3 KB total; 11.0 B each Jump
198.2 KB total; 8.0 B each CondBranch
167.6 KB total; 22.3 B each Return
163.5 KB total; 4.8 B each LoadField
149.0 KB total; 23.6 B each IsBitEqual
142.4 KB total; 100.0 B each HashAref
135.9 KB total; 16.3 B each Test

138705 PatchPoint
128879 PadPatchPoint
124942 Snapshot
45884 side-exit
40535 Const
34701 LoadField
30364 Jump
25234 CondBranch
22264 CheckInterrupts
17657 GuardType
16101 LoadArg
14081 EntryPoint
12892 RefineType
11106 SendDirect
9980 HasType
8541 Test
8385 Send
7693 Return
6938 GuardBitEquals
6699 LoadSelf
plum%
```

or with just `--zjit-perf`:

```
plum% ruby ../tool/zjit_analyze_perf_map_size.rb /tmp/perf-22517.map
770.7 KB total; 192.7 KB each _app_views_stories__listdetail_html_erb__2872691580871714137_14696@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/stories/_listdetail.html.erb:1
452.0 KB total; 150.7 KB each _app_views_layouts_application_html_erb__3422508349557286544_14376@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/layouts/application.html.erb:1
232.9 KB total; 232.9 KB each _app_views_comments__comment_html_erb___3513273811879470227_16232@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/comments/_comment.html.erb:1
200.9 KB total; 50.2 KB each block-in initialize@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/erubi-1.13.1/lib/erubi.rb:135
194.0 KB total; 64.7 KB each parse@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/tzinfo-2.0.6/lib/tzinfo/data_sources/zoneinfo_reader.rb:345
191.8 KB total; 191.8 KB each _app_views_comments__comment_html_erb___3513273811879470227_15016@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/comments/_comment.html.erb:1
167.4 KB total; 167.4 KB each _app_views_comments__comment_html_erb___3513273811879470227_16488@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/comments/_comment.html.erb:1
165.9 KB total; 165.9 KB each _app_views_stories__listdetail_html_erb__2872691580871714137_15008@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/stories/_listdetail.html.erb:1
124.3 KB total; 31.1 KB each build_arel@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/relation/query_methods.rb:1751
120.9 KB total; 30.2 KB each _delegator_method@/Users/emacs/.rubies/ruby-zjit-rel-stats/lib/ruby/4.1.0+4/forwardable.rb:202
119.5 KB total; 29.9 KB each perform_query@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/connection_adapters/sqlite3/database_statements.rb:87
111.6 KB total; 55.8 KB each _app_views_stories_show_html_erb__2313005407901203172_15000@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/stories/show.html.erb:1
103.8 KB total; 25.9 KB each block-in generate@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activesupport-8.1.1/lib/active_support/delegation.rb:72
98.3 KB total; 98.3 KB each _app_views_users_show_html_erb___3973630128665404112_14592@/Users/emacs/Documents/code/yjit-bench/benchmarks/lobsters/app/views/users/show.html.erb:1
91.0 KB total; 45.5 KB each normalize_options@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/bundler-4.0.12/lib/bundler/dsl.rb:394
85.9 KB total; 21.5 KB each parse@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/tzinfo-2.0.6/lib/tzinfo/data_sources/posix_time_zone_parser.rb:37
74.5 KB total; 37.3 KB each generate@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activesupport-8.1.1/lib/active_support/delegation.rb:22
69.0 KB total; 17.3 KB each determine_template@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/actionview-8.1.1/lib/action_view/renderer/template_renderer.rb:17
67.5 KB total; 16.9 KB each block-in expand_from_hash@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/relation/predicate_builder.rb:88
65.2 KB total; 16.3 KB each block-in derive_offsets@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/tzinfo-2.0.6/lib/tzinfo/data_sources/zoneinfo_reader.rb:118

17 __callbacks@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activesupport-8.1.1/lib/active_support/callbacks.rb:70
12 _layout@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/actionview-8.1.1/lib/action_view/layouts.rb:329
5 __callbacks=@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activesupport-8.1.1/lib/active_support/callbacks.rb:70
5 default_url_options@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/actionpack-8.1.1/lib/action_dispatch/routing/url_for.rb:100
4 scope@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/associations/association.rb:108
4 default_render@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/actionpack-8.1.1/lib/action_controller/metal/implicit_render.rb:38
4 scope@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/associations/association_scope.rb:22
4 get_method_for_class@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/actionpack-8.1.1/lib/action_dispatch/routing/polymorphic_routes.rb:348
4 visit_Arel_Nodes_SqlLiteral@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/arel/visitors/to_sql.rb:755
4 block-in preprocess_order_args@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/relation/query_methods.rb:2105
4 strictly_lower?@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/bundler-4.0.12/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb:179
4 choose_compatible@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/bundler-4.0.12/lib/bundler/lazy_specification.rb:236
4 column_types@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/result.rb:168
4 local_search@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/bundler-4.0.12/lib/bundler/index.rb:65
4 method_defined_within?@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/attribute_methods.rb:187
4 join_scopes@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/reflection.rb:227
4 block-in expand_from_hash@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/relation/predicate_builder.rb:88
4 block-in convert_dot_notation_to_hash@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/relation/predicate_builder.rb:166
4 block-in references@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/activerecord-8.1.1/lib/active_record/relation/predicate_builder.rb:29
4 block-in materialize_dependencies@/Users/emacs/.gem/ruby/ruby-zjit-rel-stats/gems/bundler-4.0.12/lib/bundler/spec_set.rb:246
plum%
```
That attribute is C++23, not C23

ruby/prism@5e4f45712e
rb_vm_opt_getconstant_path() asserts on an inline constant cache hit that
the cached value equals a freshly recomputed constant chain:

    VM_ASSERT(val == vm_get_ev_const_chain(ec, segments));

On a non-main ractor an IC hit is only allowed for shareable values
(IMEMO_CONST_CACHE_SHAREABLE). Reassigning a shareable constant is legal
from a non-main ractor, and it invalidates ICs asynchronously via
rb_clear_constant_cache_for_id() (ic->entry = NULL) without locking the
reader side. So the hit path can load a still-valid, previously-assigned
shareable value while another ractor concurrently reassigns the constant;
the subsequent recomputation then observes the newer value and the two
legitimately differ (a benign TOCTOU). Both values were validly assigned
to the constant at some point, so no correctness or memory-safety issue
results -- only this debug-only assertion trips.

Guard the equality check with rb_multi_ractor_p(), mirroring the existing
workaround in vm_cc_invalidate() (vm_callinfo.h). Reproducible with several
ractors reassigning the same frozen constant in a loop; NDEBUG builds are
unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
pow5mult's b_cache publishes new cache nodes with ATOMIC_PTR_CAS (release),
but both readers -- the fast-path check and the recheck before allocating --
were plain loads racing with that CAS: a data race in the C11 sense, and
what TSan reports as `race:pow5mult` under parallel Ractor float<->string
conversion. Harmless on current targets (the reader dereferences through
the loaded pointer, so address dependency orders the accesses), but easy
to make formally correct: read the cache head/next through
RUBY_ATOMIC_PTR_LOAD. The lock-free CAS scheme is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Doing it in `rb_gc_obj_changed_slot_size` is wrong as the object
could still be moved back because of `invalidate_moved_plane`.
Followup: #17631

Now that complex `RObject` always have an IMEMO/fields, we no
longer need to have an external `st_table` to replicate the
memory layout of `RObject`.
By handling complex shapes in `rb_shape_rebuild` we can merge
the two complex cases (when `src` is complex and when `dest`
becomes complex).
It used to be that multiple paths would need to clear
the generic ivar reference, but it's no longer the case.
Share more code with `rb_copy_generic_ivar`.
Now share more code between the various cases:

  - Whether to copy all fields or just ivars
  - Whether to add or remove some capacity.
The layout is shared by T_DATA objects and overflowed RObjects, so name the Rust variant after SHAPE_ID_LAYOUT_EXTENDED rather than one of its users.
Directly update existing instance variables in the fields object used by overflowed RObjects. Keep shape-changing writes on the generic path so the owner and fields object retain their private layout and capacity bits.
Lightweight frames need C code to use CFP_ISEQ(...).
Match YJIT by checking interrupts only on backward jump, branchif, branchunless, and branchnil instructions. Forward branches cannot form loops and do not need polling.
…TION

The global method cache was removed by b9007b6
for Ruby 3.0 [Feature #16614], and OPT_UNIFY_ALL_COMBINATION lost its
last consumer when the old insns2vm was replaced by tool/ruby_vm in 2017.
Nothing reads these macros anymore.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
gmp is enabled by default and setup/macos passes --with-gmp-dir to
every job, so the plain check job already links -lgmp and the dedicated
--with-gmp job duplicated it. Trims one of ten macOS jobs per event
against the org-wide macOS concurrency cap of 50.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The dedicated cargo job occupied a runner from the org-wide macOS
concurrency pool of 50 for less than a minute of work. Run the Rust
unit tests as steps of the --enable-yjit entry instead, which stays
shorter than the --enable-yjit=dev long pole. The steps are guarded
with !cancelled() so a Ruby-side test failure does not mask the Rust
result.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The full macOS fan-out (10 jobs, about 117 runner-minutes) repeats
test tasks that macos.yml already runs from the git tree on every
event; what is tarball-specific is only that the packaged tarball
configures, builds and installs. Run a single check on macos-26 for
pull requests and pushes, and keep the full matrix for
workflow_dispatch, which is how the nightly schedule and release
verification invoke it. Only macOS is trimmed: its org-wide
concurrency pool of 50 runners saturates during peak hours and has
been delaying release jobs, while Linux and Windows share a pool with
headroom.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was by far the heaviest bundler spec file (~2500 example-seconds
on Windows). Parallel spec runs distribute work per file, so a single
huge file caps the achievable wall-clock time. Move its describe
blocks verbatim into three files, keeping example count and structure
unchanged.

ruby/rubygems@a50eb931e5

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Its before(:context) shard warning fires on every run since the file
was added without a shards.rb entry.

ruby/rubygems@f9879f9015

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Recorded per-file runtimes show outdated_spec.rb, newgem_spec.rb and
update_spec.rb each exceed the ideal per-worker load of a parallel
run, and setup_spec.rb dominates standalone runs, so file-based
distribution cannot go faster without splitting them. Blocks move
verbatim and example sets are unchanged. newgem's shared examples move
together with their consumers, with its top-level helpers duplicated
into both files.

ruby/rubygems@5d40766029

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
BSD/OS was discontinued in 2003 and the bsdi* target has been
unbuildable for decades. This also removes the BROKEN_SETREUID and
BROKEN_SETREGID fallbacks in process.c, which no other platform
ever defined.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…afely

Same relaxation as PR #17873: another ractor can invalidate a cc
(klass = Qundef) while a call using it is in flight; cme_/call_ stay
intact, so the call proceeds with the method resolved before the
redefinition (same treatment as vm_cc_invalidate).

Route the check through VM_CC_RACED_P(), which extensions see as a
constant: ext/objspace/objspace_dump.c includes vm_callinfo.h and calls
vm_cc_cme, and with assertions enabled at -O0 (--enable-yjit/zjit=dev on
macOS) a direct rb_multi_ractor_p() there materializes references to the
core-internal globals ruby_current_vm_ptr / ruby_single_main_ractor,
which are hidden from extensions -- objspace.bundle then fails to load
("symbol not found in flat namespace '_ruby_current_vm_ptr'", the five
JIT-dev CI failures on #17873). At -O1+ the compiler proves the first
disjunct from the caller's Qundef guard and dead-codes the call, which
is why only the -O0 dev jobs saw it. Verified both ways on the
objspace_dump.c TU: PR state at -O0+RUBY_DEBUG has both unresolved
globals; with VM_CC_RACED_P() it has none.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bumps the github-actions group with 1 update in the / directory: [ruby/setup-ruby](https://github.com/ruby/setup-ruby).


Updates `ruby/setup-ruby` from 1.316.0 to 1.318.0
- [Release notes](https://github.com/ruby/setup-ruby/releases)
- [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb)
- [Commits](ruby/setup-ruby@d45b1a4...8e41b36)

---
updated-dependencies:
- dependency-name: ruby/setup-ruby
  dependency-version: 1.318.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Gem::Source#fetch_spec built the local spec cache path directly from the
name tuple returned by a remote index, which is never validated for use
as a path component. A crafted gem name containing path separators or
`..` could therefore make fetch_spec write the downloaded gemspec bytes
outside Gem.spec_cache_dir. Reject any spec name that is not a plain
basename before constructing the cache path.

ruby/rubygems@56ed326cb2

Co-Authored-By: Claude <noreply@anthropic.com>
Track explicit lengths while parsing command strings and comparing the
current directory. This avoids relying on Ruby string terminators and
makes separators in the generated argument buffer explicit.
nobu and others added 17 commits July 15, 2026 13:28
Compare compiler attribute names using Ruby string lengths.  Share
attribute handling between the compiler paths to keep their behavior
aligned.
Restore hidden operand strings and arrays with their dedicated
resurrection functions so inspection preserves all contents.
Use the message length when looking for the receiver placeholder
instead of requiring a NUL-terminated string.
Search only the gethostname buffer for its terminator so resizing the
Ruby string does not read beyond the returned data.
Move the local fallback out of string.c so other source files can use
memrchr on platforms that do not provide it.
Search and compare feature extensions within the Ruby string length so
require does not rely on a terminator while classifying paths.
Create system errors from the filepath VALUE so the full path is
retained without relying on a NUL terminator or a separate GC guard.
The Hash#[] and Array#product examples referenced undefined variables,
the StringIO doc named a nonexistent File::RDRW constant, and
Pathname#mkpath's call-seq advertised a positional permissions
argument that the keyword-only implementation does not accept.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Set#include? built its receiver from an Array literal, so the
`hash`/`eql?` semantics the surrounding text describes did not apply.
Set#each wrote `sum => 6`, which is a rightward-assignment pattern
match rather than an output comment.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add Proc#refined(mod, ...), which returns a new Proc that behaves like
the receiver but with the refinements activated by the given modules in
effect inside its body, without affecting the original Proc.  This is
an alternative to the previously proposed Proc#using
(https://bugs.ruby-lang.org/issues/16461) that does not modify the
existing block and needs no `using Proc::Refinements` declaration.

Refinements are resolved at run time through the cref, so a refined
proc gets two pieces of its own:

* A cref carrying the additional refinements, built by activating the
  modules (rb_using_module_recursive, under the VM lock) on a duplicate
  of the block's captured cref.  It is stored in a hidden ivar on the
  Proc and injected into the block frame on every proc-invocation path
  (Proc#call, yield from C methods, invokeblock/opt_call, and
  instance_eval/instance_exec/module_eval/class_eval via yield_under).
  The captured environment stays shared, so closure variables are still
  shared with the original Proc.  `using` inside the body is rejected
  (CREF_REFINED_PROC), so the cref's refinements never change after
  publication.

* A recursive deep copy of the block's instruction sequences
  (rb_iseq_dup_with_independent_caches) so the new Proc has its own
  inline method caches.  This is required for correctness: the VM
  caches refinement method resolution per call site assuming a single
  lexical cref per iseq, so sharing the iseq would leak the refined
  methods into the original Proc.  Coverage keeps measuring the copied
  iseq.

The copy and the cref are memoized in a hidden identity Hash keyed by
the source iseq (one slot per iseq, matched by the captured cref and
the module arguments, accessed under the VM lock), so repeated calls at
the same site reuse one copy and procs refined with the same modules
share the iseq and the cref.  A differing module set or a ruby2_keywords
flag mismatch rebuilds the entry (with a performance warning).  The
refinements table of the memoized cref is frozen and marked shareable so
the memo also serves other Ractors.

Procs without an iseq block (Symbol#to_proc, C-function procs), procs
created from methods, and procs that already have refinements are
rejected with ArgumentError.

The YJIT/ZJIT Rust bindings are regenerated for the new rb_proc_t field.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…YAMLSerializer

Splitting the source on LF alone left a trailing CR on every line, so
the empty-value check saw a non-empty scalar and folded nested mappings
and sequences into a single plain scalar. YAML normalizes CRLF to LF
during parsing, so the CR belongs to the line break, not the content.
The existing CRLF test only covered a flat mapping, which happens to
survive the stray CR.

ruby/rubygems@067e0aa4bf

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ck scalar

A literal block scalar cannot represent a CR because parsing
normalizes CRLF line breaks to LF, so a string like a CRLF PEM
certificate lost its CRs on roundtrip. Emit such strings as
double-quoted scalars with escapes, matching Psych. This fixes
TestGemPackage signing tests on Windows JRuby where to_pem
returns CRLF line endings.

ruby/rubygems@afc73d34d8

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pull pull Bot locked and limited conversation to collaborators Jul 15, 2026
@pull pull Bot added the ⤵️ pull label Jul 15, 2026
@pull pull Bot merged commit b1c35b9 into turkdevops:master Jul 15, 2026
1 of 3 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants