[ruby-core:123484] [Ruby Bug#21640] Core Pathname is missing 3 methods / is partially-defined
Issue #21640 has been reported by Eregon (Benoit Daloze). ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like an autoload that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realize the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gems. Here are concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 4. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 5. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem. Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Eregon (Benoit Daloze). I'm happy to help making the changes in ruby/ruby to make Pathname "just a default gem" again like it was in 3.4, if that is the decided outcome of the dev meeting (I added this ticket to https://bugs.ruby-lang.org/issues/21606). ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114859 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Eregon (Benoit Daloze).
I'm not sure why, but that seems a serious bug that the pathname gem apparently can't be used at all with Bundler.
This is actually a Bundler issue independent from this issue as it already exists on Ruby 3.4: https://github.com/ruby/rubygems/issues/9030. The issue (point 4) is caused by core Pathname though, on 3.4 it behaves as expected: ``` $ gem install pathname $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' /home/eregon/.rubies/ruby-3.4.4/lib/ruby/gems/3.4.0/gems/pathname-0.4.0/lib/pathname.so /home/eregon/.rubies/ruby-3.4.4/lib/ruby/gems/3.4.0/gems/pathname-0.4.0/lib/pathname.rb ``` But on 3.5 due to core Pathname it's broken: ``` $ gem install pathname $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ``` ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114890 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Earlopain (Earlopain _). I want to adress some of these points: * Problems 1 and 2 seem to be the same to be * Problem 3, is that even one? If pathname is core, I don't except development to continue in the gem repository. * Problem 4 you just adressed yourself, arguably a bug in bundler. If the pathname gem becomes a noop on modern rubies (see below on problem 6) then I believe this would just resolve itself. * Nothing to add for problem 5, I believe keeping them in sync should not be a goal, see below. * Problem 6, I believe pathname is "doing it wrong". `set` for example got no-opped on versions of ruby where set got made core: https://github.com/ruby/set/blob/4aa1291c49a12eca8f8bb633a01afedab41800dd/li.... Set was pure Ruby though, so it might need a slightly different approach. For me, that only leaves the issue of the 3 methods that rely on default gems. Honestly, it doesn't seem such a big deal to me, I don't understand why they can't just be required on usage. But it seems decided, so I have nothing more to say on that. ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114894 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Eregon (Benoit Daloze). Earlopain (Earlopain _) wrote in #note-12:
I want to adress some of these points:
Thank you for your feedback.
* Problems 1 and 2 seem to be the same to me
They are very related but not the same, here is what I meant: 1 is explaining that Pathname inherently depends on other gems/stdlib like find/fileutils/tmpdir, because it's a big part of what makes it useful, IOW we cannot remove this dependency or remove the corresponding methods. It would be a huge breaking change. 2 is about these methods being only available on `require "pathname"`. They are still available, but it's awkward and confusing to have a partially-defined class.
* Problem 3, is that even one? If pathname is core, I don't except development to continue in the gem repository.
I think the gem should continue to exist and be a way to get new pathname features and fixes on any Ruby >= 3.0. `pathname` has been a default gem since Ruby 3.0, so I think it should remain upgradable. This functionality is basically lost in 3.5 with core pathname. It's also much easier to contribute or improve the gem, than changing pathname.rb in the ruby repository. Making it core will probably discourage most people to contribute to pathname. Unlike `Set`, the Pathname API is not "done and stable for years", there are plenty of useful things to add.
* Problem 4 you just adressed yourself, arguably a bug in bundler. If the pathname gem becomes a noop on modern rubies (see below on problem 6) then I believe this would just resolve itself.
The example with bundler is a Bundler bug. But the `require "pathname"` is an issue (it uses to pick up the gem, and now it no longer does), unless indeed the gem becomes noop on 3.5+. It shows the incompatibility of having the gem non-noop but missing the default gem.
* Problem 6, I believe pathname is "doing it wrong". `set` for example got no-opped on versions of ruby where set got made core: https://github.com/ruby/set/blob/4aa1291c49a12eca8f8bb633a01afedab41800dd/li.... Set was pure Ruby though, so it might need a slightly different approach.
I hadn't considered the idea to make the pathname gem noop. It would mean Ruby 3.5 loses the ability to update pathname, be it for new functionality or bug fixes or security fixes, every change would need a Ruby release, which is very heavy for this. My gut feeling is we'd then basically freeze pathname as it is currently and it would probably not be changed much in years. As time goes by the community would find new convenient patterns for path-like objects and find pathname insufficient, and then probably create another gem for it, or possibly extend Pathname with another gem. It doesn't sound great/ideal to me. We can imagine there would be a security fix in the last release of the pathname gem, having `gem "pathname", "x.y.z"` in a Gemfile would ensure the fix is used on Ruby 3.0-3.4 but on 3.5 it would silently be ignored and vulnerable. Granted it is rather unlikely to have security issues with Pathname given it delegates most of the work, but it's still possible and in fact more likely if functionality like `mkpath` [is duplicated](https://github.com/ruby/ruby/commit/03800bff6999fd03076c03a3dec50fc4d1220824). Also I thought the goal is to gemify the stdlib, for that core pathname is clearly a step backward. I totally agree for trivial things like io/nonblock to have them core rather than a gem but pathname is far bigger and the API less established/finished.
For me, that only leaves the issue of the 3 methods that rely on default gems. Honestly, it doesn't seem such a big deal to me, I don't understand why they can't just be required on usage. But it seems decided, so I have nothing more to say on that.
I think a NoMethodError as in the description is very confusing, how can Pathname be defined but not have the methods it always had? Also if people need to `require "pathname"` to get "the full Pathname" then there seems be no point to have this in core, people will then learn to always `require "pathname"` and it will become another gotcha to learn when programming Ruby (not unlike having to add the frozen string literal magic comment). --- I'm not sure if making the pathname gem noop is good or not, as you say it does address problems 3 to 6 but not 1 & 2, i.e. the dependency concern and the missing methods. My main goal with this issue is to address the missing methods, i.e. to never have a partially-defined Pathname. The dependency concern sounds like potential future problems, in fact it's not unlike #21645 where `fiddle` became a bundled gem but still being depending on by default gems/stdlib. I think that can't work and in such cases we should do it following the order of dependencies. I.e. for pathname we'd need to make `find`, `fileutils` and `tmpdir` core, or leave it as a default gem, since it depends on other default gems. ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114895 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Earlopain (Earlopain _).
... it's awkward and confusing to have a partially-defined class
I agree.
I think the gem should continue to exist and be a way to get new pathname features and fixes on any Ruby >= 3.0. This functionality is basically lost in 3.5 with core pathname.
I admit I am not very knowledgable on this. Are there other core classes that are still distributed as a gem also? To me being part of core excludes that.
My gut feeling is we'd then basically freeze pathname as it is currently and it would probably not be changed much in years.
pathname only had 4 releases since it became a gem at the end of 2020, that does not seem like that much innovation. Per the changelog it barely changed since then even with the releases that tweaked/added something slightly. I do agree that it is more intimidating to contribute to ruby directly.
I think a NoMethodError as in the description is very confusing, how can Pathname be defined but not have the methods it always had?
I agree with this. I want more things in core but starting with pathname while it directly depends on 3 default gems was perhaps too eager. You could say that these methods make up a miniscule usage of pathname overall (probably, right?) but I don't think that would be a very good argument. ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114901 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Eregon (Benoit Daloze). Earlopain (Earlopain _) wrote in #note-14:
pathname only had 4 releases since it became a gem at the end of 2020, that does not seem like that much innovation. Per the changelog it barely changed since then even with the releases that tweaked/added something slightly. I do agree that it is more intimidating to contribute to ruby directly.
True, but looking at https://github.com/ruby/pathname/releases each of these releases had a bunch of changes, so it's more of "released not so often" than "few changes". I think several PRs at https://github.com/ruby/pathname/pulls look good and in fact I'd like to help maintaining pathname gem (if it stays usable on Ruby 3.5+).
You could say that these methods make up a miniscule usage of pathname overall (probably, right?) but I don't think that would be a very good argument.
It's 4 methods actually `find`, `mkpath`, `rmtree` and `mktmpdir`. `mkpath` has been worked around for now by duplicating the definition. My expectation is both `mkpath` and `rmtree` are pretty frequent: * https://github.com/search?q=language%3ARuby+mkpath&type=code 59.6k hits * https://github.com/search?q=language%3ARuby+rmtree&type=code 20.4k hits ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114902 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by matz (Yukihiro Matsumoto). I'd like to document clearly that those 3 methods require explicit "require". Matz. ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114909 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Eregon (Benoit Daloze). OK, I've made a PR to document that in https://github.com/ruby/ruby/pull/14953. But it's just a workaround, it doesn't address any of the problems. It doesn't address what happens to the pathname gem and the various problems I mentioned in the description (core pathname is likely to miss some methods compared to the gem, `require 'pathname'` doesn't load the gem as expected, complications with sync'ing the gem and core code, performance issues when redefining Pathname with the gem). Also this partial definition of core Pathname problem is likely to become worse as more methods are added e.g. in https://github.com/ruby/pathname/issues/64. ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114921 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by gurgeous (Adam Doppelt). Longtime rubyist here. I am the author of one of the Pathname PRs that kickstarted this discussion (#64). My PR adds the following methods to Pathname: ``` ruby # these all use FileUtils def mkdir_p(...) def ln(...) def ln_s(...) def ln_sf(...) def cp(...) def cp_r(...) def mv(...) def rm(...) def rm_r(...) def rm_rf(...) ``` The PR brings together two of my favorite Ruby libraries, FileUtils and Pathname. Wouldn't this be nice? What's the best way to move forward? I understand there are some difficult questions surrounding core vs gem. We don't want to accidentally make it difficult to improve a key library like Pathname. ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114922 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Dan0042 (Daniel DeLorme).
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
But *why*? If there's an actual problem with this approach I would like to hear it. If it's just because it "feels unclean" then I would like the core team to prioritize usefulness over these subjective notions. `pp` already works like that and I don't see a problem, it's really quite useful. Regarding the bugs caused by conflicts between core and gem pathname, yeah that seems like a big pain in the ass. But they also seem like the kind of bugs than can/should be solved by debugging them, not by giving up on the whole premise. Doesn't `Set` have the same problems? It was changed from a default gem to a builtin in 3.2, and there's also an installable gem. It seems like the situation is the same as `Pathname` but it hasn't had the same issues? ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114928 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by jeremyevans0 (Jeremy Evans). Dan0042 (Daniel DeLorme) wrote in #note-19:
Doesn't `Set` have the same problems?
No.
It was changed from a default gem to a builtin in 3.2, and there's also an installable gem. It seems like the situation is the same as `Pathname` but it hasn't had the same issues?
In Ruby 3.2, `set` was default gem, and `Set` was an autoloaded constant. The `set` library was not required when a method was called (unless the method referenced the `Set` constant). When `Set` was changed to a core class, all methods were reimplemented in core, there were no methods where you still need to require `set` (requiring `set` is a no-op in Ruby 3.5). There was one method (`Set#divide`) that relied on another standard library (`tsort`) in one case, but it was reimplemented to avoid needing the standard library (first incorrectly by me, and then correctly by @tompng). The issue with `Pathname` is that it was not fully converted to core, only partially converted. ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114929 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Dan0042 (Daniel DeLorme).
The issue with `Pathname` is that it was not fully converted to core, only partially converted.
Yes that's the issue with the 3 methods missing from core Pathname, but @eregon's point 4 was about conflicts when `require "pathname"` loads the core version rather than the gem. But that doesn't happen with `require "set"`. In fact, the "set" gem appear to never be loaded at all?! Sorry, I can't make sense of these divergent behaviors. $ 3.5 ruby -e 'Pathname; puts $".grep /pathname/' pathname.so $ 3.5 ruby -e 'require "pathname"; puts $".grep /pathname/' pathname.so /opt/ruby/master/lib/ruby/3.5.0+4/pathname.rb $ 3.5 gem install pathname $ 3.5 ruby -e 'require "pathname"; puts $".grep /pathname/' pathname.so /opt/ruby/master/lib/ruby/3.5.0+4/pathname.rb $ 3.5 ruby -e 'gem "pathname"; require "pathname"; puts $".grep /pathname/' /opt/ruby/master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb:17: warning: already initialized constant Pathname::VERSION <internal:pathname_builtin>:194: warning: previous definition of VERSION was here /opt/ruby/master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb:22: warning: already initialized constant Pathname::TO_PATH <internal:pathname_builtin>:199: warning: previous definition of TO_PATH was here /opt/ruby/master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb:24: warning: already initialized constant Pathname::SAME_PATHS <internal:pathname_builtin>:201: warning: previous definition of SAME_PATHS was here /opt/ruby/master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb:36: warning: already initialized constant Pathname::SEPARATOR_LIST <internal:pathname_builtin>:319: warning: previous definition of SEPARATOR_LIST was here /opt/ruby/master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb:37: warning: already initialized constant Pathname::SEPARATOR_PAT <internal:pathname_builtin>:320: warning: previous definition of SEPARATOR_PAT was here /opt/ruby/master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb:43: warning: already initialized constant Pathname::ABSOLUTE_PATH <internal:pathname_builtin>:327: warning: previous definition of ABSOLUTE_PATH was here pathname.so /opt/ruby/master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb vs $ 3.5 ruby -e 'Set; puts $".grep /set/' set.rb $ 3.5 ruby -e 'require "set"; puts $".grep /set/' set.rb $ 3.5 gem install set $ 3.5 ruby -e 'require "set"; puts $".grep /set/' set.rb $ 3.5 ruby -e 'gem "set"; require "set"; puts $".grep /set/' set.rb ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114933 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by jeremyevans0 (Jeremy Evans). Dan0042 (Daniel DeLorme) wrote in #note-21:
But that doesn't happen with `require "set"`. In fact, the "set" gem appear to never be loaded at all?! Sorry, I can't make sense of these divergent behaviors.
It's normal behavior when moving from stdlib to core that `rb_provide` is used to make it appear that the library has already been loaded. Having `set.rb` in `$"` makes it so code that uses `require 'set'` does not cause files to be loaded. Ruby has done this for a long time. If you look in `$"`, you'll also see: * `enumerator.so` * `thread.rb` * `fiber.so` * `rational.so` * `complex.so` * `ruby2_keywords.rb` ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114934 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Eregon (Benoit Daloze). Dan0042 (Daniel DeLorme) wrote in #note-19:
But _why_? If there's an actual problem with this approach I would like to hear it. If it's just because it "feels unclean" then I would like the core team to prioritize usefulness over these subjective notions. `pp` already works like that and I don't see a problem, it's really quite useful.
Yeah I would like to know in more details as well. It feels unclean but it's also very pragmatic to just do the `require` when needed in the method, like for `pp`, `binding.irb`, etc. ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114942 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Dan0042 (Daniel DeLorme).
It's normal behavior when moving from stdlib to core that `rb_provide` is used to make it appear that the library has already been loaded. Having `set.rb` in `$"` makes it so code that uses `require 'set'` does not cause files to be loaded. Ruby has done this for a long time.
So the issue here is that pathname doesn't use this `rb_provide` ? ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114946 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by jeremyevans0 (Jeremy Evans). Dan0042 (Daniel DeLorme) wrote in #note-24:
So the issue here is that pathname doesn't use this `rb_provide` ?
pathname does use `rb_provide`: ``` $ git grep rb_provide pathname.c pathname.c: rb_provide("pathname.so"); ``` Note that it uses `pathname.so`. The 3 methods that require libraries are in `pathname.rb`. It would not make sense for pathname to do `rb_provide("pathname.rb")` unless it implemented those 3 methods in core. ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114947 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Dan0042 (Daniel DeLorme). Ah, thank you very much, now I see it. So this #4 issue could be solved by implementing the 3 methods as shims that load the necessary dependencies, which then allows pathname to do `rb_provide("pathname.rb")` ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114948 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Eregon (Benoit Daloze). If the gem is a noop then of course it would not matter, but I'm unsure if the gem should be a noop. There is also the issue that core already uses the pathname C extension, and loading the gem pathname C extension might cause issues, including native symbol conflicts, calling the wrong Init_ function, etc. It's not really possible to unload a C extension AFAIK. That's for me another reason to not have Pathname in core (or to make the pathname gem noop, but that has different concerns detailed in https://bugs.ruby-lang.org/issues/21640#note-13, mostly it's much harder and slower to improve it). ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114952 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Dan0042 (Daniel DeLorme). Eregon (Benoit Daloze) wrote in #note-27:
If the gem is a noop then of course it would not matter, but I'm unsure if the gem should be a noop.
I can't answer if it "should", but at least that's how it works with `set`, so at least it's consistent. But to be honest, as @hsbt said in #17473, "I'm happy to use Pathname without require it." and that's really all I am looking for as well. `Pathname` autoloaded from a default gem would work fine for me. At the same time @mame said "Rubygems cannot allow users to choose the version of a gem that rubygems itself are using." and I think that's an important goal/point to consider; that's the real reason the gem needs to be a noop. ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-114953 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by Eregon (Benoit Daloze). Dan0042 (Daniel DeLorme) wrote in #note-28:
But to be honest, as @hsbt said in #17473, "I'm happy to use Pathname without require it." and that's really all I am looking for as well.
That's a trap though because without requiring it pretty essential stuff is missing like `Pathname#rmtree` and `Pathname.mktmpdir`.
`Pathname` autoloaded from a default gem would work fine for me.
I think this could work nicely, and be a lot simpler.
At the same time @mame said "Rubygems cannot allow users to choose the version of a gem that rubygems itself are using." and I think that's an important goal/point to consider; that's the real reason the gem needs to be a noop.
RubyGems and Bundler should not use `::Pathname` anyway, they should have their own vendored copy (same approach as other default/bundled gems used by RubyGems & Bundler), that's a known issue and there is even a PR to fix it: https://github.com/ruby/rubygems/pull/4992 ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-115035 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
Issue #21640 has been updated by gurgeous (Adam Doppelt). Is there a way to resolve this? I just want to make Pathname (and Ruby) better :) ---------------------------------------- Bug #21640: Core Pathname is missing 3 methods / is partially-defined https://bugs.ruby-lang.org/issues/21640#change-115401 * Author: Eregon (Benoit Daloze) * Status: Open * ruby -v: ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- ``` $ ruby -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > core_pathname_methods.txt $ ruby -rpathname -e 'puts Pathname.instance_methods(false).sort; puts Pathname.singleton_methods.sort' > require_pathname_methods.txt $ diff core_pathname_methods.txt require_pathname_methods.txt 36a37
find 72a74 rmtree 98a101 mktmpdir
So `#find`, `#rmtree` and `.mktmpdir` are missing from core Pathname.
And indeed, they give NoMethodError, e.g.
$ ruby -ve 'Pathname.new("doesnotexist").rmtree' ruby 3.5.0dev (2025-10-09T08:06:20Z master a29c90c3b0) +PRISM [x86_64-linux] -e:1:in '<main>': undefined method 'rmtree' for an instance of Pathname (NoMethodError) ``` I think this is confusing and unexpected for most users. Either Pathname should be fully defined or not at all, having a partially-defined Pathname seems particularly confusing (a bit like a `require` that failed in the middle or so). AFAIK the only core class which used to have this was Fiber with `alive?` and `transfer`, that certainly caused its share of confusion, and Fiber has since been fixed, now even without `require "fiber"` Fiber has all methods. Furthermore these 3 methods are not documented as needing `require 'pathname'` in their documentation: https://github.com/ruby/ruby/blob/master/lib/pathname.rb The reason these 3 methods are not in core pathname seems to be (from [this comment](https://github.com/ruby/pathname/issues/64#issuecomment-3388907046)):
That's consensus with akr and me. We should avoid loading other libraries by simply calling methods from the embedded core classes.
I understand that concern and I share it, but I think the situation of having a partially-defined Pathname in core is quite problematic. I think there are 2 solutions: * Define all Pathname methods in core. The `require` are done lazily inside the methods so AFAIK there is no technical issue blocking that, but it's not ideal design-wise that a core class can load default gems (i.e. give up that concern for this particular case). * Do not define Pathname in core and let it be a default gem as it was in Ruby 3.4. I discuss the second in more details, because I found more problems than I would have imagined with core Pathname: ## Should Pathname be in core? #17473 proposed to make Pathname core. That sounded great to me at first thought, but as I realized the practical problems with it I'm thinking it's actually better to keep Pathname non-core and as a default gem. Here are 6 problems/concerns with having Pathname in core: 1. Pathname inherently depends on other default gems/stdlib like `find`, `fileutils` and `tmpdir`. This is important to make Pathname useful. The docs even phrase it like this: `ri Pathname`
... All functionality from File, FileTest, and some from Dir and FileUtils is included, in an unsurprising way. It is essentially a facade for all of these, and more.
2. core Pathname is missing 3 methods compared to gem Pathname (shown above) 3. the pathname gem is likely to gain extra features, methods and bug fixes. For example I see [4 PRs](https://github.com/ruby/pathname/pulls) adding new methods. It means core Pathname will always be outdated and potentially missing some new methods. 4. One can still use the pathname gem even if it's in core, but surprisingly just `require 'pathname'` is not enough: ``` $ gem install pathname Building native extensions. This could take a while... Successfully installed pathname-0.4.0 1 gem installed $ ruby -e 'require "pathname"; puts $".grep(/pathname/)' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb ^ wrong that's the stdlib pathname $ ruby -e 'gem "pathname"; require "pathname"; puts $".grep(/pathname/)' # some warnings, reported in https://github.com/ruby/pathname/issues/66 pathname.so /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/pathname-0.4.0/lib/pathname.rb ^ correct .rb but the wrong .so! (could lead to pretty confusing issues) ``` This is another source of confusion caused by core pathname. It even happens with Bundler! ``` $ cat Gemfile source "https://rubygems.org" gem "pathname" $ bundle install $ ruby -e 'require "bundler/setup"; require "pathname"; puts $".grep(/pathname/); puts; puts $:' pathname.so /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/pathname.rb /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/gems/pathname-0.4.0/lib /home/eregon/tmp/bundler-pathname/vendor/bundle/ruby/3.5.0+4/extensions/x86_64-linux/3.5.0+4-static/pathname-0.4.0 /home/eregon/prefix/ruby-master/lib/ruby/gems/3.5.0+4/gems/bundler-2.8.0.dev/lib /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/site_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/site_ruby /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby/3.5.0+4/x86_64-linux /home/eregon/prefix/ruby-master/lib/ruby/vendor_ruby /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4 /home/eregon/prefix/ruby-master/lib/ruby/3.5.0+4/x86_64-linux $ bundle exec ruby -e 'require "pathname"; puts $".grep(/pathname/); puts; puts $:' same as above ``` I'm not sure why, but that seems a serious bug that the `pathname` gem apparently can't be used at all with Bundler. 5. due to this difference in terms of methods for core & gem pathname it seems complicated to keep core Pathname and gem Pathname in sync, since e.g. everything is naturally in one `.rb` file in the gem, but in two `.rb` files in core 6. the pathname gem has to `remove_const :Pathname` to avoid conflicts and warnings in https://github.com/ruby/pathname/blob/4689b0b78d081ae855f325e086d95803fa5bd5.... This is bad for Ruby JITs, especially if core Pathname methods might have been used, as it will invalidate JITs compilations, invalidate some inline caches (also bad for the interpreter), caused the JIT to do more compilations which means slower warmup, makes it much harder to persist JITed code across process executions, etc. Based on all of these I think it would actually be better to not have Pathname in core, and let it be a default gem (as it was in 3.4). Having to `require "pathname"` as one always needed to do so far seems far better than a partially-defined core Pathname with rough edge cases (those concerns). -- https://bugs.ruby-lang.org/
participants (6)
-
Dan0042 (Daniel DeLorme) -
Earlopain (Earlopain _) -
Eregon (Benoit Daloze) -
gurgeous (Adam Doppelt) -
jeremyevans0 (Jeremy Evans) -
matz (Yukihiro Matsumoto)