@@ -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 } ;
@@ -2183,7 +2185,7 @@ impl Target {
2183
2185
TargetTriple :: TargetTriple ( ref target_triple) => {
2184
2186
load_builtin ( target_triple) . expect ( "built-in target" )
2185
2187
}
2186
- TargetTriple :: TargetPath ( .. ) => {
2188
+ TargetTriple :: TargetJson { .. } => {
2187
2189
panic ! ( "built-in targets doens't support target-paths" )
2188
2190
}
2189
2191
}
@@ -2248,11 +2250,9 @@ impl Target {
2248
2250
2249
2251
Err ( format ! ( "Could not find specification for target {:?}" , target_triple) )
2250
2252
}
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)
2256
2256
}
2257
2257
}
2258
2258
}
@@ -2421,10 +2421,77 @@ impl ToJson for Target {
2421
2421
}
2422
2422
2423
2423
/// Either a target triple string or a path to a JSON file.
2424
- #[ derive( PartialEq , Clone , Debug , Hash , Encodable , Decodable ) ]
2424
+ #[ derive( Clone , Debug ) ]
2425
2425
pub enum TargetTriple {
2426
2426
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
+ }
2428
2495
}
2429
2496
2430
2497
impl TargetTriple {
@@ -2436,20 +2503,28 @@ impl TargetTriple {
2436
2503
/// Creates a target triple from the passed target path.
2437
2504
pub fn from_path ( path : & Path ) -> Result < Self , io:: Error > {
2438
2505
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 } )
2440
2519
}
2441
2520
2442
2521
/// Returns a string triple for this target.
2443
2522
///
2444
2523
/// If this target is a path, the file name (without extension) is returned.
2445
2524
pub fn triple ( & self ) -> & str {
2446
2525
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,
2453
2528
}
2454
2529
}
2455
2530
@@ -2459,16 +2534,15 @@ impl TargetTriple {
2459
2534
/// by `triple()`.
2460
2535
pub fn debug_triple ( & self ) -> String {
2461
2536
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
+ }
2472
2546
}
2473
2547
}
2474
2548
}
0 commit comments