Skip to content

stdlib Path has inconsistent normalisation behaviour #29008

Description

@aidanhs

Given:

use std::path::{Path, PathBuf};

fn main() {
    let mut p = PathBuf::from("/a/b/c");
    println!("{:?} {:?}", p, p.file_name());
    p.push("");
    println!("{:?} {:?}", p, p.file_name());
    p.push("");
    println!("{:?} {:?}", p, p.file_name());
    p.pop();
    println!("{:?} {:?}", p, p.file_name());

    p = PathBuf::from("/");
    println!("{:?} {:?}", p, p.file_name());
    p.push("");
    println!("{:?} {:?}", p, p.file_name());
    p.push("");
    println!("{:?} {:?}", p, p.file_name());
    p.pop();
    println!("{:?} {:?}", p, p.file_name());
}

You get:

"/a/b/c" Some("c")
"/a/b/c/" Some("c")
"/a/b/c/" Some("c")
"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/a/b" Some("b")
"/" None
"/" None
"/" None
"/" None

http://is.gd/XbyUdj

First, the documentation is misleading (wrong?). file_name (https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.file_name) is documented as "The final component of the path, if it is a normal file.", but it's returning the directory when there's a trailing slash, which is not (by my book) a normal file?
Looking at the implementation of components it will return the final component of the path unless it is the root directory or a relative component. Maybe it just needs clarifying.

There's a stranger issue with normalisation of trailing slashes. Initially I thought it should be documented (https://doc.rust-lang.org/std/path/index.html#normalization), because trailing slashes are ignored by components(). However, unlike any other normalisation, it is possible to reconstruct the original path (by doing .push(""))!

I'm unsure what the intended behaviour is here and what needs fixing (implementation or docs).
Given stabilisation, I'm going to assume that implemented behaviour wins at this point? It's slightly irritating because being able to detect a trailing slash can be useful (as rsync does). Failing that I might be tempted to make .push("") do nothing - this uncertain state with trailing slashes is strange. Is there an RFC I can look at maybe?

Activity

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

Metadata

Metadata

Assignees

Labels

A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsC-bugCategory: This is a bug.E-mediumCall for participation: Medium difficulty. Experience needed to fix: Intermediate.P-mediumMedium priorityT-libs-api[DEPRECATED; DO NOT USE]

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions