From 4750ec7ba03a5499e9777a06172d00378a5649a5 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 11 Sep 2026 14:35:59 +0000 Subject: [PATCH] Fix `*_trailing_sep` for Windows verbatim paths --- library/std/src/path.rs | 6 ++++-- library/std/tests/path.rs | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 141bc72fb2e42..f06625613ec00 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2983,7 +2983,8 @@ impl Path { #[must_use] #[inline] pub fn has_trailing_sep(&self) -> bool { - self.as_os_str().as_encoded_bytes().last().copied().is_some_and(is_sep_byte) + let comps = self.components(); + self.as_os_str().as_encoded_bytes().last().copied().is_some_and(|b| comps.is_sep_byte(b)) } /// Ensures that a path has a trailing [separator](MAIN_SEPARATOR), @@ -3034,10 +3035,11 @@ impl Path { #[must_use] #[inline] pub fn trim_trailing_sep(&self) -> &Path { + let comps = self.components(); if self.has_trailing_sep() && (!self.has_root() || self.parent().is_some()) { let mut bytes = self.inner.as_encoded_bytes(); while let Some((last, init)) = bytes.split_last() - && is_sep_byte(*last) + && comps.is_sep_byte(*last) { bytes = init; } diff --git a/library/std/tests/path.rs b/library/std/tests/path.rs index 4d42437fbd871..10bfe9eb2bd6c 100644 --- a/library/std/tests/path.rs +++ b/library/std/tests/path.rs @@ -2597,3 +2597,20 @@ fn test_trim_trailing_sep() { assert_eq!(Path::new("c:..\\\\").trim_trailing_sep().as_os_str(), OsStr::new("c:..")); } } + +#[cfg(windows)] +#[test] +fn trailing_sep_verbatim() { + assert_eq!(Path::new(r"\\?\C:\path").has_trailing_sep(), false); + assert_eq!(Path::new(r"\\?\C:\path/").has_trailing_sep(), false); + assert_eq!(Path::new(r"\\?\C:\path\").has_trailing_sep(), true); + assert_eq!(Path::new(r"\\?\C:\").has_trailing_sep(), true); + assert_eq!(Path::new(r"\\?\C:/").has_trailing_sep(), false); + + assert_eq!(Path::new(r"\\?\C:\path").trim_trailing_sep(), Path::new(r"\\?\C:\path")); + assert_eq!(Path::new(r"\\?\C:\path/").trim_trailing_sep(), Path::new(r"\\?\C:\path/")); + assert_eq!(Path::new(r"\\?\C:\path\").trim_trailing_sep(), Path::new(r"\\?\C:\path")); + assert_eq!(Path::new(r"\\?\C:\path/\\\").trim_trailing_sep(), Path::new(r"\\?\C:\path/")); + assert_eq!(Path::new(r"\\?\C:\").trim_trailing_sep(), Path::new(r"\\?\C:\")); + assert_eq!(Path::new(r"\\?\C:/").trim_trailing_sep(), Path::new(r"\\?\C:/")); +}