Skip to content

Implemented DoubledEndedIterator for Ancestors<'_> + added tests and updated doc comments#153239

Open
asder8215 wants to merge 1 commit intorust-lang:mainfrom
asder8215:reverse_ancestor_acp
Open

Implemented DoubledEndedIterator for Ancestors<'_> + added tests and updated doc comments#153239
asder8215 wants to merge 1 commit intorust-lang:mainfrom
asder8215:reverse_ancestor_acp

Conversation

@asder8215
Copy link
Contributor

This PR revolves around the tracking issue for implementing DoubleEndedIterator for Ancestors<'_>.

I tried to minimize the information needed in Ancestors<'_> struct to effectively produce the correct backward and forward paths using a front and back index; I did opt to use a &'a [u8] over &'a Path because it would reduce code in .next()/.next_back() where I wouldn't need to constantly convert the Path into a u8 slice. Due to how relative paths worked previously for Ancestors<'_>, I had to introduce logic that allowed for returning an empty string at the start/end of a relative path for .next_back()/.next(); I'm open to a lot of feedback on how to make the code neater to address these cases.

I tested this pretty extensively on my Linux machine (comparing it with the output of what Ancestors<'_> previously returned); I do have to do more testing for Windows (been struggling a bit to get my Windows VM to run my shared folder containing the rust project through ./x though, so I may need some help on this), which there are some windows-specific test in tests/path_ancestors.rs. As far as I'm aware as well, the create_dir_all tests, which does use Ancestors<'_> underneath the hood, all passes.

I am aware of one breaking change in this code though. I realized for a path like:

let mut path = Path::new("/foo/bar/baz/").ancestors();

Its Ancestor<'_> iterator contains:

"/foo/bar/baz/"
"/foo/bar"
"/foo"
"/"
 (Then it's None afterward)

The previous implementation doesn't strip trailing slashes for the first path, but in subsequent paths it does eliminate trailing slashes. You can see this here.

With how I use ascii separators to determine that we've reached the next component, this does make it a bit difficult to find a neat way to handle this logic (and do this symmetrically as well for .next_back()). For example, consider the two paths:

"/foo/bar/baz/"
"/foo/bar/baz"

With how I'm using a back index approach, I save what the current back idx is in a variable (curr_back), then iterate through the u8 slice until I hit an ascii separator, advance more through potential ascii separators, and then stop reading from there if there are no more adjacent ascii separators, returning what path[..curr_back] is (trimming separators). Doing this on the first path would return "/foo/bar/baz" in the first call (since I trim separators, but otherwise this would be "/foo/bar/baz/") and then return "/foo/bar/baz" again in the next call (this is because curr_back is set to the idx of where the last "/" is at in "/foo/bar/baz/"). Doing this for the second path would return "/foo/bar/baz" in the first call and then "/foo/bar" in the next call. I currently just trim separators from the original path before giving that to the Ancestors<'_> struct when .ancestors() is called.

I'm hoping this change isn't room for big concerns because removing trailing separators for the original path does not break logic in accessing that path. However, if someone were to use Ancestors<'_> for printing paths recursively up, this would cause changes to the first path, which I do not see it being a huge issue if they want to print the original path unchanged since they can opt to consume the first item in the iterator and print the original path. If I do, however, need to account for this logic, then I will try and see what I can do; I'm open to feedback in handling this case as well.

@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 Mar 1, 2026
@rustbot
Copy link
Collaborator

rustbot commented Mar 1, 2026

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
  • Random selection from Mark-Simulacrum, joboet

@rust-log-analyzer

This comment has been minimized.

@asder8215 asder8215 force-pushed the reverse_ancestor_acp branch from 79234be to eb5b1fc Compare March 1, 2026 03:32
@rust-log-analyzer

This comment has been minimized.

@asder8215 asder8215 force-pushed the reverse_ancestor_acp branch from eb5b1fc to 26917f2 Compare March 1, 2026 03:43
@rust-log-analyzer

This comment has been minimized.

@asder8215 asder8215 force-pushed the reverse_ancestor_acp branch from 26917f2 to b436c61 Compare March 1, 2026 05:20
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.

4 participants