Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 17c6bde

Browse files
committedJun 20, 2022
Auto merge of rust-lang#98265 - JohnTitor:rollup-wtfqc4g, r=JohnTitor
Rollup of 4 pull requests Successful merges: - rust-lang#95534 (Add `core::mem::copy` to complement `core::mem::drop`.) - rust-lang#97912 (Stabilize `Path::try_exists()` and improve doc) - rust-lang#98225 (Make debug_triple depend on target json file content rather than file path) - rust-lang#98257 (Fix typos in `IntoFuture` docs) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 611e7b9 + 761f83f commit 17c6bde

File tree

7 files changed

+142
-38
lines changed

7 files changed

+142
-38
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

‎compiler/rustc_target/src/spec/mod.rs

+99-25
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,13 @@ use crate::json::{Json, ToJson};
3939
use crate::spec::abi::{lookup as lookup_abi, Abi};
4040
use crate::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
4141
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
42+
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
4243
use rustc_span::symbol::{sym, Symbol};
4344
use serde_json::Value;
4445
use std::borrow::Cow;
4546
use std::collections::BTreeMap;
4647
use std::convert::TryFrom;
48+
use std::hash::{Hash, Hasher};
4749
use std::iter::FromIterator;
4850
use std::ops::{Deref, DerefMut};
4951
use std::path::{Path, PathBuf};
@@ -2183,7 +2185,7 @@ impl Target {
21832185
TargetTriple::TargetTriple(ref target_triple) => {
21842186
load_builtin(target_triple).expect("built-in target")
21852187
}
2186-
TargetTriple::TargetPath(..) => {
2188+
TargetTriple::TargetJson { .. } => {
21872189
panic!("built-in targets doens't support target-paths")
21882190
}
21892191
}
@@ -2248,11 +2250,9 @@ impl Target {
22482250

22492251
Err(format!("Could not find specification for target {:?}", target_triple))
22502252
}
2251-
TargetTriple::TargetPath(ref target_path) => {
2252-
if target_path.is_file() {
2253-
return load_file(&target_path);
2254-
}
2255-
Err(format!("Target path {:?} is not a valid file", target_path))
2253+
TargetTriple::TargetJson { ref contents, .. } => {
2254+
let obj = serde_json::from_str(contents).map_err(|e| e.to_string())?;
2255+
Target::from_json(obj)
22562256
}
22572257
}
22582258
}
@@ -2421,10 +2421,77 @@ impl ToJson for Target {
24212421
}
24222422

24232423
/// Either a target triple string or a path to a JSON file.
2424-
#[derive(PartialEq, Clone, Debug, Hash, Encodable, Decodable)]
2424+
#[derive(Clone, Debug)]
24252425
pub enum TargetTriple {
24262426
TargetTriple(String),
2427-
TargetPath(PathBuf),
2427+
TargetJson {
2428+
/// Warning: This field may only be used by rustdoc. Using it anywhere else will lead to
2429+
/// inconsistencies as it is discarded during serialization.
2430+
path_for_rustdoc: PathBuf,
2431+
triple: String,
2432+
contents: String,
2433+
},
2434+
}
2435+
2436+
// Use a manual implementation to ignore the path field
2437+
impl PartialEq for TargetTriple {
2438+
fn eq(&self, other: &Self) -> bool {
2439+
match (self, other) {
2440+
(Self::TargetTriple(l0), Self::TargetTriple(r0)) => l0 == r0,
2441+
(
2442+
Self::TargetJson { path_for_rustdoc: _, triple: l_triple, contents: l_contents },
2443+
Self::TargetJson { path_for_rustdoc: _, triple: r_triple, contents: r_contents },
2444+
) => l_triple == r_triple && l_contents == r_contents,
2445+
_ => false,
2446+
}
2447+
}
2448+
}
2449+
2450+
// Use a manual implementation to ignore the path field
2451+
impl Hash for TargetTriple {
2452+
fn hash<H: Hasher>(&self, state: &mut H) -> () {
2453+
match self {
2454+
TargetTriple::TargetTriple(triple) => {
2455+
0u8.hash(state);
2456+
triple.hash(state)
2457+
}
2458+
TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents } => {
2459+
1u8.hash(state);
2460+
triple.hash(state);
2461+
contents.hash(state)
2462+
}
2463+
}
2464+
}
2465+
}
2466+
2467+
// Use a manual implementation to prevent encoding the target json file path in the crate metadata
2468+
impl<S: Encoder> Encodable<S> for TargetTriple {
2469+
fn encode(&self, s: &mut S) {
2470+
match self {
2471+
TargetTriple::TargetTriple(triple) => s.emit_enum_variant(0, |s| s.emit_str(triple)),
2472+
TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents } => s
2473+
.emit_enum_variant(1, |s| {
2474+
s.emit_str(triple);
2475+
s.emit_str(contents)
2476+
}),
2477+
}
2478+
}
2479+
}
2480+
2481+
impl<D: Decoder> Decodable<D> for TargetTriple {
2482+
fn decode(d: &mut D) -> Self {
2483+
match d.read_usize() {
2484+
0 => TargetTriple::TargetTriple(d.read_str().to_owned()),
2485+
1 => TargetTriple::TargetJson {
2486+
path_for_rustdoc: PathBuf::new(),
2487+
triple: d.read_str().to_owned(),
2488+
contents: d.read_str().to_owned(),
2489+
},
2490+
_ => {
2491+
panic!("invalid enum variant tag while decoding `TargetTriple`, expected 0..2");
2492+
}
2493+
}
2494+
}
24282495
}
24292496

24302497
impl TargetTriple {
@@ -2436,20 +2503,28 @@ impl TargetTriple {
24362503
/// Creates a target triple from the passed target path.
24372504
pub fn from_path(path: &Path) -> Result<Self, io::Error> {
24382505
let canonicalized_path = path.canonicalize()?;
2439-
Ok(TargetTriple::TargetPath(canonicalized_path))
2506+
let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
2507+
io::Error::new(
2508+
io::ErrorKind::InvalidInput,
2509+
format!("target path {:?} is not a valid file: {}", canonicalized_path, err),
2510+
)
2511+
})?;
2512+
let triple = canonicalized_path
2513+
.file_stem()
2514+
.expect("target path must not be empty")
2515+
.to_str()
2516+
.expect("target path must be valid unicode")
2517+
.to_owned();
2518+
Ok(TargetTriple::TargetJson { path_for_rustdoc: canonicalized_path, triple, contents })
24402519
}
24412520

24422521
/// Returns a string triple for this target.
24432522
///
24442523
/// If this target is a path, the file name (without extension) is returned.
24452524
pub fn triple(&self) -> &str {
24462525
match *self {
2447-
TargetTriple::TargetTriple(ref triple) => triple,
2448-
TargetTriple::TargetPath(ref path) => path
2449-
.file_stem()
2450-
.expect("target path must not be empty")
2451-
.to_str()
2452-
.expect("target path must be valid unicode"),
2526+
TargetTriple::TargetTriple(ref triple)
2527+
| TargetTriple::TargetJson { ref triple, .. } => triple,
24532528
}
24542529
}
24552530

@@ -2459,16 +2534,15 @@ impl TargetTriple {
24592534
/// by `triple()`.
24602535
pub fn debug_triple(&self) -> String {
24612536
use std::collections::hash_map::DefaultHasher;
2462-
use std::hash::{Hash, Hasher};
2463-
2464-
let triple = self.triple();
2465-
if let TargetTriple::TargetPath(ref path) = *self {
2466-
let mut hasher = DefaultHasher::new();
2467-
path.hash(&mut hasher);
2468-
let hash = hasher.finish();
2469-
format!("{}-{}", triple, hash)
2470-
} else {
2471-
triple.into()
2537+
2538+
match self {
2539+
TargetTriple::TargetTriple(triple) => triple.to_owned(),
2540+
TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents: content } => {
2541+
let mut hasher = DefaultHasher::new();
2542+
content.hash(&mut hasher);
2543+
let hash = hasher.finish();
2544+
format!("{}-{}", triple, hash)
2545+
}
24722546
}
24732547
}
24742548
}

‎library/core/src/future/into_future.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::future::Future;
22

33
/// Conversion into a `Future`.
44
///
5-
/// By implementing `Intofuture` for a type, you define how it will be
5+
/// By implementing `IntoFuture` for a type, you define how it will be
66
/// converted to a future.
77
///
88
/// # `.await` desugaring
@@ -29,7 +29,7 @@ use crate::future::Future;
2929
/// When implementing futures manually there will often be a choice between
3030
/// implementing `Future` or `IntoFuture` for a type. Implementing `Future` is a
3131
/// good choice in most cases. But implementing `IntoFuture` is most useful when
32-
/// implementing "async builder" types, which allows the type to be modified
32+
/// implementing "async builder" types, which allow their values to be modified
3333
/// multiple times before being `.await`ed.
3434
///
3535
/// ```rust

‎library/core/src/mem/mod.rs

+22
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,28 @@ pub const fn replace<T>(dest: &mut T, src: T) -> T {
973973
#[cfg_attr(not(test), rustc_diagnostic_item = "mem_drop")]
974974
pub fn drop<T>(_x: T) {}
975975

976+
/// Bitwise-copies a value.
977+
///
978+
/// This function is not magic; it is literally defined as
979+
/// ```
980+
/// pub fn copy<T: Copy>(x: &T) -> T { *x }
981+
/// ```
982+
///
983+
/// It is useful when you want to pass a function pointer to a combinator, rather than defining a new closure.
984+
///
985+
/// Example:
986+
/// ```
987+
/// #![feature(mem_copy_fn)]
988+
/// use core::mem::copy;
989+
/// let result_from_ffi_function: Result<(), &i32> = Err(&1);
990+
/// let result_copied: Result<(), i32> = result_from_ffi_function.map_err(copy);
991+
/// ```
992+
#[inline]
993+
#[unstable(feature = "mem_copy_fn", issue = "98262")]
994+
pub fn copy<T: Copy>(x: &T) -> T {
995+
*x
996+
}
997+
976998
/// Interprets `src` as having type `&U`, and then reads `src` without moving
977999
/// the contained value.
9781000
///

‎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)

‎src/librustdoc/doctest.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,8 @@ fn run_test(
365365
}
366366
compiler.arg("--target").arg(match target {
367367
TargetTriple::TargetTriple(s) => s,
368-
TargetTriple::TargetPath(path) => {
369-
path.to_str().expect("target path must be valid unicode").to_string()
368+
TargetTriple::TargetJson { path_for_rustdoc, .. } => {
369+
path_for_rustdoc.to_str().expect("target path must be valid unicode").to_string()
370370
}
371371
});
372372
if let ErrorOutputType::HumanReadable(kind) = rustdoc_options.error_format {

0 commit comments

Comments
 (0)
Failed to load comments.