@@ -39,11 +39,13 @@ use crate::json::{Json, ToJson};
39
39
use crate::spec::abi::{lookup as lookup_abi, Abi};
40
40
use crate::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
41
41
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
42
+ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
42
43
use rustc_span::symbol::{sym, Symbol};
43
44
use serde_json::Value;
44
45
use std::borrow::Cow;
45
46
use std::collections::BTreeMap;
46
47
use std::convert::TryFrom;
48
+ use std::hash::{Hash, Hasher};
47
49
use std::iter::FromIterator;
48
50
use std::ops::{Deref, DerefMut};
49
51
use std::path::{Path, PathBuf};
@@ -2248,7 +2250,7 @@ impl Target {
2248
2250
2249
2251
Err(format!("Could not find specification for target {:?}", target_triple))
2250
2252
}
2251
- TargetTriple::TargetJson { triple: _, ref contents } => {
2253
+ TargetTriple::TargetJson { ref contents, .. } => {
2252
2254
let obj = serde_json::from_str(contents).map_err(|e| e.to_string())?;
2253
2255
Target::from_json(obj)
2254
2256
}
@@ -2419,10 +2421,77 @@ impl ToJson for Target {
2419
2421
}
2420
2422
2421
2423
/// Either a target triple string or a path to a JSON file.
2422
- #[derive(PartialEq, Clone, Debug, Hash, Encodable, Decodable )]
2424
+ #[derive(Clone, Debug)]
2423
2425
pub enum TargetTriple {
2424
2426
TargetTriple(String),
2425
- TargetJson { triple: String, contents: String },
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
+ }
2426
2495
}
2427
2496
2428
2497
impl TargetTriple {
@@ -2437,7 +2506,7 @@ impl TargetTriple {
2437
2506
let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| {
2438
2507
io::Error::new(
2439
2508
io::ErrorKind::InvalidInput,
2440
- format!("Target path {:?} is not a valid file: {}", canonicalized_path, err),
2509
+ format!("target path {:?} is not a valid file: {}", canonicalized_path, err),
2441
2510
)
2442
2511
})?;
2443
2512
let triple = canonicalized_path
@@ -2446,7 +2515,7 @@ impl TargetTriple {
2446
2515
.to_str()
2447
2516
.expect("target path must be valid unicode")
2448
2517
.to_owned();
2449
- Ok(TargetTriple::TargetJson { triple, contents })
2518
+ Ok(TargetTriple::TargetJson { path_for_rustdoc: canonicalized_path, triple, contents })
2450
2519
}
2451
2520
2452
2521
/// Returns a string triple for this target.
@@ -2455,7 +2524,7 @@ impl TargetTriple {
2455
2524
pub fn triple(&self) -> &str {
2456
2525
match *self {
2457
2526
TargetTriple::TargetTriple(ref triple)
2458
- | TargetTriple::TargetJson { ref triple, contents: _ } => triple,
2527
+ | TargetTriple::TargetJson { ref triple, .. } => triple,
2459
2528
}
2460
2529
}
2461
2530
@@ -2465,11 +2534,10 @@ impl TargetTriple {
2465
2534
/// by `triple()`.
2466
2535
pub fn debug_triple(&self) -> String {
2467
2536
use std::collections::hash_map::DefaultHasher;
2468
- use std::hash::{Hash, Hasher};
2469
2537
2470
2538
match self {
2471
2539
TargetTriple::TargetTriple(triple) => triple.to_owned(),
2472
- TargetTriple::TargetJson { triple, contents: content } => {
2540
+ TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents: content } => {
2473
2541
let mut hasher = DefaultHasher::new();
2474
2542
content.hash(&mut hasher);
2475
2543
let hash = hasher.finish();
0 commit comments