Skip to content

Commit 5608707

Browse files
committed
Stabilize Path::try_exists() and improve doc
This stabilizes the `Path::try_exists()` method which returns `Result<bool, io::Error>` instead of `bool` allowing handling of errors unrelated to the file not existing. (e.g permission errors) Along with the stabilization it also: * Warns that the `exists()` method is error-prone and suggests to use the newly stabilized one. * Suggests it instead of `metadata()` to handle errors. * Mentions TOCTOU bugs to avoid false assumption that `try_exists()` is completely safe fixed version of `exists()`. * Renames the feature of still-unstable `std::fs::try_exists()` to `fs_try_exists` to avoid name conflict. The tracking issue #83186 remains open to track `fs_try_exists`.
1 parent edab34a commit 5608707

File tree

3 files changed

+17
-9
lines changed

3 files changed

+17
-9
lines changed

compiler/rustc_error_messages/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#![feature(let_chains)]
22
#![feature(once_cell)]
3-
#![feature(path_try_exists)]
43
#![feature(rustc_attrs)]
54
#![feature(type_alias_impl_trait)]
65

library/std/src/fs.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -2317,10 +2317,14 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
23172317
/// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission
23182318
/// denied on some of the parent directories.)
23192319
///
2320+
/// Note that while this avoids some pitfalls of the `exists()` method, it still can not
2321+
/// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios
2322+
/// where those bugs are not an issue.
2323+
///
23202324
/// # Examples
23212325
///
23222326
/// ```no_run
2323-
/// #![feature(path_try_exists)]
2327+
/// #![feature(fs_try_exists)]
23242328
/// use std::fs;
23252329
///
23262330
/// assert!(!fs::try_exists("does_not_exist.txt").expect("Can't check existence of file does_not_exist.txt"));
@@ -2330,7 +2334,7 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
23302334
/// [`Path::exists`]: crate::path::Path::exists
23312335
// FIXME: stabilization should modify documentation of `exists()` to recommend this method
23322336
// instead.
2333-
#[unstable(feature = "path_try_exists", issue = "83186")]
2337+
#[unstable(feature = "fs_try_exists", issue = "83186")]
23342338
#[inline]
23352339
pub fn try_exists<P: AsRef<Path>>(path: P) -> io::Result<bool> {
23362340
fs_imp::try_exists(path.as_ref())

library/std/src/path.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -2705,6 +2705,9 @@ impl Path {
27052705

27062706
/// Returns `true` if the path points at an existing entity.
27072707
///
2708+
/// Warning: this method may be error-prone, consider using [`try_exists()`] instead!
2709+
/// It also has a risk of introducing time-of-check to time-of-use (TOCTOU) bugs.
2710+
///
27082711
/// This function will traverse symbolic links to query information about the
27092712
/// destination file.
27102713
///
@@ -2721,7 +2724,9 @@ impl Path {
27212724
/// # See Also
27222725
///
27232726
/// This is a convenience function that coerces errors to false. If you want to
2724-
/// check errors, call [`fs::metadata`].
2727+
/// check errors, call [`Path::try_exists`].
2728+
///
2729+
/// [`try_exists()`]: Self::try_exists
27252730
#[stable(feature = "path_ext", since = "1.5.0")]
27262731
#[must_use]
27272732
#[inline]
@@ -2738,20 +2743,20 @@ impl Path {
27382743
/// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission
27392744
/// denied on some of the parent directories.)
27402745
///
2746+
/// Note that while this avoids some pitfalls of the `exists()` method, it still can not
2747+
/// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios
2748+
/// where those bugs are not an issue.
2749+
///
27412750
/// # Examples
27422751
///
27432752
/// ```no_run
2744-
/// #![feature(path_try_exists)]
2745-
///
27462753
/// use std::path::Path;
27472754
/// assert!(!Path::new("does_not_exist.txt").try_exists().expect("Can't check existence of file does_not_exist.txt"));
27482755
/// assert!(Path::new("/root/secret_file.txt").try_exists().is_err());
27492756
/// ```
27502757
///
27512758
/// [`exists()`]: Self::exists
2752-
// FIXME: stabilization should modify documentation of `exists()` to recommend this method
2753-
// instead.
2754-
#[unstable(feature = "path_try_exists", issue = "83186")]
2759+
#[stable(feature = "path_try_exists", since = "1.63.0")]
27552760
#[inline]
27562761
pub fn try_exists(&self) -> io::Result<bool> {
27572762
fs::try_exists(self)

0 commit comments

Comments
 (0)