Skip to content

Tracking Issue for std::path::absolute #92750

Description

@ChrisDenton

View all comments

Feature gate: #![feature(absolute_path)]

This is a tracking issue for std::path::absolute for making relative paths absolute without touching the filesystem. It is a drop-in replacement for std::fs::canonicalize.

Public API

let absolute = std::path::absolute("foo/./bar")?;

Steps / History

Unresolved Questions

  • on Windows this is currently implemented using GetFullPathNameW, which isn't quite a "pure" function (in some special cases, e.g. D:file.txt, it can use hidden environment variables, set by cmd.exe, to resolve the path's root).
  • Should we recommend using absolute(a.join(b)), where a is an alternative current directory to using std::env::current_dir?
  • Is the avoidance of stripping .. actually the right call? It does seem consistent with the POSIX docs, but may not be the most intuitive behavior (particularly given that Windows doesn't do that).
    • I think making the path absolute is inherently a platform-specific function. It can only really work according to the rules of the platform.

Activity

  1. added
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    T-libs-api[DEPRECATED; DO NOT USE]
    on Jan 10, 2022
  2. ChrisDenton commented on Jan 10, 2022

    @ChrisDenton
    MemberAuthor

    Ok, so cards on the table. My personal motivation for this function is to expose the Windows function GetFullPathNameW (or something similar) into the standard library in a way that can be used cross-platform. This is already used by the standard library for making verbatim paths (absolute paths that aren't limited by MAX_PATH). I've also heard from Linux users who want a way to make absolute paths that won't break on Windows. Previous related discussions include these internals thread where I explore other possibilities:

    I'd like to address the unresolved issues of not resolving .. on *nix: it was felt that resolving this is undesirable as it would change the meaning of the path. Whereas on Windows it does not. This is a fundamental difference between POSIX and Windows. On Windows, .. is resolved lexically (aka without reference to the filesystem) whereas on POSIX systems it's essentially a symlink that can take you anywhere in the filesystem. It's not possible to resolve this dissonance so maybe we shouldn't hide it.

  3. ChrisDenton commented on Jan 11, 2022

    @ChrisDenton
    MemberAuthor

    Should we prepend the current directory, or skip that step? The user can typically join with the current directory afterwards.

    I feel this is mistaken. On Windows, when you pass a path to File::open or other fs operation, there is a fair amount of parsing done to get the "real" absolute path which is then passed to the kernel. It is often desirable to know exactly what path is actually being used to avoid surprises.

    Here are some examples of the potential differences between using absolute and Path::join. I'm using cmd.exe which initially sets the current directory to C:\Users\Chris. I then change the current directory to D:\Chris\rust.

    Input std::path::absolute current_dir()?.join
    aux \\.\aux D:\Chris\rust\aux
    C:file.txt C:\Users\Chris\file.txt C:file.txt
    folder.\file... .. D:\Chris\rust\folder\file D:\Chris\rust\folder.\file.. ..

    The idea of absolute is that it gives you the path the kernel will see so there are no surprises. Some of the Windows behaviour (in particular the legacy ones) can be very unintuitive. The absolute function avoids having to know much of the weirdness involved with user paths because it "knows" how to parse it the same way the OS does.

  4. golddranks commented on Aug 15, 2022

    @golddranks
    Contributor

    whereas on POSIX systems it's essentially a symlink that can take you anywhere in the filesystem.

    Could you elaborate on that? I get that /foo/a and /bar/a could point to the same directory a if, for example /bar/a is a symlink; do you mean that stripping the .. in /bar/a/.. is required to take you to the "physical" parent of the directory, /foo, thus requiring a filesystem access to resolve?

  5. ChrisDenton commented on Aug 15, 2022

    @ChrisDenton
    MemberAuthor

    Yes. sorry I worded that badly. The absolute function doesn't use the file system to resolve paths so it can't know which directory .. should resolve to. Instead, canonicalize must be used to properly resolve such paths. It's the same reason why Path::components normalizes . but not ...

  6. Zoxc commented on Mar 20, 2023

    @Zoxc
    Contributor

    Is there a particular reason this is added to the path module and not on the Path type like other path methods?

  7. ChrisDenton commented on Mar 20, 2023

    @ChrisDenton
    MemberAuthor

    Mainly just to be more or less a drop-in replacement for fs::canonicalize. And to avoid issues like: should Path::absolute take a base path? That said, I don't personally have any objection to it being a Path method.

  8. Zoxc commented on Mar 20, 2023

    @Zoxc
    Contributor

    The path module doesn't have any other path function currently, so I think adding it to Path as a drop-in for Path::canonicalize makes sense.

    Resolving .. seems like a really useful usecase too, but it's probably better to make fs::canonicalize behave better on Windows for that.

  9. Zoxc commented on Mar 24, 2023

    @Zoxc
    Contributor

    Thinking things over a bit I think we may want 2 functions.

    • absolute which does only what is necessary to convert the path into an absolute form, so no resolving of . and ... It's intended to be a fast and as pure as possible path manipulation function with no filesystem access. This way it behaves in a consistent manner with regards to ...
    • resolve which converts the path to absolute form and only fails if absolute would. Additional it resolves . and .. by best effort using filesystem access if necessary, but it keeps . and .. instead of failing. It may resolve symlinks. This would use a realpath call per .. component and GetFullPathName on Windows. This is more expensive and is intended to produce more readable paths.
  10. jyn514 commented on Apr 2, 2023

    @jyn514
    Member

    What advantage would resolve have over canonicalize? "more readable paths" on Windows seems like it would be served just as well by absolute, and on Unix you can just use canonicalize.

  11. added
    A-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`
    on Apr 2, 2023
  12. Zoxc commented on Apr 2, 2023

    @Zoxc
    Contributor

    What advantage would resolve have over canonicalize?

    It would work on Windows in more scenarios and on paths which may partially exist or not exist at all. It can avoid filesystem access if there's no .. component on Unix. It should perhaps do case and Unicode normalization however.

    "more readable paths" on Windows seems like it would be served just as well by absolute, and on Unix you can just use canonicalize.

    You seem to suggest that end user programs should call different functions on Windows and Unix. That's not great for a portable API.

  13. ChrisDenton commented on Apr 3, 2023

    @ChrisDenton
    MemberAuthor

    The path::absolute function, as it stands, gives an "OS view" of the path. By which I mean, you see essentially the same path as the OS sees right before it starts doing filesystem stuff (e.g. resolving symlinks, etc). This is useful because it helps to ensure the application and OS are interpreting the path similarly. In some situations it can also be a useful diagnostic to log the path before symlinks are resolved, albeit cleaned up as much as possible.

    Libraries could build on this primitive to provide a number of other useful functions. They can't however unbuild it. If std only provides higher level functions, then it will not allow experimenting outside of std without those libraries having to reimplement it themselves.

  14. BurntSushi commented on Sep 21, 2023

    @BurntSushi
    Member

    This is useful because it helps to ensure the application and OS are interpreting the path similarly. In some situations it can also be a useful diagnostic to log the path before symlinks are resolved, albeit cleaned up as much as possible.

    I agree this is useful. I want something close to this for implementing support for hyperlinks in ripgrep. Say, for example, a user is in /home/andrew and finds a result in /home/andrew/foo/bar.txt. The user then clicks on the hyperlinked /home/andrew/foo/bar.txt, but it winds up opening the path /home/andrew/some/deeply/nested/directory/bar.txt instead. It's the same file, but because symlinks are resolved, the path that is opened is different from the one I clicked on. This leads to a surprise, and may even lead to undesirable behavior (albeit not necessarily).

    But in order for absolute to work for the hyperlink use case, I think it would need to resolve ...

  15. 17 remaining items

  16. rfcbot commented on Apr 24, 2024

    @rfcbot

    The final comment period, with a disposition to merge, as per the review above, is now complete.

    As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

    This will be merged soon.

  17. added 3 commits that reference this issue on Apr 24, 2024
  18. added a commit that references this issue on Apr 25, 2024
  19. GrigorenkoPV commented on Jul 27, 2024

    @GrigorenkoPV
    Contributor

    Now that #124335 is merged, should this issue be closed?

  20. wmmc88 commented on May 9, 2025

    @wmmc88
    Contributor

    Mainly just to be more or less a drop-in replacement for fs::canonicalize. And to avoid issues like: should Path::absolute take a base path? That said, I don't personally have any objection to it being a Path method.

    Was there any reason why a method wasn't also introduced for Path? Sort of like how Path.canonicalize is an alias for fs::canonicalize

  21. ChrisDenton commented on May 23, 2025

    @ChrisDenton
    MemberAuthor

    I don't think there's any particular reason. It might be enough for someone to create a PR adding it and then one of the team can nominate that for libs discussion.

  22. added a commit that references this issue on Mar 3, 2026
  23. added a commit that references this issue on Mar 4, 2026
  24. added a commit that references this issue on Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCT-libs-api[DEPRECATED; DO NOT USE]disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.finished-final-comment-periodThe final comment period is finished for this PR / Issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions