From 26b1ed1b92a1c3ea9e511e81a456401777dbf425 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 24 Aug 2018 18:51:10 +0300 Subject: [PATCH] rustc: add unstable support for --extern crate_name without a path. --- src/librustc/session/config.rs | 43 ++++++++++++++++---------------- src/librustc_metadata/creader.rs | 3 ++- src/librustc_metadata/locator.rs | 7 +++++- src/librustdoc/lib.rs | 11 +++++--- 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 2a9732bf02c..4c0eeba7441 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -275,18 +275,18 @@ impl OutputTypes { // DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That // would break dependency tracking for commandline arguments. #[derive(Clone, Hash)] -pub struct Externs(BTreeMap>); +pub struct Externs(BTreeMap>>); 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> { + pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet>> { self.0.iter() } } @@ -2169,6 +2169,8 @@ pub fn build_session_options_and_crate_config( let cfg = parse_cfgspecs(matches.opt_strs("cfg")); let test = matches.opt_present("test"); + let is_unstable_enabled = nightly_options::is_unstable_enabled(matches); + prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s { "crate-name" => PrintRequest::CrateName, "file-names" => PrintRequest::FileNames, @@ -2182,15 +2184,13 @@ pub fn build_session_options_and_crate_config( "tls-models" => PrintRequest::TlsModels, "native-static-libs" => PrintRequest::NativeStaticLibs, "target-spec-json" => { - if nightly_options::is_unstable_enabled(matches) { + if is_unstable_enabled { PrintRequest::TargetSpec } else { early_error( error_format, - &format!( - "the `-Z unstable-options` flag must also be passed to \ - enable the target-spec-json print option" - ), + "the `-Z unstable-options` flag must also be passed to \ + enable the target-spec-json print option", ); } } @@ -2220,18 +2220,19 @@ pub fn build_session_options_and_crate_config( Some(s) => s, None => early_error(error_format, "--extern value must not be empty"), }; - let location = match parts.next() { - Some(s) => s, - None => early_error( + let location = parts.next().map(|s| s.to_string()); + if location.is_none() && !is_unstable_enabled { + early_error( error_format, - "--extern value must be of the format `foo=bar`", - ), + "the `-Z unstable-options` flag must also be passed to \ + enable `--extern crate_name` without `=path`", + ); }; externs .entry(name.to_string()) .or_default() - .insert(location.to_string()); + .insert(location); } let crate_name = matches.opt_str("crate-name"); @@ -2687,33 +2688,33 @@ mod tests { v1.externs = Externs::new(mk_map(vec![ ( String::from("a"), - mk_set(vec![String::from("b"), String::from("c")]), + mk_set(vec![Some(String::from("b")), Some(String::from("c"))]), ), ( String::from("d"), - mk_set(vec![String::from("e"), String::from("f")]), + mk_set(vec![Some(String::from("e")), Some(String::from("f"))]), ), ])); v2.externs = Externs::new(mk_map(vec![ ( String::from("d"), - mk_set(vec![String::from("e"), String::from("f")]), + mk_set(vec![Some(String::from("e")), Some(String::from("f"))]), ), ( String::from("a"), - mk_set(vec![String::from("b"), String::from("c")]), + mk_set(vec![Some(String::from("b")), Some(String::from("c"))]), ), ])); v3.externs = Externs::new(mk_map(vec![ ( String::from("a"), - mk_set(vec![String::from("b"), String::from("c")]), + mk_set(vec![Some(String::from("b")), Some(String::from("c"))]), ), ( String::from("d"), - mk_set(vec![String::from("f"), String::from("e")]), + mk_set(vec![Some(String::from("f")), Some(String::from("e"))]), ), ])); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 5eb54195215..e28bb260820 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -132,7 +132,8 @@ impl<'a> CrateLoader<'a> { // 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()) { - let found = locs.iter().any(|l| { + // Only use `--extern crate_name=path` here, not `--extern crate_name`. + let found = locs.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() diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 9492385957e..02207c63b34 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -438,7 +438,12 @@ impl<'a> Context<'a> { if self.hash.is_none() { self.should_match_name = false; if let Some(s) = self.sess.opts.externs.get(&self.crate_name.as_str()) { - return self.find_commandline_library(s.iter()); + // Only use `--extern crate_name=path` here, not `--extern crate_name`. + if s.iter().any(|l| l.is_some()) { + return self.find_commandline_library( + s.iter().filter_map(|l| l.as_ref()), + ); + } } self.should_match_name = true; } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index bc471d42704..73057b19016 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -609,16 +609,19 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R { /// Extracts `--extern CRATE=PATH` arguments from `matches` and /// returns a map mapping crate names to their paths or else an /// error message. +// FIXME(eddyb) This shouldn't be duplicated with `rustc::session`. fn parse_externs(matches: &getopts::Matches) -> Result { let mut externs: BTreeMap<_, BTreeSet<_>> = BTreeMap::new(); for arg in &matches.opt_strs("extern") { let mut parts = arg.splitn(2, '='); let name = parts.next().ok_or("--extern value must not be empty".to_string())?; - let location = parts.next() - .ok_or("--extern value must be of the format `foo=bar`" - .to_string())?; + let location = parts.next().map(|s| s.to_string()); + if location.is_none() && !nightly_options::is_unstable_enabled(matches) { + return Err("the `-Z unstable-options` flag must also be passed to \ + enable `--extern crate_name` without `=path`".to_string()); + } let name = name.to_string(); - externs.entry(name).or_default().insert(location.to_string()); + externs.entry(name).or_default().insert(location); } Ok(Externs::new(externs)) }