// DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That
// would break dependency tracking for command-line arguments.
#[derive(Clone, Hash)]
-pub struct Externs(BTreeMap<String, BTreeSet<ExternEntry>>);
+pub struct Externs(BTreeMap<String, ExternEntry>);
#[derive(Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct ExternEntry {
- pub location: Option<String>,
- pub public: bool
+ pub locations: BTreeSet<Option<String>>,
+ pub is_private_dep: bool
}
-
-
impl Externs {
- pub fn new(data: BTreeMap<String, BTreeSet<ExternEntry>>) -> Externs {
+ pub fn new(data: BTreeMap<String, ExternEntry>) -> Externs {
Externs(data)
}
- pub fn get(&self, key: &str) -> Option<&BTreeSet<ExternEntry>> {
+ pub fn get(&self, key: &str) -> Option<&ExternEntry> {
self.0.get(key)
}
- pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet<ExternEntry>> {
+ pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, ExternEntry> {
self.0.iter()
}
}
// and later convert it into a BTreeSet<(Option<String>, bool)>
// This allows to modify entries in-place to set their correct
// 'public' value
- let mut externs: BTreeMap<_, BTreeMap<Option<String>, bool>> = BTreeMap::new();
- for (arg, public) in matches.opt_strs("extern").into_iter().map(|v| (v, true))
- .chain(matches.opt_strs("extern-private").into_iter().map(|v| (v, false))) {
+ let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new();
+ for (arg, private) in matches.opt_strs("extern").into_iter().map(|v| (v, false))
+ .chain(matches.opt_strs("extern-private").into_iter().map(|v| (v, true))) {
let mut parts = arg.splitn(2, '=');
let name = parts.next().unwrap_or_else(||
};
- // Extern crates start out public,
- // and become private if we later see
- // an '--extern-private' key. They never
- // go back to being public once we've seen
- // '--extern-private', so we logical-AND
- // their current and new 'public' value together
-
externs
.entry(name.to_owned())
- .or_default()
- .entry(location)
- .and_modify(|e| *e &= public)
- .or_insert(public);
- }
+ .and_modify(|e| {
+ e.locations.insert(location.clone());
+
+ // Crates start out being not private,
+ // and go to being private if we see an '--extern-private'
+ // flag
+ e.is_private_dep |= private;
+ })
+ .or_insert_with(|| {
+ let mut locations = BTreeSet::new();
+ locations.insert(location);
- // Now that we've determined the 'public' status of each extern,
- // collect them into a set of ExternEntry
- let externs: BTreeMap<String, BTreeSet<ExternEntry>> = externs.into_iter()
- .map(|(k, v)| {
- let values =v.into_iter().map(|(location, public)| {
ExternEntry {
- location,
- public
+ locations: locations,
+ is_private_dep: private
}
- }).collect::<BTreeSet<ExternEntry>>();
- (k, values)
- })
- .collect();
-
-
+ });
+ }
let crate_name = matches.opt_str("crate-name");
impl ExternEntry {
fn new_public(location: Option<String>) -> ExternEntry {
+ let mut locations = BTreeSet::new();
+ locations.insert(location);
ExternEntry {
- location,
- public: true
+ locations,
+ is_private_dep: false
}
}
}
// `source` stores paths which are normalized which may be different
// from the strings on the command line.
let source = &self.cstore.get_crate_data(cnum).source;
- if let Some(locs) = self.sess.opts.externs.get(&*name.as_str()) {
+ if let Some(entry) = self.sess.opts.externs.get(&*name.as_str()) {
// Only use `--extern crate_name=path` here, not `--extern crate_name`.
- let found = locs.iter().filter_map(|l| l.location.as_ref()).any(|l| {
+ let found = entry.locations.iter().filter_map(|l| l.as_ref()).any(|l| {
let l = fs::canonicalize(l).ok();
source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
let crate_root = lib.metadata.get_root();
self.verify_no_symbol_conflicts(span, &crate_root);
- let mut private_dep = false;
- if let Some(s) = self.sess.opts.externs.get(&name.as_str()) {
- for entry in s {
- let p = entry.location.as_ref().map(|s| s.as_str());
- if p == lib.dylib.as_ref().and_then(|r| r.0.to_str()) ||
- p == lib.rlib.as_ref().and_then(|r| r.0.to_str()) {
-
- private_dep = !entry.public;
- break;
- }
- }
- }
-
+ let private_dep = self.sess.opts.externs.get(&name.as_str())
+ .map(|e| e.is_private_dep)
+ .unwrap_or(false);
info!("register crate `extern crate {} as {}` (private_dep = {})",
crate_root.name, ident, private_dep);
// must be loaded via -L plus some filtering.
if self.hash.is_none() {
self.should_match_name = false;
- if let Some(s) = self.sess.opts.externs.get(&self.crate_name.as_str()) {
+ if let Some(entry) = self.sess.opts.externs.get(&self.crate_name.as_str()) {
// Only use `--extern crate_name=path` here, not `--extern crate_name`.
- if s.iter().any(|l| l.location.is_some()) {
+ if entry.locations.iter().any(|l| l.is_some()) {
return self.find_commandline_library(
- s.iter().filter_map(|l| l.location.as_ref()),
+ entry.locations.iter().filter_map(|l| l.as_ref()),
);
}
}
})
}
-fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, main_def_id: DefId) {
+pub fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, main_def_id: DefId) {
let main_id = tcx.hir().as_local_hir_id(main_def_id).unwrap();
let main_span = tcx.def_span(main_def_id);
let main_t = tcx.type_of(main_def_id);
}
}
-fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, start_def_id: DefId) {
+pub fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, start_def_id: DefId) {
let start_id = tcx.hir().as_local_hir_id(start_def_id).unwrap();
let start_span = tcx.def_span(start_def_id);
let start_t = tcx.type_of(start_def_id);
}
}
-fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+pub fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
match tcx.entry_fn(LOCAL_CRATE) {
Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
pub aux_builds: Vec<String>,
// A list of crates to pass '--extern-private name:PATH' flags for
// This should be a subset of 'aux_build'
+ // FIXME: Replace this with a better solution: https://github.com/rust-lang/rust/pull/54020
pub extern_private: Vec<String>,
// Environment settings to use for compiling
pub rustc_env: Vec<(String, String)>,