diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 29415973ed073..ec36c642733fb 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -22,7 +22,7 @@ use rustc_session::config::{self, CrateType, Lto}; use tracing::{debug, info}; use std::ffi::{CStr, CString}; -use std::fs::File; +use std::fs::{self, File}; use std::io; use std::path::Path; use std::ptr; @@ -497,7 +497,7 @@ fn thin_lto( // reading the file, then we'll just use `None` as the // prev_key_map, which will force the code to be recompiled. let prev = - if path.exists() { ThinLTOKeysMap::load_from_file(&path).ok() } else { None }; + if fs::exists(&path) { ThinLTOKeysMap::load_from_file(&path).ok() } else { None }; let curr = ThinLTOKeysMap::from_thin_lto_modules(&data, &thin_modules, &module_names); (Some(path), prev, curr) } else { diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index c477ac6462acb..50519e93bf6e4 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -1,6 +1,7 @@ use rustc_session::Session; use rustc_span::symbol::Symbol; +use std::fs; use std::io; use std::path::{Path, PathBuf}; @@ -14,12 +15,12 @@ pub fn find_library(name: Symbol, search_paths: &[PathBuf], sess: &Session) -> P for path in search_paths { debug!("looking for {} inside {:?}", name, path); let test = path.join(&oslibname); - if test.exists() { + if fs::exists(&test) { return test; } if oslibname != unixlibname { let test = path.join(&unixlibname); - if test.exists() { + if fs::exists(&test) { return test; } } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 55fddb38e10be..0cd126996b4d2 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1110,19 +1110,19 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) { fn get_object_file_path(sess: &Session, name: &str, self_contained: bool) -> PathBuf { let fs = sess.target_filesearch(PathKind::Native); let file_path = fs.get_lib_path().join(name); - if file_path.exists() { + if fs::exists(&file_path) { return file_path; } // Special directory with objects used only in self-contained linkage mode if self_contained { let file_path = fs.get_self_contained_lib_path().join(name); - if file_path.exists() { + if fs::exists(&file_path) { return file_path; } } for search_path in fs.search_paths() { let file_path = search_path.dir.join(name); - if file_path.exists() { + if fs::exists(&file_path) { return file_path; } } @@ -1312,7 +1312,7 @@ fn detect_self_contained_mingw(sess: &Session) -> bool { for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) { let full_path = dir.join(&linker_with_extension); // If linker comes from sysroot assume self-contained mode - if full_path.is_file() && !full_path.starts_with(&sess.sysroot) { + if fs::is_file(&full_path) && !full_path.starts_with(&sess.sysroot) { return false; } } @@ -2228,7 +2228,7 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result { if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") => {} // Ignore `SDKROOT` if it's not a valid path. - _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {} + _ if !p.is_absolute() || p == Path::new("/") || !fs::exists(p) => {} _ => return Ok(sdkroot), } } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 3df956c465e5e..a3cc116c29318 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -695,7 +695,7 @@ impl<'a> Linker for MsvcLinker<'a> { // check to see if the file is there and just omit linking to it if it's // not present. let name = format!("{}.dll.lib", lib); - if fs::metadata(&path.join(&name)).is_ok() { + if fs::exists(&path.join(&name)) { self.cmd.arg(name); } } diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs index 7742961e65dbb..87e97c746ef56 100644 --- a/compiler/rustc_fs_util/src/lib.rs +++ b/compiler/rustc_fs_util/src/lib.rs @@ -62,8 +62,10 @@ pub enum LinkOrCopy { pub fn link_or_copy, Q: AsRef>(p: P, q: Q) -> io::Result { let p = p.as_ref(); let q = q.as_ref(); - if q.exists() { - fs::remove_file(&q)?; + match fs::remove_file(&q) { + Ok(()) => (), + Err(err) if err.kind() == io::ErrorKind::NotFound => (), + Err(err) => return Err(err), } match fs::hard_link(p, q) { diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index e185ee24d171b..c86122f89392d 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -52,11 +52,11 @@ pub fn read_file( path: &Path, nightly_build: bool, ) -> io::Result, usize)>> { - if !path.exists() { - return Ok(None); - } - - let data = fs::read(path)?; + let data = match fs::read(path) { + Ok(data) => data, + Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(None), + Err(err) => return Err(err), + }; let mut file = io::Cursor::new(data); diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 9fdf0a56d9de1..45c2bbe7ad5bb 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -205,7 +205,7 @@ pub fn prepare_session_directory( // because, on windows, long paths can cause problems; // canonicalization inserts this weird prefix that makes windows // tolerate long paths. - let crate_dir = match crate_dir.canonicalize() { + let crate_dir = match std_fs::canonicalize(&crate_dir) { Ok(v) => v, Err(err) => { sess.err(&format!( @@ -387,7 +387,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) { } pub fn delete_all_session_dir_contents(sess: &Session) -> io::Result<()> { - let sess_dir_iterator = sess.incr_comp_session_dir().read_dir()?; + let sess_dir_iterator = std_fs::read_dir(&*sess.incr_comp_session_dir())?; for entry in sess_dir_iterator { let entry = entry?; safe_remove_file(&entry.path())? @@ -412,7 +412,7 @@ fn copy_files(sess: &Session, target_dir: &Path, source_dir: &Path) -> Result it, Err(_) => return Err(()), }; @@ -534,8 +534,7 @@ fn find_source_directory( crate_dir: &Path, source_directories_already_tried: &FxHashSet, ) -> Option { - let iter = crate_dir - .read_dir() + let iter = std_fs::read_dir(crate_dir) .unwrap() // FIXME .filter_map(|e| e.ok().map(|e| e.path())); @@ -670,7 +669,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> { let mut session_directories = FxHashSet::default(); let mut lock_files = FxHashSet::default(); - for dir_entry in crate_directory.read_dir()? { + for dir_entry in std_fs::read_dir(crate_directory)? { let dir_entry = match dir_entry { Ok(dir_entry) => dir_entry, _ => { @@ -922,22 +921,24 @@ fn all_except_most_recent( /// before passing it to std::fs::remove_dir_all(). This will convert the path /// into the '\\?\' format, which supports much longer paths. fn safe_remove_dir_all(p: &Path) -> io::Result<()> { - if p.exists() { - let canonicalized = p.canonicalize()?; - std_fs::remove_dir_all(canonicalized) - } else { - Ok(()) - } + let canonicalized = match std_fs::canonicalize(p) { + Ok(canonicalized) => canonicalized, + Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(()), + Err(err) => return Err(err), + }; + + std_fs::remove_dir_all(canonicalized) } fn safe_remove_file(p: &Path) -> io::Result<()> { - if p.exists() { - let canonicalized = p.canonicalize()?; - match std_fs::remove_file(canonicalized) { - Err(ref err) if err.kind() == io::ErrorKind::NotFound => Ok(()), - result => result, - } - } else { - Ok(()) + let canonicalized = match std_fs::canonicalize(p) { + Ok(canonicalized) => canonicalized, + Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(()), + Err(err) => return Err(err), + }; + + match std_fs::remove_file(canonicalized) { + Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(()), + result => result, } } diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 35428dc8d84e5..c6319599b5692 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -8,6 +8,7 @@ use rustc_middle::ty::TyCtxt; use rustc_serialize::opaque::Decoder; use rustc_serialize::Decodable as RustcDecodable; use rustc_session::Session; +use std::fs; use std::path::Path; use super::data::*; @@ -142,7 +143,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { let mut all_files_exist = true; if let Some(ref file_name) = swp.work_product.saved_file { let path = in_incr_comp_dir_sess(sess, file_name); - if !path.exists() { + if !fs::exists(&path) { all_files_exist = false; if sess.opts.debugging_opts.incremental_info { diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 102a77e8e79a7..1d2219af42db0 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -5,8 +5,8 @@ use rustc_middle::ty::TyCtxt; use rustc_serialize::opaque::Encoder; use rustc_serialize::Encodable as RustcEncodable; use rustc_session::Session; -use std::fs; use std::path::PathBuf; +use std::{fs, io}; use super::data::*; use super::dirty_clean; @@ -73,11 +73,9 @@ pub fn save_work_product_index( for (id, wp) in previous_work_products.iter() { if !new_work_products.contains_key(id) { work_product::delete_workproduct_files(sess, wp); - debug_assert!( - wp.saved_file.as_ref().map_or(true, |file_name| { - !in_incr_comp_dir_sess(sess, &file_name).exists() - }) - ); + debug_assert!(wp.saved_file.as_ref().map_or(true, |file_name| { + !fs::exists(in_incr_comp_dir_sess(sess, &file_name)) + })); } } @@ -87,7 +85,7 @@ pub fn save_work_product_index( .iter() .flat_map(|(_, wp)| wp.saved_file.iter()) .map(|name| in_incr_comp_dir_sess(sess, name)) - .all(|path| path.exists()) + .all(|path| fs::exists(path)) }); } @@ -101,19 +99,18 @@ where // Note: It's important that we actually delete the old file and not just // truncate and overwrite it, since it might be a shared hard-link, the // underlying data of which we don't want to modify - if path_buf.exists() { - match fs::remove_file(&path_buf) { - Ok(()) => { - debug!("save: remove old file"); - } - Err(err) => { - sess.err(&format!( - "unable to delete old dep-graph at `{}`: {}", - path_buf.display(), - err - )); - return; - } + match fs::remove_file(&path_buf) { + Ok(()) => { + debug!("save: remove old file"); + } + Err(err) if err.kind() == io::ErrorKind::NotFound => (), + Err(err) => { + sess.err(&format!( + "unable to delete old dep-graph at `{}`: {}", + path_buf.display(), + err + )); + return; } } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 461ee08592275..4994d62fd3389 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -506,18 +506,18 @@ where } fn output_contains_path(output_paths: &[PathBuf], input_path: &PathBuf) -> bool { - let input_path = input_path.canonicalize().ok(); + let input_path = fs::canonicalize(input_path).ok(); if input_path.is_none() { return false; } let check = |output_path: &PathBuf| { - if output_path.canonicalize().ok() == input_path { Some(()) } else { None } + if fs::canonicalize(output_path).ok() == input_path { Some(()) } else { None } }; check_output(output_paths, check).is_some() } fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option { - let check = |output_path: &PathBuf| output_path.is_dir().then(|| output_path.clone()); + let check = |output_path: &PathBuf| fs::is_dir(output_path).then(|| output_path.clone()); check_output(output_paths, check) } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index f34990a1a1037..533534aa57285 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -25,6 +25,7 @@ use rustc_span::symbol::{sym, Symbol}; use smallvec::SmallVec; use std::env; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; +use std::fs; use std::io; use std::lazy::SyncOnceCell; use std::mem; @@ -269,14 +270,14 @@ fn get_rustc_path_inner(bin_path: &str) -> Option { } else { "rustc" }); - candidate.exists().then_some(candidate) + fs::exists(&candidate).then_some(candidate) }) } fn sysroot_candidates() -> Vec { let target = session::config::host_triple(); let mut sysroot_candidates = vec![filesearch::get_or_default_sysroot()]; - let path = current_dll_path().and_then(|s| s.canonicalize().ok()); + let path = current_dll_path().and_then(|s| fs::canonicalize(s).ok()); if let Some(dll) = path { // use `parent` twice to chop off the file name and then also the // directory containing the dll which should be either `lib` or `bin`. @@ -397,7 +398,7 @@ pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box fn() -> Box CrateLocator<'a> { // as well. if let Some((prev, _)) = &ret { let sysroot = &self.sess.sysroot; - let sysroot = sysroot.canonicalize().unwrap_or_else(|_| sysroot.to_path_buf()); + let sysroot = fs::canonicalize(sysroot).unwrap_or_else(|_| sysroot.to_path_buf()); if prev.starts_with(&sysroot) { continue; } @@ -664,7 +664,7 @@ impl<'a> CrateLocator<'a> { let mut rmetas = FxHashMap::default(); let mut dylibs = FxHashMap::default(); for loc in &self.exact_paths { - if !loc.exists() { + if !fs::exists(loc) { return Err(CrateError::ExternLocationNotExist(self.crate_name, loc.clone())); } let file = match loc.file_name().and_then(|s| s.to_str()) { @@ -738,7 +738,7 @@ fn get_metadata_section( filename: &Path, loader: &dyn MetadataLoader, ) -> Result { - if !filename.exists() { + if !fs::exists(filename) { return Err(format!("no such file: '{}'", filename.display())); } let raw_bytes: MetadataRef = match flavor { diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 3a757e5f0075d..f1eb464f7eb57 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -154,7 +154,7 @@ fn find_libdir(sysroot: &Path) -> Cow<'static, str> { match option_env!("CFG_LIBDIR_RELATIVE") { None | Some("lib") => { - if sysroot.join(PRIMARY_LIB_DIR).join(RUST_LIB_DIR).exists() { + if fs::exists(sysroot.join(PRIMARY_LIB_DIR).join(RUST_LIB_DIR)) { PRIMARY_LIB_DIR.into() } else { SECONDARY_LIB_DIR.into() diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index 777eea3f68d02..0d58d8357e10c 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -4,6 +4,7 @@ use crate::Session; use rustc_ast as ast; use rustc_span::symbol::sym; use rustc_span::Span; +use std::fs; use std::path::{Path, PathBuf}; pub fn out_filename( @@ -39,7 +40,7 @@ pub fn check_file_is_writeable(file: &Path, sess: &Session) { } fn is_writeable(p: &Path) -> bool { - match p.metadata() { + match fs::metadata(p) { Err(..) => true, Ok(m) => !m.permissions().readonly(), } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 509e583eca21d..d2ea09b96287d 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -33,6 +33,7 @@ use rustc_target::spec::{Target, TargetTriple, TlsModel}; use std::cell::{self, RefCell}; use std::env; use std::fmt; +use std::fs; use std::io::Write; use std::num::NonZeroU32; use std::ops::{Div, Mul}; @@ -1384,7 +1385,7 @@ pub fn build_session( let real_rust_source_base_dir = { // This is the location used by the `rust-src` `rustup` component. let mut candidate = sysroot.join("lib/rustlib/src/rust"); - if let Ok(metadata) = candidate.symlink_metadata() { + if let Ok(metadata) = fs::symlink_metadata(&candidate) { // Replace the symlink rustbuild creates, with its destination. // We could try to use `fs::canonicalize` instead, but that might // produce unnecessarily verbose path. @@ -1396,7 +1397,14 @@ pub fn build_session( } // Only use this directory if it has a file we can expect to always find. - if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None } + if fs::metadata(candidate.join("library/std/src/lib.rs")) + .map(|m| m.is_file()) + .unwrap_or(false) + { + Some(candidate) + } else { + None + } }; let asm_arch = @@ -1477,7 +1485,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) { // Make sure that any given profiling data actually exists so LLVM can't // decide to silently skip PGO. if let Some(ref path) = sess.opts.cg.profile_use { - if !path.exists() { + if !fs::exists(path) { sess.err(&format!( "File `{}` passed to `-C profile-use` does not exist.", path.display() diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index fefc0cb48ddd8..7fa9b59c096f7 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -109,7 +109,7 @@ pub struct RealFileLoader; impl FileLoader for RealFileLoader { fn file_exists(&self, path: &Path) -> bool { - fs::metadata(path).is_ok() + fs::exists(path) } fn read_file(&self, path: &Path) -> io::Result { diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 8d72df6850fc2..920b3590bc1a1 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1600,14 +1600,14 @@ impl Target { for dir in env::split_paths(&target_path) { let p = dir.join(&path); - if p.is_file() { + if fs::is_file(&p) { return load_file(&p); } } Err(format!("Could not find specification for target {:?}", target_triple)) } TargetTriple::TargetPath(ref target_path) => { - if target_path.is_file() { + if fs::is_file(target_path) { return load_file(&target_path); } Err(format!("Target path {:?} is not a valid file", target_path)) @@ -1796,7 +1796,7 @@ impl TargetTriple { /// Creates a target triple from the passed target path. pub fn from_path(path: &Path) -> Result { - let canonicalized_path = path.canonicalize()?; + let canonicalized_path = std::fs::canonicalize(path)?; Ok(TargetTriple::TargetPath(canonicalized_path)) } diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index e2d4f2e6a56af..00e8e2a6dfdf9 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2108,6 +2108,92 @@ pub fn set_permissions>(path: P, perm: Permissions) -> io::Result fs_imp::set_perm(path.as_ref(), perm.0) } +/// Returns `true` if the path points at an existing entity. +/// +/// This function will traverse symbolic links to query information about the +/// destination file. In case of broken symbolic links this will return `false`. +/// +/// If you cannot access the directory containing the file, e.g., because of a +/// permission error, this will return `false`. +/// +/// # Examples +/// +/// ```no_run +/// use std::path::Path; +/// assert!(!Path::new("does_not_exist.txt").exists()); +/// ``` +/// +/// # See Also +/// +/// This is a convenience function that coerces errors to false. If you want to +/// check errors, call [`metadata`]. +#[stable(feature = "fs_path_convenience", since = "1.51.0")] +pub fn exists>(path: P) -> bool { + metadata(path).is_ok() +} + +/// Returns `true` if the path exists on disk and is pointing at a regular file. +/// +/// This function will traverse symbolic links to query information about the +/// destination file. In case of broken symbolic links this will return `false`. +/// +/// If you cannot access the directory containing the file, e.g., because of a +/// permission error, this will return `false`. +/// +/// # Examples +/// +/// ```no_run +/// use std::path::Path; +/// assert_eq!(Path::new("./is_a_directory/").is_file(), false); +/// assert_eq!(Path::new("a_file.txt").is_file(), true); +/// ``` +/// +/// # See Also +/// +/// This is a convenience function that coerces errors to false. If you want to +/// check errors, call [`metadata`] and handle its [`Result`]. Then call +/// [`Metadata::is_file`] if it was [`Ok`]. +/// +/// When the goal is simply to read from (or write to) the source, the most +/// reliable way to test the source can be read (or written to) is to open +/// it. Only using `is_file` can break workflows like `diff <( prog_a )` on +/// a Unix-like system for example. See [`File::open`] or +/// [`OpenOptions::open`] for more information. +#[stable(feature = "fs_path_convenience", since = "1.51.0")] +pub fn is_file>(path: P) -> bool { + metadata(path).map(|m| m.is_file()).unwrap_or(false) +} + +/// Returns `true` if the path exists on disk and is pointing at a directory. +/// +/// This function will traverse symbolic links to query information about the +/// destination file. In case of broken symbolic links this will return `false`. +/// +/// If you cannot access the directory containing the file, e.g., because of a +/// permission error, this will return `false`. +/// +/// # Examples +/// +/// ```no_run +/// use std::path::Path; +/// assert_eq!(Path::new("./is_a_directory/").is_dir(), true); +/// assert_eq!(Path::new("a_file.txt").is_dir(), false); +/// ``` +/// +/// # See Also +/// +/// This is a convenience function that coerces errors to false. If you want to +/// check errors, call [`metadata`] and handle its [`Result`]. Then call +/// [`Metadata::is_dir`] if it was [`Ok`]. +/// +/// When the goal is simply to read from the source, the most reliable way to +/// test the source can be read is to open it. See [`read_dir`] for more +/// information. +#[stable(feature = "fs_path_convenience", since = "1.51.0")] +pub fn is_dir>(path: P) -> bool { + metadata(path).map(|m| m.is_dir()).unwrap_or(false) +} + impl DirBuilder { /// Creates a new set of options with default mode/security settings for all /// platforms and also non-recursive. @@ -2160,7 +2246,7 @@ impl DirBuilder { /// .recursive(true) /// .create(path).unwrap(); /// - /// assert!(fs::metadata(path).unwrap().is_dir()); + /// assert!(fs::is_dir(path)); /// ``` #[stable(feature = "dir_builder", since = "1.6.0")] pub fn create>(&self, path: P) -> io::Result<()> { @@ -2179,7 +2265,7 @@ impl DirBuilder { match self.inner.mkdir(path) { Ok(()) => return Ok(()), Err(ref e) if e.kind() == io::ErrorKind::NotFound => {} - Err(_) if path.is_dir() => return Ok(()), + Err(_) if is_dir(path) => return Ok(()), Err(e) => return Err(e), } match path.parent() { @@ -2190,7 +2276,7 @@ impl DirBuilder { } match self.inner.mkdir(path) { Ok(()) => Ok(()), - Err(_) if path.is_dir() => Ok(()), + Err(_) if is_dir(path) => Ok(()), Err(e) => Err(e), } } diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 5c969741592e6..34eda393dbae5 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -397,10 +397,8 @@ fn file_test_stat_is_correct_on_is_file() { let fstat_res = check!(fs.metadata()); assert!(fstat_res.is_file()); } - let stat_res_fn = check!(fs::metadata(filename)); - assert!(stat_res_fn.is_file()); - let stat_res_meth = check!(filename.metadata()); - assert!(stat_res_meth.is_file()); + let stat_res = check!(fs::metadata(filename)); + assert!(stat_res.is_file()); check!(fs::remove_file(filename)); } @@ -409,10 +407,8 @@ fn file_test_stat_is_correct_on_is_dir() { let tmpdir = tmpdir(); let filename = &tmpdir.join("file_stat_correct_on_is_dir"); check!(fs::create_dir(filename)); - let stat_res_fn = check!(fs::metadata(filename)); - assert!(stat_res_fn.is_dir()); - let stat_res_meth = check!(filename.metadata()); - assert!(stat_res_meth.is_dir()); + let stat_res = check!(fs::metadata(filename)); + assert!(stat_res.is_dir()); check!(fs::remove_dir(filename)); } @@ -421,7 +417,7 @@ fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() { let tmpdir = tmpdir(); let dir = &tmpdir.join("fileinfo_false_on_dir"); check!(fs::create_dir(dir)); - assert!(!dir.is_file()); + assert!(!fs::is_file(dir)); check!(fs::remove_dir(dir)); } @@ -430,21 +426,20 @@ fn file_test_fileinfo_check_exists_before_and_after_file_creation() { let tmpdir = tmpdir(); let file = &tmpdir.join("fileinfo_check_exists_b_and_a.txt"); check!(check!(File::create(file)).write(b"foo")); - assert!(file.exists()); + assert!(fs::exists(file)); check!(fs::remove_file(file)); - assert!(!file.exists()); + assert!(!fs::exists(file)); } #[test] fn file_test_directoryinfo_check_exists_before_and_after_mkdir() { let tmpdir = tmpdir(); let dir = &tmpdir.join("before_and_after_dir"); - assert!(!dir.exists()); + assert!(!fs::exists(dir)); check!(fs::create_dir(dir)); - assert!(dir.exists()); - assert!(dir.is_dir()); + assert!(fs::is_dir(dir)); check!(fs::remove_dir(dir)); - assert!(!dir.exists()); + assert!(!fs::exists(dir)); } #[test] @@ -499,7 +494,7 @@ fn recursive_mkdir() { let tmpdir = tmpdir(); let dir = tmpdir.join("d1/d2"); check!(fs::create_dir_all(&dir)); - assert!(dir.is_dir()) + assert!(fs::is_dir(dir)); } #[test] @@ -567,8 +562,8 @@ fn recursive_rmdir() { let _ = symlink_file(&canary, &d1.join("canary")); check!(fs::remove_dir_all(&d1)); - assert!(!d1.is_dir()); - assert!(canary.exists()); + assert!(!fs::is_dir(d1)); + assert!(fs::exists(canary)); } #[test] @@ -583,8 +578,8 @@ fn recursive_rmdir_of_symlink() { check!(symlink_junction(&dir, &link)); check!(fs::remove_dir_all(&link)); - assert!(!link.is_dir()); - assert!(canary.exists()); + assert!(!fs::is_dir(link)); + assert!(fs::exists(canary)); } #[test] @@ -608,34 +603,33 @@ fn recursive_rmdir_of_file_symlink() { #[test] fn unicode_path_is_dir() { - assert!(Path::new(".").is_dir()); - assert!(!Path::new("test/stdtest/fs.rs").is_dir()); + assert!(fs::is_dir(Path::new("."))); + assert!(!fs::is_dir(Path::new("test/stdtest/fs.rs"))); let tmpdir = tmpdir(); let mut dirpath = tmpdir.path().to_path_buf(); dirpath.push("test-가一ー你好"); check!(fs::create_dir(&dirpath)); - assert!(dirpath.is_dir()); + assert!(fs::is_dir(&dirpath)); let mut filepath = dirpath; filepath.push("unicode-file-\u{ac00}\u{4e00}\u{30fc}\u{4f60}\u{597d}.rs"); check!(File::create(&filepath)); // ignore return; touch only - assert!(!filepath.is_dir()); - assert!(filepath.exists()); + assert!(!fs::is_dir(filepath)); } #[test] fn unicode_path_exists() { - assert!(Path::new(".").exists()); - assert!(!Path::new("test/nonexistent-bogus-path").exists()); + assert!(fs::exists(Path::new("."))); + assert!(!fs::exists(Path::new("test/nonexistent-bogus-path"))); let tmpdir = tmpdir(); let unicode = tmpdir.path(); let unicode = unicode.join("test-각丁ー再见"); check!(fs::create_dir(&unicode)); - assert!(unicode.exists()); - assert!(!Path::new("test/unicode-bogus-path-각丁ー再见").exists()); + assert!(fs::exists(unicode)); + assert!(!fs::exists(Path::new("test/unicode-bogus-path-각丁ー再见"))); } #[test] @@ -646,8 +640,8 @@ fn copy_file_does_not_exist() { match fs::copy(&from, &to) { Ok(..) => panic!(), Err(..) => { - assert!(!from.exists()); - assert!(!to.exists()); + assert!(!fs::exists(from)); + assert!(!fs::exists(to)); } } } @@ -659,7 +653,7 @@ fn copy_src_does_not_exist() { let to = tmpdir.join("out.txt"); check!(check!(File::create(&to)).write(b"hello")); assert!(fs::copy(&from, &to).is_err()); - assert!(!from.exists()); + assert!(!fs::exists(from)); let mut v = Vec::new(); check!(check!(File::open(&to)).read_to_end(&mut v)); assert_eq!(v, b"hello"); @@ -677,7 +671,7 @@ fn copy_file_ok() { check!(check!(File::open(&out)).read_to_end(&mut v)); assert_eq!(v, b"hello"); - assert_eq!(check!(input.metadata()).permissions(), check!(out.metadata()).permissions()); + assert_eq!(check!(fs::metadata(input)).permissions(), check!(fs::metadata(out)).permissions()); } #[test] @@ -716,7 +710,7 @@ fn copy_file_src_dir() { Ok(..) => panic!(), Err(..) => {} } - assert!(!out.exists()); + assert!(!fs::exists(out)); } #[test] @@ -730,7 +724,7 @@ fn copy_file_preserves_perm_bits() { p.set_readonly(true); check!(fs::set_permissions(&input, p)); check!(fs::copy(&input, &out)); - assert!(check!(out.metadata()).permissions().readonly()); + assert!(check!(fs::metadata(&out)).permissions().readonly()); check!(fs::set_permissions(&input, attr.permissions())); check!(fs::set_permissions(&out, attr.permissions())); } @@ -741,7 +735,7 @@ fn copy_file_preserves_streams() { let tmp = tmpdir(); check!(check!(File::create(tmp.join("in.txt:bunny"))).write("carrot".as_bytes())); assert_eq!(check!(fs::copy(tmp.join("in.txt"), tmp.join("out.txt"))), 0); - assert_eq!(check!(tmp.join("out.txt").metadata()).len(), 0); + assert_eq!(check!(fs::metadata(tmp.join("out.txt"))).len(), 0); let mut v = Vec::new(); check!(check!(File::open(tmp.join("out.txt:bunny"))).read_to_end(&mut v)); assert_eq!(v, b"carrot".to_vec()); @@ -756,7 +750,7 @@ fn copy_file_returns_metadata_len() { #[cfg(windows)] check!(check!(File::create(tmp.join("in.txt:bunny"))).write(b"carrot")); let copied_len = check!(fs::copy(&in_path, &out_path)); - assert_eq!(check!(out_path.metadata()).len(), copied_len); + assert_eq!(check!(fs::metadata(out_path)).len(), copied_len); } #[test] @@ -776,7 +770,7 @@ fn copy_file_follows_dst_symlink() { check!(fs::copy(&in_path, &out_path_symlink)); - assert!(check!(out_path_symlink.symlink_metadata()).file_type().is_symlink()); + assert!(check!(fs::symlink_metadata(&out_path_symlink)).file_type().is_symlink()); assert_eq!(check!(fs::read(&out_path_symlink)), b"foo".to_vec()); assert_eq!(check!(fs::read(&out_path)), b"foo".to_vec()); } @@ -793,7 +787,7 @@ fn symlinks_work() { check!(check!(File::create(&input)).write("foobar".as_bytes())); check!(symlink_file(&input, &out)); - assert!(check!(out.symlink_metadata()).file_type().is_symlink()); + assert!(check!(fs::symlink_metadata(&out)).file_type().is_symlink()); assert_eq!(check!(fs::metadata(&out)).len(), check!(fs::metadata(&input)).len()); let mut v = Vec::new(); check!(check!(File::open(&out)).read_to_end(&mut v)); @@ -860,7 +854,6 @@ fn links_work() { check!(check!(File::create(&input)).write("foobar".as_bytes())); check!(fs::hard_link(&input, &out)); assert_eq!(check!(fs::metadata(&out)).len(), check!(fs::metadata(&input)).len()); - assert_eq!(check!(fs::metadata(&out)).len(), check!(input.metadata()).len()); let mut v = Vec::new(); check!(check!(File::open(&out)).read_to_end(&mut v)); assert_eq!(v, b"foobar".to_vec()); @@ -1196,7 +1189,7 @@ fn realpath_works() { symlink_file(&file, &link).unwrap(); symlink_dir(&dir, &linkdir).unwrap(); - assert!(link.symlink_metadata().unwrap().file_type().is_symlink()); + assert!(fs::symlink_metadata(&link).unwrap().file_type().is_symlink()); assert_eq!(fs::canonicalize(&tmpdir).unwrap(), tmpdir); assert_eq!(fs::canonicalize(&file).unwrap(), file); @@ -1243,7 +1236,7 @@ fn dir_entry_methods() { fs::create_dir_all(&tmpdir.join("a")).unwrap(); File::create(&tmpdir.join("b")).unwrap(); - for file in tmpdir.path().read_dir().unwrap().map(|f| f.unwrap()) { + for file in fs::read_dir(tmpdir.path()).unwrap().map(|f| f.unwrap()) { let fname = file.file_name(); match fname.to_str() { Some("a") => { @@ -1263,7 +1256,7 @@ fn dir_entry_methods() { fn dir_entry_debug() { let tmpdir = tmpdir(); File::create(&tmpdir.join("b")).unwrap(); - let mut read_dir = tmpdir.path().read_dir().unwrap(); + let mut read_dir = fs::read_dir(tmpdir.path()).unwrap(); let dir_entry = read_dir.next().unwrap().unwrap(); let actual = format!("{:?}", dir_entry); let expected = format!("DirEntry({:?})", dir_entry.0.path()); @@ -1293,16 +1286,16 @@ fn create_dir_all_with_junctions() { check!(fs::create_dir_all(&b)); // the junction itself is not a directory, but `is_dir()` on a Path // follows links - assert!(junction.is_dir()); - assert!(b.exists()); + assert!(fs::is_dir(junction)); + assert!(fs::exists(b)); if !got_symlink_permission(&tmpdir) { return; }; check!(symlink_dir(&target, &link)); check!(fs::create_dir_all(&d)); - assert!(link.is_dir()); - assert!(d.exists()); + assert!(fs::is_dir(link)); + assert!(fs::exists(d)); } #[test] diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 243761e389784..522802d49ea2d 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2305,6 +2305,11 @@ impl Path { /// println!("{:?}", metadata.file_type()); /// ``` #[stable(feature = "path_ext", since = "1.5.0")] + #[rustc_deprecated( + since = "1.51.0", + reason = "use `std::fs::metadata` instead", + suggestion = "std::fs::metadata" + )] pub fn metadata(&self) -> io::Result { fs::metadata(self) } @@ -2323,6 +2328,11 @@ impl Path { /// println!("{:?}", metadata.file_type()); /// ``` #[stable(feature = "path_ext", since = "1.5.0")] + #[rustc_deprecated( + since = "1.51.0", + reason = "use `std::fs::symlink_metadata` instead", + suggestion = "std::fs::symlink_metadata" + )] pub fn symlink_metadata(&self) -> io::Result { fs::symlink_metadata(self) } @@ -2341,6 +2351,11 @@ impl Path { /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs")); /// ``` #[stable(feature = "path_ext", since = "1.5.0")] + #[rustc_deprecated( + since = "1.51.0", + reason = "use `std::fs::canonicalize` instead", + suggestion = "std::fs::canonicalize" + )] pub fn canonicalize(&self) -> io::Result { fs::canonicalize(self) } @@ -2358,6 +2373,11 @@ impl Path { /// let path_link = path.read_link().expect("read_link call failed"); /// ``` #[stable(feature = "path_ext", since = "1.5.0")] + #[rustc_deprecated( + since = "1.51.0", + reason = "use `std::fs::read_link` instead", + suggestion = "std::fs::read_link" + )] pub fn read_link(&self) -> io::Result { fs::read_link(self) } @@ -2382,6 +2402,11 @@ impl Path { /// } /// ``` #[stable(feature = "path_ext", since = "1.5.0")] + #[rustc_deprecated( + since = "1.51.0", + reason = "use `std::fs::read_dir` instead", + suggestion = "std::fs::read_dir" + )] pub fn read_dir(&self) -> io::Result { fs::read_dir(self) } @@ -2394,6 +2419,8 @@ impl Path { /// If you cannot access the directory containing the file, e.g., because of a /// permission error, this will return `false`. /// + /// This is an alias to [`fs::exists`]. + /// /// # Examples /// /// ```no_run @@ -2406,8 +2433,13 @@ impl Path { /// This is a convenience function that coerces errors to false. If you want to /// check errors, call [`fs::metadata`]. #[stable(feature = "path_ext", since = "1.5.0")] + #[rustc_deprecated( + since = "1.51.0", + reason = "other processes may remove or rename files at any time", + suggestion = "use `std::fs::exists`" + )] pub fn exists(&self) -> bool { - fs::metadata(self).is_ok() + fs::exists(self) } /// Returns `true` if the path exists on disk and is pointing at a regular file. @@ -2426,6 +2458,8 @@ impl Path { /// assert_eq!(Path::new("a_file.txt").is_file(), true); /// ``` /// + /// This is an alias to [`fs::is_file`]. + /// /// # See Also /// /// This is a convenience function that coerces errors to false. If you want to @@ -2438,8 +2472,13 @@ impl Path { /// a Unix-like system for example. See [`fs::File::open`] or /// [`fs::OpenOptions::open`] for more information. #[stable(feature = "path_ext", since = "1.5.0")] + #[rustc_deprecated( + since = "1.51.0", + reason = "other processes may remove, rename, or replace files at any time", + suggestion = "use `std::fs::File::open` or `std::fs::is_file`" + )] pub fn is_file(&self) -> bool { - fs::metadata(self).map(|m| m.is_file()).unwrap_or(false) + fs::is_file(self) } /// Returns `true` if the path exists on disk and is pointing at a directory. @@ -2450,6 +2489,8 @@ impl Path { /// If you cannot access the directory containing the file, e.g., because of a /// permission error, this will return `false`. /// + /// This is an alias to [`fs::is_dir`]. + /// /// # Examples /// /// ```no_run @@ -2463,9 +2504,18 @@ impl Path { /// This is a convenience function that coerces errors to false. If you want to /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call /// [`fs::Metadata::is_dir`] if it was [`Ok`]. + /// + /// When the goal is simply to read from the source, the most reliable way to + /// test the source can be read is to open it. See [`fs::read_dir`] for more + /// information. #[stable(feature = "path_ext", since = "1.5.0")] + #[rustc_deprecated( + since = "1.51.0", + reason = "other processes may remove, rename, or replace directories at any time", + suggestion = "use `std::fs::read_dir` or `std::fs::is_dir`" + )] pub fn is_dir(&self) -> bool { - fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false) + fs::is_dir(self) } /// Converts a [`Box`](Box) into a [`PathBuf`] without copying or diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 243065b94b125..deca416915792 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -168,7 +168,7 @@ impl Command { let path = path .join(self.program.to_str().unwrap()) .with_extension(env::consts::EXE_EXTENSION); - if fs::metadata(&path).is_ok() { + if fs::exists(&path) { return Some(path.into_os_string()); } } diff --git a/library/std/src/sys_common/fs.rs b/library/std/src/sys_common/fs.rs index e30e8018a31fe..5b0c960f2a437 100644 --- a/library/std/src/sys_common/fs.rs +++ b/library/std/src/sys_common/fs.rs @@ -5,19 +5,21 @@ use crate::io::{self, Error, ErrorKind}; use crate::path::Path; pub fn copy(from: &Path, to: &Path) -> io::Result { - if !from.is_file() { + let mut reader = fs::File::open(from)?; + let metadata = reader.metadata()?; + + if !metadata.is_file() { return Err(Error::new( ErrorKind::InvalidInput, "the source path is not an existing regular file", )); } - let mut reader = fs::File::open(from)?; let mut writer = fs::File::create(to)?; let perm = reader.metadata()?.permissions(); let ret = io::copy(&mut reader, &mut writer)?; - fs::set_permissions(to, perm)?; + writer.set_permissions(perm)?; Ok(ret) } diff --git a/library/term/src/terminfo/searcher.rs b/library/term/src/terminfo/searcher.rs index 5499e240e66e5..d45f76429ad60 100644 --- a/library/term/src/terminfo/searcher.rs +++ b/library/term/src/terminfo/searcher.rs @@ -47,10 +47,10 @@ pub fn get_dbpath_for_term(term: &str) -> Option { // Look for the terminal in all of the search directories for mut p in dirs_to_search { - if fs::metadata(&p).is_ok() { + if fs::exists(&p) { p.push(&first_char.to_string()); p.push(&term); - if fs::metadata(&p).is_ok() { + if fs::exists(&p) { return Some(p); } p.pop(); @@ -60,7 +60,7 @@ pub fn get_dbpath_for_term(term: &str) -> Option { // (e.g., macOS) p.push(&format!("{:x}", first_char as usize)); p.push(term); - if fs::metadata(&p).is_ok() { + if fs::exists(&p) { return Some(p); } } diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 80f804174ed08..cd4dac6489689 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -146,8 +146,7 @@ pub fn output(cmd: &mut Command) -> String { } pub fn rerun_if_changed_anything_in_dir(dir: &Path) { - let mut stack = dir - .read_dir() + let mut stack = fs::read_dir(dir) .unwrap() .map(|e| e.unwrap()) .filter(|e| &*e.file_name() != ".git") @@ -155,7 +154,7 @@ pub fn rerun_if_changed_anything_in_dir(dir: &Path) { while let Some(entry) = stack.pop() { let path = entry.path(); if entry.file_type().unwrap().is_dir() { - stack.extend(path.read_dir().unwrap().map(|e| e.unwrap())); + stack.extend(fs::read_dir(path).unwrap().map(|e| e.unwrap())); } else { println!("cargo:rerun-if-changed={}", path.display()); } @@ -172,10 +171,11 @@ pub fn mtime(path: &Path) -> SystemTime { /// /// Uses last-modified time checks to verify this. pub fn up_to_date(src: &Path, dst: &Path) -> bool { - if !dst.exists() { - return false; - } - let threshold = mtime(dst); + let dst_meta = match fs::metadata(dst) { + Ok(meta) => meta, + Err(_) => return false, + }; + let threshold = dst_meta.modified().unwrap_or(UNIX_EPOCH); let meta = match fs::metadata(src) { Ok(meta) => meta, Err(e) => panic!("source {:?} failed to get metadata: {}", src, e), diff --git a/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs b/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs index 448c57da754a0..23e6d6ca4c383 100644 --- a/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs +++ b/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs @@ -13,6 +13,7 @@ extern crate rustc_span; use rustc_parse::new_parser_from_file; use rustc_session::parse::ParseSess; use rustc_span::source_map::FilePathMapping; +use std::fs; use std::path::Path; #[path = "mod_dir_simple/test.rs"] @@ -28,7 +29,7 @@ fn parse() { let parse_session = ParseSess::new(FilePathMapping::empty()); let path = Path::new(file!()); - let path = path.canonicalize().unwrap(); + let path = fs::canonicalize(path).unwrap(); let mut parser = new_parser_from_file(&parse_session, &path, None); let _ = parser.parse_crate_mod(); } diff --git a/src/test/ui-fulldeps/rename-directory.rs b/src/test/ui-fulldeps/rename-directory.rs index 8fc340cb91872..c06068d4b24bc 100644 --- a/src/test/ui-fulldeps/rename-directory.rs +++ b/src/test/ui-fulldeps/rename-directory.rs @@ -23,8 +23,8 @@ fn rename_directory() { let new_path = tmpdir.join("quux/blat"); fs::create_dir_all(&new_path).unwrap(); fs::rename(&old_path, &new_path.join("newdir")); - assert!(new_path.join("newdir").is_dir()); - assert!(new_path.join("newdir/temp.txt").exists()); + assert!(fs::is_dir(new_path.join("newdir"))); + assert!(fs::exists(new_path.join("newdir/temp.txt"))); } pub fn main() { rename_directory() }