]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #19941 : alexcrichton/rust/issue-19767, r=brson
authorbors <bors@rust-lang.org>
Tue, 30 Dec 2014 11:11:07 +0000 (11:11 +0000)
committerbors <bors@rust-lang.org>
Tue, 30 Dec 2014 11:11:07 +0000 (11:11 +0000)
This commit adds support for the compiler to distinguish between different forms
of lookup paths in the compiler itself. Issue #19767 has some background on this
topic, as well as some sample bugs which can occur if these lookup paths are not
separated.

This commits extends the existing command line flag `-L` with the same trailing
syntax as the `-l` flag. Each argument to `-L` can now have a trailing `:all`,
`:native`, `:crate`, or `:dependency`. This suffix indicates what form of lookup
path the compiler should add the argument to. The `dependency` lookup path is
used when looking up crate dependencies, the `crate` lookup path is used when
looking for immediate dependencies (`extern crate` statements), and the `native`
lookup path is used for probing for native libraries to insert into rlibs. Paths
with `all` are used for all of these purposes (the default).

The default compiler lookup path (the rustlib libdir) is by default added to all
of these paths. Additionally, the `RUST_PATH` lookup path is added to all of
these paths.

Closes #19767

1  2 
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc_driver/driver.rs
src/librustdoc/core.rs

index 5f3fbf897dc1602f9ea51fd20cf51a60007988c0,0cbbbfe3d36ea42b94e4c711ca22a449c0fef9d4..19ac6d466fb5856cd3d768ca54c9b707a81cb29c
@@@ -19,6 -19,7 +19,7 @@@ pub use self::OutputType::*
  pub use self::DebugInfoLevel::*;
  
  use session::{early_error, Session};
+ use session::search_paths::SearchPaths;
  
  use rustc_back::target::Target;
  use lint;
@@@ -35,7 -36,6 +36,6 @@@ use syntax::parse::token::InternedStrin
  use std::collections::HashMap;
  use std::collections::hash_map::Entry::{Occupied, Vacant};
  use getopts;
- use std::cell::{RefCell};
  use std::fmt;
  
  use llvm;
@@@ -86,7 -86,7 +86,7 @@@ pub struct Options 
      // This was mutable for rustpkg, which updates search paths based on the
      // parsed code. It remains mutable in case its replacements wants to use
      // this.
-     pub addl_lib_search_paths: RefCell<Vec<Path>>,
+     pub search_paths: SearchPaths,
      pub libs: Vec<(String, cstore::NativeLibraryKind)>,
      pub maybe_sysroot: Option<Path>,
      pub target_triple: String,
@@@ -198,7 -198,7 +198,7 @@@ pub fn basic_options() -> Options 
          lint_opts: Vec::new(),
          describe_lints: false,
          output_types: Vec::new(),
-         addl_lib_search_paths: RefCell::new(Vec::new()),
+         search_paths: SearchPaths::new(),
          maybe_sysroot: None,
          target_triple: host_triple().to_string(),
          cfg: Vec::new(),
@@@ -278,8 -278,7 +278,8 @@@ debugging_opts! 
          PARSE_ONLY,
          NO_TRANS,
          NO_ANALYSIS,
 -        UNSTABLE_OPTIONS
 +        UNSTABLE_OPTIONS,
 +        PRINT_ENUM_SIZES
      ]
      0
  }
@@@ -332,9 -331,7 +332,9 @@@ pub fn debugging_opts_map() -> Vec<(&'s
       ("no-analysis", "Parse and expand the source, but run no analysis and",
        NO_TRANS),
       ("unstable-options", "Adds unstable command line options to rustc interface",
 -      UNSTABLE_OPTIONS)]
 +      UNSTABLE_OPTIONS),
 +     ("print-enum-sizes", "Print the size of enums and their variants", PRINT_ENUM_SIZES),
 +    ]
  }
  
  #[deriving(Clone)]
@@@ -1010,9 -1007,10 +1010,10 @@@ pub fn build_session_options(matches: &
          }
      };
  
-     let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
-         Path::new(s[])
-     }).collect();
+     let mut search_paths = SearchPaths::new();
+     for s in matches.opt_strs("L").iter() {
+         search_paths.add_path(s[]);
+     }
  
      let libs = matches.opt_strs("l").into_iter().map(|s| {
          let mut parts = s.rsplitn(1, ':');
          lint_opts: lint_opts,
          describe_lints: describe_lints,
          output_types: output_types,
-         addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
+         search_paths: search_paths,
          maybe_sysroot: sysroot_opt,
          target_triple: target,
          cfg: cfg,
index 35c325bd764f1a215c5bf1466e284fc17fa99dbe,06e9379a07b8f3e15aa6730389a291864cd4155d..86a3a6001f9663d4cb24487cb59fe0507ef70825
@@@ -9,9 -9,10 +9,10 @@@
  // except according to those terms.
  
  
+ use lint;
  use metadata::cstore::CStore;
  use metadata::filesearch;
- use lint;
+ use session::search_paths::PathKind;
  use util::nodemap::NodeMap;
  
  use syntax::ast::NodeId;
@@@ -28,6 -29,7 +29,7 @@@ use std::os
  use std::cell::{Cell, RefCell};
  
  pub mod config;
+ pub mod search_paths;
  
  // Represents the data associated with a compilation
  // session for a single crate.
@@@ -202,9 -204,6 +204,9 @@@ impl Session 
      pub fn show_span(&self) -> bool {
          self.debugging_opt(config::SHOW_SPAN)
      }
 +    pub fn print_enum_sizes(&self) -> bool {
 +        self.debugging_opt(config::PRINT_ENUM_SIZES)
 +    }
      pub fn sysroot<'a>(&'a self) -> &'a Path {
          match self.opts.maybe_sysroot {
              Some (ref sysroot) => sysroot,
                          .expect("missing sysroot and default_sysroot in Session")
          }
      }
-     pub fn target_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
+     pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
          filesearch::FileSearch::new(self.sysroot(),
                                      self.opts.target_triple[],
-                                     &self.opts.addl_lib_search_paths)
+                                     &self.opts.search_paths,
+                                     kind)
      }
-     pub fn host_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
+     pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
          filesearch::FileSearch::new(
              self.sysroot(),
              config::host_triple(),
-             &self.opts.addl_lib_search_paths)
+             &self.opts.search_paths,
+             kind)
      }
  }
  
@@@ -307,3 -308,4 +311,3 @@@ pub fn early_warn(msg: &str) 
      let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None);
      emitter.emit(None, msg, None, diagnostic::Warning);
  }
 -
index 0ac8d6ba734d0137960513e7da705cedd5608b37,f7e9f52751e1619b830279d7a4d91bceb22f87b8..9084e745bfb8e4f334d8c300927c15c8716e488e
@@@ -10,6 -10,7 +10,7 @@@
  
  use rustc::session::Session;
  use rustc::session::config::{mod, Input, OutputFilenames};
+ use rustc::session::search_paths::PathKind;
  use rustc::lint;
  use rustc::metadata::creader;
  use rustc::middle::{stability, ty, reachable};
@@@ -32,6 -33,7 +33,6 @@@ use serialize::{json, Encodable}
  use std::io;
  use std::io::fs;
  use std::os;
 -use arena::TypedArena;
  use syntax::ast;
  use syntax::ast_map;
  use syntax::attr;
@@@ -78,23 -80,12 +79,23 @@@ pub fn compile_input(sess: Session
  
          if stop_after_phase_2(&sess) { return; }
  
 -        let type_arena = TypedArena::new();
 -        let analysis = phase_3_run_analysis_passes(sess, ast_map, &type_arena, id);
 +        let arenas = ty::CtxtArenas::new();
 +        let analysis = phase_3_run_analysis_passes(sess, ast_map, &arenas, id);
          phase_save_analysis(&analysis.ty_cx.sess, analysis.ty_cx.map.krate(), &analysis, outdir);
 +
 +        if log_enabled!(::log::INFO) {
 +            println!("Pre-trans");
 +            analysis.ty_cx.print_debug_stats();
 +        }
 +
          if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
          let (tcx, trans) = phase_4_translate_to_llvm(analysis);
  
 +        if log_enabled!(::log::INFO) {
 +            println!("Post-trans");
 +            tcx.print_debug_stats();
 +        }
 +
          // Discard interned strings as they are no longer required.
          token::get_ident_interner().clear();
  
@@@ -266,7 -257,7 +267,7 @@@ pub fn phase_2_configure_and_expand(ses
              let mut _old_path = String::new();
              if cfg!(windows) {
                  _old_path = os::getenv("PATH").unwrap_or(_old_path);
-                 let mut new_path = sess.host_filesearch().get_dylib_search_paths();
+                 let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths();
                  new_path.extend(os::split_paths(_old_path[]).into_iter());
                  os::setenv("PATH", os::join_paths(new_path[]).unwrap());
              }
@@@ -341,7 -332,7 +342,7 @@@ pub fn assign_node_ids_and_map<'ast>(se
  /// structures carrying the results of the analysis.
  pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
                                           ast_map: ast_map::Map<'tcx>,
 -                                         type_arena: &'tcx TypedArena<ty::TyS<'tcx>>,
 +                                         arenas: &'tcx ty::CtxtArenas<'tcx>,
                                           name: String) -> ty::CrateAnalysis<'tcx> {
      let time_passes = sess.time_passes();
      let krate = ast_map.krate();
      let lang_items = time(time_passes, "language item collection", (), |_|
                            middle::lang_items::collect_language_items(krate, &sess));
  
 +    let make_glob_map = if save_analysis(&sess) {
 +        resolve::MakeGlobMap::Yes
 +    } else {
 +        resolve::MakeGlobMap::No
 +    };
      let resolve::CrateMap {
          def_map,
          freevars,
          export_map,
          trait_map,
          external_exports,
 -        last_private_map
 +        last_private_map,
 +        glob_map,
      } =
          time(time_passes, "resolution", (),
 -             |_| resolve::resolve_crate(&sess, &lang_items, krate));
 +             |_| resolve::resolve_crate(&sess,
 +                                        &ast_map,
 +                                        &lang_items,
 +                                        krate,
 +                                        make_glob_map));
  
      // Discard MTWT tables that aren't required past resolution.
      syntax::ext::mtwt::clear_tables();
           middle::check_static_recursion::check_crate(&sess, krate, &def_map, &ast_map));
  
      let ty_cx = ty::mk_ctxt(sess,
 -                            type_arena,
 +                            arenas,
                              def_map,
                              named_region_map,
                              ast_map,
          public_items: public_items,
          reachable: reachable_map,
          name: name,
 +        glob_map: glob_map,
      }
  }
  
 +fn save_analysis(sess: &Session) -> bool {
 +    (sess.opts.debugging_opts & config::SAVE_ANALYSIS) != 0
 +}
 +
  pub fn phase_save_analysis(sess: &Session,
                             krate: &ast::Crate,
                             analysis: &ty::CrateAnalysis,
                             odir: &Option<Path>) {
 -    if (sess.opts.debugging_opts & config::SAVE_ANALYSIS) == 0 {
 +    if !save_analysis(sess) {
          return;
      }
      time(sess.time_passes(), "save analysis", krate, |krate|
@@@ -541,7 -517,7 +542,7 @@@ pub fn phase_6_link_output(sess: &Sessi
                             trans: &trans::CrateTranslation,
                             outputs: &OutputFilenames) {
      let old_path = os::getenv("PATH").unwrap_or_else(||String::new());
-     let mut new_path = sess.host_filesearch().get_tools_search_paths();
+     let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths();
      new_path.extend(os::split_paths(old_path[]).into_iter());
      os::setenv("PATH", os::join_paths(new_path[]).unwrap());
  
diff --combined src/librustdoc/core.rs
index 59883f37737f0c1a866660b67490965bcc739903,a80de6e805b25212eb9eb694f7fad2cad20e7846..2416eb2869ee2585ed62354be61bb3e8822352f1
@@@ -11,6 -11,7 +11,7 @@@ pub use self::MaybeTyped::*
  
  use rustc_driver::driver;
  use rustc::session::{mod, config};
+ use rustc::session::search_paths::SearchPaths;
  use rustc::middle::{privacy, ty};
  use rustc::lint;
  use rustc_trans::back::link;
@@@ -19,6 -20,7 +20,6 @@@ use syntax::{ast, ast_map, codemap, dia
  
  use std::cell::RefCell;
  use std::collections::{HashMap, HashSet};
 -use arena::TypedArena;
  
  use visit_ast::RustdocVisitor;
  use clean;
@@@ -76,7 -78,7 +77,7 @@@ pub struct CrateAnalysis 
  
  pub type Externs = HashMap<String, Vec<String>>;
  
- pub fn run_core(libs: Vec<Path>, cfgs: Vec<String>, externs: Externs,
+ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
                  cpath: &Path, triple: Option<String>)
                  -> (clean::Crate, CrateAnalysis) {
  
@@@ -88,7 -90,7 +89,7 @@@
  
      let sessopts = config::Options {
          maybe_sysroot: None,
-         addl_lib_search_paths: RefCell::new(libs),
+         search_paths: search_paths,
          crate_types: vec!(config::CrateTypeRlib),
          lint_opts: vec!((warning_lint, lint::Allow)),
          externs: externs,
      let mut forest = ast_map::Forest::new(krate);
      let ast_map = driver::assign_node_ids_and_map(&sess, &mut forest);
  
 -    let type_arena = TypedArena::new();
 +    let arenas = ty::CtxtArenas::new();
      let ty::CrateAnalysis {
          exported_items, public_items, ty_cx, ..
 -    } = driver::phase_3_run_analysis_passes(sess, ast_map, &type_arena, name);
 +    } = driver::phase_3_run_analysis_passes(sess, ast_map, &arenas, name);
  
      let ctxt = DocContext {
          krate: ty_cx.map.krate(),