use crate::ty::TyCtxt;
use rustc_ast as ast;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{self, MetadataRef};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
use rustc_macros::HashStable;
use rustc_session::search_paths::PathKind;
use rustc_session::utils::NativeLibKind;
use rustc_session::CrateDisambiguator;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
use rustc_target::spec::Target;
use std::any::Any;
use std::path::{Path, PathBuf};
#[derive(PartialEq, Clone, Debug, HashStable, Encodable, Decodable)]
pub struct CrateSource {
pub dylib: Option<(PathBuf, PathKind)>,
pub rlib: Option<(PathBuf, PathKind)>,
pub rmeta: Option<(PathBuf, PathKind)>,
}
impl CrateSource {
pub fn paths(&self) -> impl Iterator<Item = &PathBuf> {
self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).map(|p| &p.0)
}
}
#[derive(Encodable, Decodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
#[derive(HashStable)]
pub enum CrateDepKind {
MacrosOnly,
Implicit,
Explicit,
}
impl CrateDepKind {
pub fn macros_only(self) -> bool {
match self {
CrateDepKind::MacrosOnly => true,
CrateDepKind::Implicit | CrateDepKind::Explicit => false,
}
}
}
#[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
pub enum LibSource {
Some(PathBuf),
MetadataOnly,
None,
}
impl LibSource {
pub fn is_some(&self) -> bool {
matches!(self, LibSource::Some(_))
}
pub fn option(&self) -> Option<PathBuf> {
match *self {
LibSource::Some(ref p) => Some(p.clone()),
LibSource::MetadataOnly | LibSource::None => None,
}
}
}
#[derive(Copy, Debug, PartialEq, Clone, Encodable, Decodable, HashStable)]
pub enum LinkagePreference {
RequireDynamic,
RequireStatic,
}
#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
pub struct NativeLib {
pub kind: NativeLibKind,
pub name: Option<Symbol>,
pub cfg: Option<ast::MetaItem>,
pub foreign_module: Option<DefId>,
pub wasm_import_module: Option<Symbol>,
}
#[derive(Clone, TyEncodable, TyDecodable, HashStable)]
pub struct ForeignModule {
pub foreign_items: Vec<DefId>,
pub def_id: DefId,
}
#[derive(Copy, Clone, Debug, HashStable)]
pub struct ExternCrate {
pub src: ExternCrateSource,
pub span: Span,
pub path_len: usize,
pub dependency_of: CrateNum,
}
impl ExternCrate {
pub fn is_direct(&self) -> bool {
self.dependency_of == LOCAL_CRATE
}
pub fn rank(&self) -> impl PartialOrd {
(self.is_direct(), !self.path_len)
}
}
#[derive(Copy, Clone, Debug, HashStable)]
pub enum ExternCrateSource {
Extern(
DefId,
),
Path,
}
#[derive(Encodable, Decodable)]
pub struct EncodedMetadata {
pub raw_data: Vec<u8>,
}
impl EncodedMetadata {
pub fn new() -> EncodedMetadata {
EncodedMetadata { raw_data: Vec::new() }
}
}
pub trait MetadataLoader {
fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
}
pub type MetadataLoaderDyn = dyn MetadataLoader + Sync;
pub trait CrateStore {
fn as_any(&self) -> &dyn Any;
fn def_key(&self, def: DefId) -> DefKey;
fn def_kind(&self, def: DefId) -> DefKind;
fn def_path(&self, def: DefId) -> DefPath;
fn def_path_hash(&self, def: DefId) -> DefPathHash;
fn all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)>;
fn num_def_ids(&self, cnum: CrateNum) -> usize;
fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool;
fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
fn crates_untracked(&self) -> Vec<CrateNum>;
fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata;
fn metadata_encoding_version(&self) -> &[u8];
fn allocator_kind(&self) -> Option<AllocatorKind>;
}
pub type CrateStoreDyn = dyn CrateStore + sync::Sync;
pub fn used_crates(tcx: TyCtxt<'_>, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> {
let mut libs = tcx
.crates()
.iter()
.cloned()
.filter_map(|cnum| {
if tcx.dep_kind(cnum).macros_only() {
return None;
}
let source = tcx.used_crate_source(cnum);
let path = match prefer {
LinkagePreference::RequireDynamic => source.dylib.clone().map(|p| p.0),
LinkagePreference::RequireStatic => source.rlib.clone().map(|p| p.0),
};
let path = match path {
Some(p) => LibSource::Some(p),
None => {
if source.rmeta.is_some() {
LibSource::MetadataOnly
} else {
LibSource::None
}
}
};
Some((cnum, path))
})
.collect::<Vec<_>>();
let mut ordering = tcx.postorder_cnums(LOCAL_CRATE).to_owned();
ordering.reverse();
libs.sort_by_cached_key(|&(a, _)| ordering.iter().position(|x| *x == a));
libs
}