diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 92f9346ef6e4..2a4ff69cbd7c 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -283,33 +283,24 @@ impl OutputTypes { // 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>>); +pub struct Externs(BTreeMap>); +#[derive(Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)] +pub struct ExternEntry { + pub location: Option, + pub public: bool +} impl Externs { - pub fn new(data: BTreeMap>>) -> Externs { + pub fn new(data: BTreeMap>) -> Externs { Externs(data) } - pub fn get(&self, key: &str) -> Option<&BTreeSet>> { + pub fn get(&self, key: &str) -> Option<&BTreeSet> { self.0.get(key) } - pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet>> { - self.0.iter() - } -} - -// Similar to 'Externs', but used for the '--extern-private' option -#[derive(Clone, Hash)] -pub struct ExternPrivates(BTreeMap>); - -impl ExternPrivates { - pub fn get(&self, key: &str) -> Option<&BTreeSet> { - self.0.get(key) - } - - pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet> { + pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet> { self.0.iter() } } @@ -446,7 +437,7 @@ top_level_options!( // The crates to consider private when // checking leaked private dependency types in public interfaces - extern_private: ExternPrivates [UNTRACKED], + //extern_private: ExternPrivates [UNTRACKED], } ); @@ -649,7 +640,7 @@ impl Default for Options { cli_forced_thinlto_off: false, remap_path_prefix: Vec::new(), edition: DEFAULT_EDITION, - extern_private: ExternPrivates(BTreeMap::new()) + //extern_private: ExternPrivates(BTreeMap::new()) } } } @@ -2331,7 +2322,7 @@ pub fn build_session_options_and_crate_config( ) } - let mut extern_private: BTreeMap<_, BTreeSet<_>> = BTreeMap::new(); + /*let mut extern_private: BTreeMap<_, BTreeSet<_>> = BTreeMap::new(); for arg in matches.opt_strs("extern-private").into_iter() { let mut parts = arg.splitn(2, '='); @@ -2346,10 +2337,16 @@ pub fn build_session_options_and_crate_config( .or_default() .insert(location); - } + }*/ + + // We start out with a Vec<(Option, bool)>>, + // and later convert it into a BTreeSet<(Option, bool)> + // This allows to modify entries in-place to set their correct + // 'public' value + let mut externs: BTreeMap<_, BTreeMap, 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<_, BTreeSet<_>> = BTreeMap::new(); - for arg in matches.opt_strs("extern").into_iter() { let mut parts = arg.splitn(2, '='); let name = parts.next().unwrap_or_else(|| early_error(error_format, "--extern value must not be empty")); @@ -2362,12 +2359,38 @@ pub fn build_session_options_and_crate_config( ); }; + + // Externsl 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() - .insert(location); + .entry(location) + .and_modify(|e| *e &= public) + .or_insert(public); } + // Now that we've determined the 'public' status of each extern, + // collect them into a set of ExternEntry + let externs: BTreeMap> = externs.into_iter() + .map(|(k, v)| { + let values =v.into_iter().map(|(location, public)| { + ExternEntry { + location, + public + } + }).collect::>(); + (k, values) + }) + .collect(); + + + let crate_name = matches.opt_str("crate-name"); let remap_path_prefix = matches @@ -2417,7 +2440,7 @@ pub fn build_session_options_and_crate_config( cli_forced_thinlto_off: disable_thinlto, remap_path_prefix, edition, - extern_private: ExternPrivates(extern_private) + //extern_private: ExternPrivates(extern_private) }, cfg, ) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 53348e75aa93..7c5b5dc7113a 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -133,7 +133,7 @@ impl<'a> CrateLoader<'a> { let source = &self.cstore.get_crate_data(cnum).source; if let Some(locs) = 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.as_ref()).any(|l| { + let found = locs.iter().filter_map(|l| l.location.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() @@ -202,13 +202,14 @@ impl<'a> CrateLoader<'a> { self.verify_no_symbol_conflicts(span, &crate_root); let mut private_dep = false; - if let Some(s) = self.sess.opts.extern_private.get(&name.as_str()) { - for path in s { - let p = Some(path.as_str()); + 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 = true; + private_dep = !entry.public; + break; } } } diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 81878c4f687b..f56ca5af76e8 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -444,9 +444,9 @@ impl<'a> Context<'a> { self.should_match_name = false; if let Some(s) = 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.is_some()) { + if s.iter().any(|l| l.location.is_some()) { return self.find_commandline_library( - s.iter().filter_map(|l| l.as_ref()), + s.iter().filter_map(|l| l.location.as_ref()), ); } } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index f2682e00430d..80c0911fee1e 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -7,7 +7,7 @@ use errors::emitter::ColorConfig; use getopts; use rustc::lint::Level; use rustc::session::early_error; -use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs}; +use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs, ExternEntry}; use rustc::session::config::{nightly_options, build_codegen_options, build_debugging_options, get_cmd_lint_options}; use rustc::session::search_paths::SearchPath; @@ -588,7 +588,8 @@ fn parse_externs(matches: &getopts::Matches) -> Result { enable `--extern crate_name` without `=path`".to_string()); } let name = name.to_string(); - externs.entry(name).or_default().insert(location); + // For Rustdoc purposes, we can treat all externs as public + externs.entry(name).or_default().insert(ExternEntry { location, public: true }); } Ok(Externs::new(externs)) }