@@ -39,11 +39,13 @@ use crate::json::{Json, ToJson};
3939use crate :: spec:: abi:: { lookup as lookup_abi, Abi } ;
4040use crate :: spec:: crt_objects:: { CrtObjects , CrtObjectsFallback } ;
4141use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
42+ use rustc_serialize:: { Decodable , Decoder , Encodable , Encoder } ;
4243use rustc_span:: symbol:: { sym, Symbol } ;
4344use serde_json:: Value ;
4445use std:: borrow:: Cow ;
4546use std:: collections:: BTreeMap ;
4647use std:: convert:: TryFrom ;
48+ use std:: hash:: { Hash , Hasher } ;
4749use std:: iter:: FromIterator ;
4850use std:: ops:: { Deref , DerefMut } ;
4951use 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 ) ]
24252425pub 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
24302497impl 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}
0 commit comments