Skip to content

stdlib Path has inconsistent normalisation behaviour #29008

Closed
@aidanhs

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")
"/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?

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-apiRelevant to the library API team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions