{"action":"opened","issue":{"url":"https://api.github.com/repos/rust-lang/rust/issues/29008","labels_url":"https://api.github.com/repos/rust-lang/rust/issues/29008/labels{/name}","comments_url":"https://api.github.com/repos/rust-lang/rust/issues/29008/comments","events_url":"https://api.github.com/repos/rust-lang/rust/issues/29008/events","html_url":"https://github.com/rust-lang/rust/issues/29008","id":111077915,"number":29008,"title":"No way to strip a trailing empty path component","user":{"login":"aidanhs","id":1050652,"avatar_url":"https://avatars.githubusercontent.com/u/1050652?v=3","gravatar_id":"","url":"https://api.github.com/users/aidanhs","html_url":"https://github.com/aidanhs","followers_url":"https://api.github.com/users/aidanhs/followers","following_url":"https://api.github.com/users/aidanhs/following{/other_user}","gists_url":"https://api.github.com/users/aidanhs/gists{/gist_id}","starred_url":"https://api.github.com/users/aidanhs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aidanhs/subscriptions","organizations_url":"https://api.github.com/users/aidanhs/orgs","repos_url":"https://api.github.com/users/aidanhs/repos","events_url":"https://api.github.com/users/aidanhs/events{/privacy}","received_events_url":"https://api.github.com/users/aidanhs/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-10-13T00:11:19Z","updated_at":"2015-10-13T00:11:19Z","closed_at":null,"body":"Given:\r\n```\r\nuse std::path::{Path, PathBuf};\r\n\r\nfn main() {\r\n    let mut p = PathBuf::from(\"/a/b/c\");\r\n    println!(\"{:?} {:?}\", p, p.file_name());\r\n    p.push(\"\");\r\n    println!(\"{:?} {:?}\", p, p.file_name());\r\n    p.push(\"\");\r\n    println!(\"{:?} {:?}\", p, p.file_name());\r\n    p.pop();\r\n    println!(\"{:?} {:?}\", p, p.file_name());\r\n\r\n    p = PathBuf::from(\"/\");\r\n    println!(\"{:?} {:?}\", p, p.file_name());\r\n    p.push(\"\");\r\n    println!(\"{:?} {:?}\", p, p.file_name());\r\n    p.push(\"\");\r\n    println!(\"{:?} {:?}\", p, p.file_name());\r\n    p.pop();\r\n    println!(\"{:?} {:?}\", p, p.file_name());\r\n}\r\n```\r\nYou get:\r\n```\r\n\"/a/b/c\" Some(\"c\")\r\n\"/a/b/c/\" Some(\"c\")\r\n\"/a/b/c/\" Some(\"c\")\r\n\"/a/b\" Some(\"b\")\r\n\"/\" None\r\n\"/\" None\r\n\"/\" None\r\n\"/\" None\r\n```\r\nhttp://is.gd/XbyUdj\r\n\r\nFirst, 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?\r\nLooking 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.\r\n\r\nThere'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(\"\")`)!\r\n\r\nI'm unsure what the intended behaviour is here and what needs fixing (implementation or docs).\r\nGiven 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?"}}