use crate::hir::def_id::{DefId, LOCAL_CRATE}; use crate::ich::StableHashingContext; use rustc_data_structures::stable_hasher::{StableHasher, HashStable, StableHasherResult}; use std::cmp; use std::mem; use crate::ty; use crate::ty::subst::SubstsRef; /// The SymbolExportLevel of a symbols specifies from which kinds of crates /// the symbol will be exported. `C` symbols will be exported from any /// kind of crate, including cdylibs which export very few things. /// `Rust` will only be exported if the crate produced is a Rust /// dylib. #[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)] pub enum SymbolExportLevel { C, Rust, } impl_stable_hash_for!(enum self::SymbolExportLevel { C, Rust }); impl SymbolExportLevel { pub fn is_below_threshold(self, threshold: SymbolExportLevel) -> bool { threshold == SymbolExportLevel::Rust // export everything from Rust dylibs || self == SymbolExportLevel::C } } #[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)] pub enum ExportedSymbol<'tcx> { NonGeneric(DefId), Generic(DefId, SubstsRef<'tcx>), NoDefId(ty::SymbolName), } impl<'tcx> ExportedSymbol<'tcx> { pub fn symbol_name(&self, tcx: ty::TyCtxt<'_, 'tcx, '_>) -> ty::SymbolName { match *self { ExportedSymbol::NonGeneric(def_id) => { tcx.symbol_name(ty::Instance::mono(tcx, def_id)) } ExportedSymbol::Generic(def_id, substs) => { tcx.symbol_name(ty::Instance::new(def_id, substs)) } ExportedSymbol::NoDefId(symbol_name) => { symbol_name } } } pub fn compare_stable(&self, tcx: ty::TyCtxt<'_, 'tcx, '_>, other: &ExportedSymbol<'tcx>) -> cmp::Ordering { match *self { ExportedSymbol::NonGeneric(self_def_id) => match *other { ExportedSymbol::NonGeneric(other_def_id) => { tcx.def_path_hash(self_def_id).cmp(&tcx.def_path_hash(other_def_id)) } ExportedSymbol::Generic(..) | ExportedSymbol::NoDefId(_) => { cmp::Ordering::Less } } ExportedSymbol::Generic(..) => match *other { ExportedSymbol::NonGeneric(_) => { cmp::Ordering::Greater } ExportedSymbol::Generic(..) => { self.symbol_name(tcx).cmp(&other.symbol_name(tcx)) } ExportedSymbol::NoDefId(_) => { cmp::Ordering::Less } } ExportedSymbol::NoDefId(self_symbol_name) => match *other { ExportedSymbol::NonGeneric(_) | ExportedSymbol::Generic(..) => { cmp::Ordering::Greater } ExportedSymbol::NoDefId(ref other_symbol_name) => { self_symbol_name.cmp(other_symbol_name) } } } } } pub fn metadata_symbol_name(tcx: ty::TyCtxt<'_, '_, '_>) -> String { format!("rust_metadata_{}_{}", tcx.original_crate_name(LOCAL_CRATE), tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex()) } impl<'a, 'gcx> HashStable> for ExportedSymbol<'gcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); match *self { ExportedSymbol::NonGeneric(def_id) => { def_id.hash_stable(hcx, hasher); } ExportedSymbol::Generic(def_id, substs) => { def_id.hash_stable(hcx, hasher); substs.hash_stable(hcx, hasher); } ExportedSymbol::NoDefId(symbol_name) => { symbol_name.hash_stable(hcx, hasher); } } } }