Skip to content

Remove the leading . (CurrentDir) prefix while normalizing#159874

Open
schneems wants to merge 1 commit into
rust-lang:mainfrom
schneems:schneems/normalize-relative
Open

Remove the leading . (CurrentDir) prefix while normalizing#159874
schneems wants to merge 1 commit into
rust-lang:mainfrom
schneems:schneems/normalize-relative

Conversation

@schneems

@schneems schneems commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Today, if you pass ./a/b and a/b through normalize equality will tell you they are different. That was surprising to me.

Here is how other languages behave with the current Rust behavior for comparison:

Implementation a ./a a/ (empty) .
Go path.Clean a a a . .
Java Path.normalize a a a (empty) (empty)
Node path.posix.normalize a a a/ . .
C++ lexically_normal a a a/ (empty) .
Ruby Pathname#cleanpath a a a . .
Python os.path.normpath a a a . .
Rust normalize_lexically (main) a ./a a (empty) .

Rust is the only one that keeps the leading .. This PR strips it so ./a normalizes to a (a lone . is still preserved):

Implementation a ./a a/ (empty) .
Rust normalize_lexically (proposed) a a a (empty) .

This aligns the leading . case with other languages.

Related tracking issue for normalize_lexically unstable feature #134694.

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jul 24, 2026
@schneems
schneems force-pushed the schneems/normalize-relative branch 2 times, most recently from 4613b4c to 0adbad0 Compare July 25, 2026 00:07
Today, if you pass `./a/b` and `a/b` through normalize equality will tell you they are different. That was surprising to me.

Here is how other languages behave with the current Rust behavior for comparison:


| Implementation                    | `a` | `./a` | `a/` | `(empty)` | `.`       |
| --------------------------------- | --- | ----- | ---- | --------- | --------- |
| Go `path.Clean`                   | `a` | `a`   | `a`  | `.`       | `.`       |
| Java `Path.normalize`             | `a` | `a`   | `a`  | `(empty)` | `(empty)` |
| Node `path.posix.normalize`       | `a` | `a`   | `a/` | `.`       | `.`       |
| C++ `lexically_normal`            | `a` | `a`   | `a/` | `(empty)` | `.`       |
| Ruby `Pathname#cleanpath`         | `a` | `a`   | `a`  | `.`       | `.`       |
| Python `os.path.normpath`         | `a` | `a`   | `a`  | `.`       | `.`       |
| Rust `normalize_lexically` (main) | `a` | `./a` | `a`  | `(empty)` | `.`       |


Rust is the only one that keeps the leading `.`. This PR strips it so `./a`
normalizes to `a` (a lone `.` is still preserved):

| Implementation | `a` | `./a` | `a/` | `(empty)` | `.` |
|---|---|---|---|---|---|
| Rust `normalize_lexically` (proposed) | `a` | `a` | `a` | `(empty)` | `.` |

This aligns the leading `.` case with other languages.
@schneems
schneems force-pushed the schneems/normalize-relative branch from 0adbad0 to e8ebb2a Compare July 25, 2026 00:12
@schneems
schneems marked this pull request as ready for review July 25, 2026 00:13
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 25, 2026
@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jul 25, 2026
@rustbot

rustbot commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

r? @jhpratt

rustbot has assigned @jhpratt.
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 13 candidates
  • Random selection from 6 candidates

@jhpratt

jhpratt commented Jul 25, 2026

Copy link
Copy Markdown
Member

I'm going to wait for t-libs to weigh in on #159863, as I don't know what the intent of this API is.

@ChrisDenton

Copy link
Copy Markdown
Member

One issue is that on Windows those can be different paths in special cases. For example:

// This opens the console input 
std::fs::File::open(r"CONIN$").unwrap();
// This attempts to open a file called `CONIN$`
std::fs::File::open(r"./CONIN$").unwrap();

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