]> git.lizzy.rs Git - rust.git/commitdiff
Combine 'Extern' and 'ExternPrivate'
authorAaron Hill <aa1ronham@gmail.com>
Mon, 25 Mar 2019 03:06:32 +0000 (23:06 -0400)
committerAaron Hill <aa1ronham@gmail.com>
Sun, 14 Apr 2019 04:37:25 +0000 (00:37 -0400)
src/librustc/session/config.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/locator.rs
src/librustdoc/config.rs

index 92f9346ef6e47ce835b1adc5abfacc19f4c51cb7..2a4ff69cbd7ca6cc824b6fe13c74d6a5b091e4e7 100644 (file)
@@ -283,33 +283,24 @@ pub fn should_codegen(&self) -> bool {
 // 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<Option<String>>>);
+pub struct Externs(BTreeMap<String, BTreeSet<ExternEntry>>);
 
+#[derive(Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug)]
+pub struct ExternEntry {
+    pub location: Option<String>,
+    pub public: bool
+}
 
 impl Externs {
-    pub fn new(data: BTreeMap<String, BTreeSet<Option<String>>>) -> Externs {
+    pub fn new(data: BTreeMap<String, BTreeSet<ExternEntry>>) -> Externs {
         Externs(data)
     }
 
-    pub fn get(&self, key: &str) -> Option<&BTreeSet<Option<String>>> {
-        self.0.get(key)
-    }
-
-    pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet<Option<String>>> {
-        self.0.iter()
-    }
-}
-
-// Similar to 'Externs', but used for the '--extern-private' option
-#[derive(Clone, Hash)]
-pub struct ExternPrivates(BTreeMap<String, BTreeSet<String>>);
-
-impl ExternPrivates {
-    pub fn get(&self, key: &str) -> Option<&BTreeSet<String>> {
+    pub fn get(&self, key: &str) -> Option<&BTreeSet<ExternEntry>> {
         self.0.get(key)
     }
 
-    pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet<String>> {
+    pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet<ExternEntry>> {
         self.0.iter()
     }
 }
@@ -446,7 +437,7 @@ pub struct 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 @@ fn default() -> 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<String>, bool)>>,
+    // 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<_, 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,11 +2359,37 @@ 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<String, BTreeSet<ExternEntry>> = externs.into_iter()
+        .map(|(k, v)| {
+            let values =v.into_iter().map(|(location, public)| {
+                ExternEntry {
+                    location,
+                    public
+                }
+            }).collect::<BTreeSet<ExternEntry>>();
+            (k, values)
+        })
+        .collect();
+        
+
 
     let crate_name = matches.opt_str("crate-name");
 
@@ -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,
     )
index 53348e75aa9327e3f3624b4f171aff7b8e258448..7c5b5dc7113ae933aefa5c243924eda558bd84f4 100644 (file)
@@ -133,7 +133,7 @@ fn existing_match(&self, name: Symbol, hash: Option<&Svh>, kind: PathKind)
             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 @@ fn register_crate(
         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;
                 }
             }
         }
index 81878c4f687b6df0797527264ad082f2c71e679c..f56ca5af76e8f93414531ca00b1bb8f6c811ae14 100644 (file)
@@ -444,9 +444,9 @@ fn find_library_crate(&mut self,
             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()),
                     );
                 }
             }
index f2682e00430d08fb3aadd79afc136e7377668cac..80c0911fee1eac358b0d810f1b6774da94c1d75c 100644 (file)
@@ -7,7 +7,7 @@
 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<Externs, String> {
                         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))
 }