diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index aec089f7e5c22..f0b6068e06c0f 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -186,14 +186,24 @@ pub fn chdir(p: &path::Path) -> io::Result<()> { if result == 0 { Ok(()) } else { Err(io::Error::last_os_error()) } } -pub type SplitPaths<'a> = impl Iterator; +// This can't just be `impl Iterator` because that requires `'a` to be live on +// drop (see #146045). +pub type SplitPaths<'a> = iter::Map< + slice::Split<'a, u8, impl FnMut(&u8) -> bool + 'static>, + impl FnMut(&[u8]) -> PathBuf + 'static, +>; #[define_opaque(SplitPaths)] pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> { - unparsed - .as_bytes() - .split(|&b| b == PATH_SEPARATOR) - .map(|part| PathBuf::from(OsStr::from_bytes(part))) + fn is_separator(&b: &u8) -> bool { + b == PATH_SEPARATOR + } + + fn into_pathbuf(part: &[u8]) -> PathBuf { + PathBuf::from(OsStr::from_bytes(part)) + } + + unparsed.as_bytes().split(is_separator).map(into_pathbuf) } #[derive(Debug)] diff --git a/tests/ui/type-alias-impl-trait/split-paths-may-dangle.rs b/tests/ui/type-alias-impl-trait/split-paths-may-dangle.rs new file mode 100644 index 0000000000000..61c5342cdbb94 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/split-paths-may-dangle.rs @@ -0,0 +1,11 @@ +// Regression test for issue #146045 - ensure that the TAIT `SplitPaths` does not +// require the borrowed string to be live. +//@ check-pass +//@ edition:2015 + +pub fn repro() -> Option { + let unparsed = std::ffi::OsString::new(); + std::env::split_paths(&unparsed).next() +} + +fn main() {}