Skip to content

Redesigned Components iterator to use front and back indexing instead mutating and subslicing path field#156496

Open
asder8215 wants to merge 9 commits into
rust-lang:mainfrom
asder8215:components_rewrite
Open

Redesigned Components iterator to use front and back indexing instead mutating and subslicing path field#156496
asder8215 wants to merge 9 commits into
rust-lang:mainfrom
asder8215:components_rewrite

Conversation

@asder8215

@asder8215 asder8215 commented May 12, 2026

Copy link
Copy Markdown
Contributor

View all comments

This PR entirely changes how Components<'_> is implemented. Currently, the Components<'_> iterator 'consumes' components through mutating its path field to a subslice that presents the left over unconsumed path components (this consumed path component is what's returned in Components::next or Components::next_back). However, this PR keeps the path field alive/unmodified and uses front and back indexing strategy to extract consumed/unconsumed components.

This PR benefits implementations like Components::as_path, which is pretty used is multiple areas of the standard library. Previously, Components<'_> iterator was required to clone inside the function to present the unconsumed path because our original Component<'_> consuming behavior on path will not allow the returned &'a Path from Components::as_path to last after a Components::next or Components::next_back call. Due to the current implementation of Components iterator has a size of 64 bytes, if you're using Components::as_path after each Components::next/Components::next_back, then it's pretty unfortunate to be cloning 64 bytes again and again, especially if each of your path components are a few bytes (e.g., "foo/bar/baz").

On the point of size, with the indexing strategy, this PR has further optimized the size of Components<'_> from 64 bytes -> 40 bytes since a large chunk of the Components<'_> was taken up by the Option<Prefix> (this takes up 40 bytes). Instead of holding a prefix field in Components<'_>, we can encode the length of the Prefix within our front field index and use another enum called FirstComponent to check whether our first component of the given path is Prefix (or something else). If it's a Prefix, we can use parse_prefix on the subslice self.path[..self.front] since we know our front index encodes the Prefix length.

Due to not having the prefix Option<Prefix> field inside Components<'_> anymore, all the prefix functions in Components<'_> have been removed in favor of calling parse_prefix, Prefix::is_verbatim, Prefix::is_drive, etc.

I'm curious if this redesign of Components<'_> improves Path equality as pointed out by @clarfonthey in #154521 with Path equality (not to be confused with Path ordering as mentioned in the issue, since that uses Components:::compare_components and the example code shows equality) being slow. I haven't benchmarked this though. I have benchmarked the result and I can say that currently this implementation improves Path equality due to Components::next_back running faster with this implementation than the current mutating path with a subslice implementation. However, Path ordering runs slightly slower. You can check the benchmark code I used here, and play around with the number of bytes in a component, the number of components, etc..

Right now, when I tested it locally on my PC (Fedora OS), it passed all the standard library tests and rust analyzer didn't crash on me (had a few crash reports coming from rust analyzer early on when I messed around with Components<'_> dealing something with threads using Path::components, but now that's all resolved). I have not tested this on Windows yet, and I would probably need someone to help me test on this platform as my Windows VM is not working properly to run the standard library test suite.

There's a lot of things being done here, and possibly there may be better approaches or ways I could improve this implementation or write the code in a neater way here. I am open to any advice or feedback on this approach.

Update: I got to testing some things out with Prefixes on my Windows VM manually, so the prefix component index encoded into the Components<'_> front field seems to work out nicely. I've also accounted for root directory being able to exists after a Prefix component like "\?\checkout\src\tools" having the following components: PrefixVerbatim -> RootDir -> Normal -> Normal -> None (learnt this from the fail that occurred in miri tests, which is nice to see this Components<'_> implementation works on the Windows tests in CI).

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels May 12, 2026
@rustbot

rustbot commented May 12, 2026

Copy link
Copy Markdown
Collaborator

r? @Mark-Simulacrum

rustbot has assigned @Mark-Simulacrum.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: @ChrisDenton, libs
  • @ChrisDenton, libs expanded to 8 candidates

@rustbot

This comment has been minimized.

@asder8215 asder8215 force-pushed the components_rewrite branch from 1627e2f to 33e69e1 Compare May 12, 2026 09:09
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@asder8215 asder8215 force-pushed the components_rewrite branch from 33e69e1 to ed9d33d Compare May 12, 2026 17:05
@rust-log-analyzer

This comment has been minimized.

@asder8215 asder8215 force-pushed the components_rewrite branch from ed9d33d to 0b0f84c Compare May 12, 2026 17:19
@rust-log-analyzer

This comment has been minimized.

@asder8215 asder8215 force-pushed the components_rewrite branch from 0b0f84c to 8ed33ea Compare May 12, 2026 22:05
@asder8215

This comment was marked as outdated.

@asder8215 asder8215 force-pushed the components_rewrite branch from 2151b8f to 83cdbed Compare May 13, 2026 22:21
@asder8215

This comment was marked as outdated.

@asder8215 asder8215 force-pushed the components_rewrite branch from 83cdbed to 3921fff Compare May 15, 2026 00:30
@asder8215 asder8215 marked this pull request as draft May 16, 2026 12:22
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 16, 2026
@asder8215 asder8215 force-pushed the components_rewrite branch from 0a25dda to 92e0132 Compare May 17, 2026 16:09
@asder8215

asder8215 commented May 17, 2026

Copy link
Copy Markdown
Contributor Author

New benchmarking results. You can see what the benchmark code looks like here and run it yourself to see if there are any difference in measurements on your end:

This is the measurement of the current implementation of Components<'_> (without black box):

Std Components (No BB)  time:   [21.546 µs 21.800 µs 22.096 µs]
Found 5 outliers among 100 measurements (5.00%)
  4 (4.00%) high mild
  1 (1.00%) high severe

Std Components Next (No BB)
                        time:   [20.434 µs 20.482 µs 20.538 µs]
Found 7 outliers among 100 measurements (7.00%)
  5 (5.00%) high mild
  2 (2.00%) high severe

Std Components Next Back (No BB)
                        time:   [38.367 µs 38.757 µs 39.199 µs]
Found 4 outliers among 100 measurements (4.00%)
  3 (3.00%) high mild
  1 (1.00%) high severe

Std Path Iter (No BB)   time:   [21.547 µs 21.730 µs 21.921 µs]

Std As Path Iter (No BB)
                        time:   [87.680 µs 88.439 µs 89.231 µs]
Found 6 outliers among 100 measurements (6.00%)
  2 (2.00%) high mild
  4 (4.00%) high severe

Std Eq Comps (No BB)    time:   [591.21 ns 593.35 ns 595.82 ns]
Found 16 outliers among 100 measurements (16.00%)
  1 (1.00%) low severe
  3 (3.00%) low mild
  7 (7.00%) high mild
  5 (5.00%) high severe

Std Uneq Comps (No BB)  time:   [60.953 ns 61.419 ns 61.911 ns]
Found 2 outliers among 100 measurements (2.00%)
  2 (2.00%) high mild

Std Uneq 2 Comps (No BB)
                        time:   [75.454 µs 75.734 µs 76.027 µs]
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild

Std Compare Comps (No BB)
                        time:   [46.182 µs 46.621 µs 47.192 µs]
Found 4 outliers among 100 measurements (4.00%)
  3 (3.00%) high mild
  1 (1.00%) high severe

Std Compare Uneq Comps (No BB)
                        time:   [46.679 µs 46.980 µs 47.291 µs]
Found 2 outliers among 100 measurements (2.00%)
  1 (1.00%) high mild
  1 (1.00%) high severe

Std Compare Uneq 2 Comps (No BB)
                        time:   [41.480 ns 41.827 ns 42.160 ns]
Found 3 outliers among 100 measurements (3.00%)
  2 (2.00%) high mild
  1 (1.00%) high severe

This is the measurement of the new implementation of Components<'_> I'm working on (without black box):

Components Rewrite (No BB)
                        time:   [24.982 µs 25.267 µs 25.570 µs]

Components Next Rewrite (No BB)
                        time:   [24.388 µs 24.655 µs 24.937 µs]
Found 6 outliers among 100 measurements (6.00%)
  6 (6.00%) high mild

Components Next Back Rewrite (No BB)
                        time:   [18.184 µs 18.567 µs 19.034 µs]
Found 16 outliers among 100 measurements (16.00%)
  1 (1.00%) high mild
  15 (15.00%) high severe

Path Iter Rewrite (No BB)
                        time:   [23.485 µs 23.659 µs 23.829 µs]
Found 2 outliers among 100 measurements (2.00%)
  2 (2.00%) high mild

As Path Iter Rewrite (No BB)
                        time:   [22.936 µs 23.066 µs 23.208 µs]
Found 7 outliers among 100 measurements (7.00%)
  3 (3.00%) high mild
  4 (4.00%) high severe

Eq Comps Rewrite (No BB)
                        time:   [605.12 ns 608.83 ns 612.98 ns]
Found 11 outliers among 100 measurements (11.00%)
  1 (1.00%) low mild
  7 (7.00%) high mild
  3 (3.00%) high severe

Uneq Comps Rewrite (No BB)
                        time:   [31.799 ns 32.108 ns 32.433 ns]
Found 5 outliers among 100 measurements (5.00%)
  5 (5.00%) high mild

Uneq Comps 2 Rewrite (No BB)
                        time:   [47.091 µs 48.186 µs 49.085 µs]

Compare Comps Rewrite (No BB)
                        time:   [50.234 µs 50.725 µs 51.254 µs]
Found 10 outliers among 100 measurements (10.00%)
  9 (9.00%) high mild
  1 (1.00%) high severe

Compare Uneq Comps Rewrite (No BB)
                        time:   [49.262 µs 49.631 µs 50.067 µs]
Found 16 outliers among 100 measurements (16.00%)
  4 (4.00%) high mild
  12 (12.00%) high severe

Compare Uneq Comps 2 Rewrite (No BB)
                        time:   [43.397 ns 43.767 ns 44.171 ns]
Found 5 outliers among 100 measurements (5.00%)
  5 (5.00%) high mild

Edit: Updated Components::as_path to match on Option<FirstComponent>/self.first_comp instead of using if let Some(_) = self.first_comp and matching on that, benchmarking for this PR Components<'_> has been updated as a result. Everything else is unaffected by this change.

@asder8215

asder8215 commented May 17, 2026

Copy link
Copy Markdown
Contributor Author

Here are the benchmark results with black box:

From current Components<'_> implementation:

Std Components          time:   [20.947 µs 21.010 µs 21.084 µs]
Found 8 outliers among 100 measurements (8.00%)
  4 (4.00%) high mild
  4 (4.00%) high severe

Std Components Next     time:   [20.967 µs 20.993 µs 21.021 µs]
Found 2 outliers among 100 measurements (2.00%)
  2 (2.00%) high mild

Std Components Next Back
                        time:   [35.715 µs 35.802 µs 35.925 µs]
Found 20 outliers among 100 measurements (20.00%)
  6 (6.00%) high mild
  14 (14.00%) high severe

Std Path Iter           time:   [20.883 µs 20.992 µs 21.152 µs]
Found 12 outliers among 100 measurements (12.00%)
  5 (5.00%) high mild
  7 (7.00%) high severe

Std As Path Iter        time:   [80.673 µs 80.935 µs 81.261 µs]
Found 9 outliers among 100 measurements (9.00%)
  6 (6.00%) high mild
  3 (3.00%) high severe

Std Eq Comps            time:   [589.43 ns 593.36 ns 597.88 ns]
Found 4 outliers among 100 measurements (4.00%)
  1 (1.00%) low severe
  2 (2.00%) low mild
  1 (1.00%) high severe

Std Uneq Comps          time:   [63.919 ns 64.262 ns 64.765 ns]
Found 10 outliers among 100 measurements (10.00%)
  6 (6.00%) high mild
  4 (4.00%) high severe

Std Uneq 2 Comps        time:   [75.284 µs 75.939 µs 76.599 µs]
Found 3 outliers among 100 measurements (3.00%)
  3 (3.00%) high severe

From this Components<'_> implementation PR:

Components Rewrite      time:   [24.190 µs 24.425 µs 24.687 µs]
Found 5 outliers among 100 measurements (5.00%)
  4 (4.00%) high mild
  1 (1.00%) high severe

Components Next Rewrite time:   [24.230 µs 24.550 µs 24.889 µs]
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild

Components Next Back Rewrite
                        time:   [17.339 µs 17.488 µs 17.655 µs]
Found 5 outliers among 100 measurements (5.00%)
  3 (3.00%) high mild
  2 (2.00%) high severe

Path Iter Rewrite       time:   [23.845 µs 23.996 µs 24.154 µs]
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild

As Path Iter Rewrite    time:   [22.431 µs 22.676 µs 23.010 µs]
Found 4 outliers among 100 measurements (4.00%)
  2 (2.00%) high mild
  2 (2.00%) high severe

Eq Comps Rewrite        time:   [586.16 ns 588.10 ns 590.14 ns]

Found 5 outliers among 100 measurements (5.00%)
  2 (2.00%) low mild
  2 (2.00%) high mild
  1 (1.00%) high severe

Uneq Comps Rewrite      time:   [31.733 ns 32.023 ns 32.378 ns]

Found 7 outliers among 100 measurements (7.00%)
  1 (1.00%) high mild
  6 (6.00%) high severe

Uneq 2 Comps Rewrite    time:   [36.318 µs 36.574 µs 36.913 µs]
Found 23 outliers among 100 measurements (23.00%)
  23 (23.00%) high severe

Edit: Updated Components::as_path to match on Option<FirstComponent>/self.first_comp instead of using if let Some(_) = self.first_comp and matching on that, benchmarking for this PR Components<'_> has been updated as a result. Everything else is unaffected by this change.

Edit 2: Took off Path ordering benchmark here since it was incorrect see below to see corrected path ordering benchmarks.

@asder8215 asder8215 force-pushed the components_rewrite branch from 92e0132 to 574d7f2 Compare May 17, 2026 18:41
@asder8215 asder8215 marked this pull request as ready for review May 17, 2026 18:59
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 17, 2026
@asder8215

asder8215 commented May 17, 2026

Copy link
Copy Markdown
Contributor Author

I'm confident this code works (passed CI in previous run, the current amended commit change I made doesn't change logic, but makes the code written in a more idiomatic way).

In my opinion, the logic in this code should look more readable than how Component<'_> is currently written implemented as. From benchmarking, we can see that Components::next_back, Components::as_path, and in the cases where Components equality falls down to using Components::next_back (when they are unequal or equality can't be determine unless one/both Components<'_> are normalized), this PR implementation of Components<'_> is faster than how it's currently implemented as. The trade off is that this PR implementation of Components<'_> has a slight reduction in performance for Components::next and as a result Components<'_> comparison, but I would take this slight reduction in performance to make path equality faster.

@asder8215

asder8215 commented May 19, 2026

Copy link
Copy Markdown
Contributor Author

@rustbot label +I-libs-nominated

Since Components<'_> is pretty well-used in many other methods, I think this may need discussion from the libs team on whether the re-implementation of Components<'_> here is okay/valid to take over the current implementation (and the trade-off between faster Components::next_back with a slight reduction in performance in Components::next). I wasn't sure if this should be labeled as I-libs-api-nominated or not since it pertains to an existing stable feature than a new feature.

@rustbot rustbot added the I-libs-nominated Nominated for discussion during a libs team meeting. label May 19, 2026
Comment thread library/std/src/path.rs Outdated
Comment thread library/std/src/path.rs Outdated
Comment thread library/std/src/path.rs Outdated
&& prefix.is_verbatim()
&& !path.inner.is_empty()
{
let comps = self.components();

@clarfonthey clarfonthey Jun 20, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how likely the redundant prefix-checking is to get elided here in optimisation, but perhaps the fact that you need to recreate the components iterator again might be a reason to just start with that, maybe gated by HAS_PREFIXES.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the components iterator created earlier in the Windows/HAS_PREFIXES path. Unix and all the other platforms with !HAS_PREFIXES don't need to rely on components iterator at all.

With redundant prefix checking, the only optimization I could think about that is to have a parse_prefix_unchecked method that constructs a Prefix<'_> given two OsStr and something like a prefix tag enum (same enum names as the members in Prefix just without the field info that these members have) (though maybe a better name than parse should be used here since it's constructing from given arguments instead of parsing).

Comment thread library/std/src/path.rs Outdated
Comment thread library/std/src/path.rs Outdated
Comment thread library/std/src/path.rs Outdated
Comment thread library/std/src/path.rs Outdated
Comment thread library/std/src/path.rs Outdated
Comment thread library/std/src/path.rs Outdated
Comment thread library/std/src/path.rs Outdated
Comment thread library/std/src/path.rs Outdated
Comment thread library/std/src/path.rs Outdated
@clarfonthey

Copy link
Copy Markdown
Contributor

So, after the investigation I wanted to do, it does seem that we have a bit of confusion regarding how Components is explicitly documented in the standard library. I don't think it's something we need to specifically worry about for this PR, but it's a note for later to fix those, since there are a few bits of contention that would probably be surprising for some folks, like how currently Components zealously strips trailing separators and here you're making your best effort to avoid doing that.

Can probably move onto verifying perf after addressing a few comments.

@asder8215

Copy link
Copy Markdown
Contributor Author

Will address these comments when I get back to my PC!

I also wanted to check in with the team that handles Rust releases (maybe also Cargo or Rustup team) to verify if I'm building rustc and cargo with the correct configs as the one installed by rustup.

@asder8215 asder8215 force-pushed the components_rewrite branch from 53dd52e to 2ae818f Compare June 22, 2026 01:38
@rustbot

This comment has been minimized.

… of mutating and subslicing path field; as a result, Components iterator memory size goes from 64 bytes to 40 bytes and as_path does not use cloning at all
…ity, added safety comments, and check for root dir after Prefix component (e.g., '\\?\checkout\src\tools' should produce Prefix, RootDir, Normal, Normal, None, ...) in Components::parse_single_component
…here to use iter().position()/.iter().rposition(), refactored code in compare_components, and removed stale comments
…omponents::normalize_back instead, refactored Components::as_path code
…e in previous implementation, but making it work with Components<'_> front index
…nt_front and consume_first_component_back. Also introduced aggressive inlining.
…comparison (normalizing paths if needed) and return Ordering Equal/Greater/Less if possible before needing to fall back on Iterator::cmp
@asder8215 asder8215 force-pushed the components_rewrite branch from 2ae818f to 21ccd83 Compare June 22, 2026 02:23
@rustbot

rustbot commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@clarfonthey

clarfonthey commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Just occurred to me that a pretty good benchmark to represent what I was doing (where the performance was so bad) would be to aggregate a few file lists based upon the contents of various filesystems (I'm thinking, docker images), shuffling them, and storing them in a BTreeSet<PathBuf>, then recording the speed of that. We could probably choose a few seeds for the RNG to make benchmarking easier.

(And if we want to only benchmark equality, not ordering, using HashSet<PathBuf> should work too.)

I would be down to collect those file lists, and writing the code would be pretty easy for a benchmark. Apparently there are some benchmarks in the standard library via ./x bench, but I haven't looked too closely to see how they're set up. Probably using something like criterion or gungraun would be better, though.

Will try to work on a proper benchmark crate later if I remember.

… make it simpler or have it documented in the appropriate areas, and renamed a couple of methods/field members, and simplified Components::next_back relative first component branch
@asder8215 asder8215 force-pushed the components_rewrite branch from 21ccd83 to c10aaf6 Compare June 30, 2026 03:57
@asder8215

asder8215 commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author
Just occurred to me that a pretty good benchmark to represent what I was doing (where the performance was so bad) would be to aggregate a few file lists based upon the contents of various filesystems (I'm thinking, docker images), shuffling them, and storing them in a `BTreeSet<PathBuf>`, then recording the speed of that. We could probably choose a few seeds for the RNG to make benchmarking easier.

That sounds good to me. I got some assistance from Jakub on Zulip a few days ago and I built cargo + rustc with PGO optimizations through running the CI job locally. I had to copy over files from obj/.../stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib to obj/.../stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib (since it's empty), so that I could run cargo commands (though if that's incorrect for me to do, let me know). This is me compiling tokio using hyperfine:

On Debug build:
PGO-optimized Components

Benchmark 1: cargo build && cargo clean
  Time (mean ± σ):      7.000 s ±  0.107 s    [User: 14.482 s, System: 3.646 s]
  Range (min … max):    6.901 s …  7.221 s    10 runs

rustc 1.98.0 nightly compiler

Benchmark 1: cargo +nightly-x86_64-unknown-linux-gnu build && cargo +nightly-x86_64-unknown-linux-gnu clean
  Time (mean ± σ):      7.063 s ±  0.148 s    [User: 14.607 s, System: 3.656 s]
  Range (min … max):    6.842 s …  7.357 s    10 runs

On release build:
PGO-optimized Components

Benchmark 1: cargo build --release && cargo clean
  Time (mean ± σ):      6.608 s ±  0.151 s    [User: 26.261 s, System: 3.260 s]
  Range (min … max):    6.391 s …  6.847 s    10 runs

rustc 1.98.0 nightly compiler

Benchmark 1: cargo +nightly-x86_64-unknown-linux-gnu build --release && cargo +nightly-x86_64-unknown-linux-gnu clean
  Time (mean ± σ):      6.800 s ±  0.164 s    [User: 26.687 s, System: 3.258 s]
  Range (min … max):    6.571 s …  7.083 s    10 runs

There's a marginal improvement from the PGO optimized Components build on release (~3% improvement on average). However, I'm unsure if my cargo build time is a perfect comparison because it's possible that this PR rustc may not match with 1.98 rustc since my branch for this PR may be outdated in terms of other functions or features added to the standard library within 1.98.

I would be down to collect those file lists, and writing the code would be pretty easy for a benchmark. Apparently there are some benchmarks in the standard library via ./x bench, but I haven't looked too closely to see how they're set up. Probably using something like criterion or gungraun would be better, though.

Will try to work on a proper benchmark crate later if I remember.

Sure, I'll leave you to that. I'm curious to see if there would be any big performance differences.


On a separate note, I was thinking about the ACP suggestion you mentioned earlier, and I was thinking that this Components PR might just be better off as a unix (or any platforms with HAS_PREFIX set to false) exclusive thing because I don't see a good way to make this benefit Windows with how we have redundant prefix parsing. I tried out introducing a field in Components to hold a prefix enum tag (e.g. UNC, Verbatim, but without their field members) and another index point to the end of the server OsStr for UNC and VerbatimUNC components so that we can construct the Prefix component without re-parsing it, but it just ends up degrading Components::next_back to similar to how Components currently works. For some reason, keeping this Components struct at 40 bytes over 48 bytes allows it to be optimized better, which I think it has to do with compiler intrinsics (__mm256 I believe).

Going back to the ACP suggestion idea, I think we can just do something similar to how std::fs functions have platform independent behavior. We'd just need two different files one that implements Components with prefixes (uses the current subslicing behavior implementation) and one that implements Components without prefixes (this PR), and then the specific implementations of Components would be re-exported to prefix/prefix-less platforms. This PR also kind of tells me that the only thing we'd need to isolate to a different file are Components and its methods, Path::components, and Path::push. The other benefit with doing this is that I can just get rid of FirstComponents enum and rely solely on has_physical_root since I believe Prefix is the only reason why I needed FirstComponents.

In a future/separate PR, it would also be beneficial to put the Ancestors struct in the same file as Components since it can possible perform better utilizing the front/back index field members directly from Components.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants