]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/session/mod.rs
save a borrow by using return value of HashSet::insert
[rust.git] / src / librustc / session / mod.rs
index 268dbd70bb5bb2f8cd1bdde4a9c4e8bbd4efbbd2..f4029fde471b94fe77909c63ab450e642b01a37a 100644 (file)
@@ -15,9 +15,9 @@
 use middle::cstore::CrateStore;
 use middle::dependency_format;
 use session::search_paths::PathKind;
-use session::config::{DebugInfoLevel, PanicStrategy};
+use session::config::DebugInfoLevel;
 use ty::tls;
-use util::nodemap::{NodeMap, FnvHashMap};
+use util::nodemap::{NodeMap, FnvHashMap, FnvHashSet};
 use util::common::duration_to_secs_str;
 use mir::transform as mir_pass;
 
@@ -33,6 +33,7 @@
 use syntax::feature_gate::AttributeType;
 use syntax_pos::{Span, MultiSpan};
 
+use rustc_back::PanicStrategy;
 use rustc_back::target::Target;
 use rustc_data_structures::flock;
 use llvm;
@@ -42,6 +43,7 @@
 use std::collections::HashMap;
 use std::env;
 use std::ffi::CString;
+use std::io::Write;
 use std::rc::Rc;
 use std::fmt;
 use std::time::Duration;
@@ -73,6 +75,10 @@ pub struct Session {
     pub working_dir: PathBuf,
     pub lint_store: RefCell<lint::LintStore>,
     pub lints: RefCell<NodeMap<Vec<(lint::LintId, Span, String)>>>,
+    /// Set of (span, message) tuples tracking lint (sub)diagnostics that have
+    /// been set once, but should not be set again, in order to avoid
+    /// redundantly verbose output (Issue #24690).
+    pub one_time_diagnostics: RefCell<FnvHashSet<(Span, String)>>,
     pub plugin_llvm_passes: RefCell<Vec<String>>,
     pub mir_passes: RefCell<mir_pass::Passes>,
     pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>,
@@ -116,6 +122,8 @@ pub struct PerfStats {
     pub incr_comp_hashes_time: Cell<Duration>,
     // The number of incr. comp. hash computations performed
     pub incr_comp_hashes_count: Cell<u64>,
+    // The number of bytes hashed when computing ICH values
+    pub incr_comp_bytes_hashed: Cell<u64>,
     // The accumulated time spent on computing symbol hashes
     pub symbol_hash_time: Cell<Duration>,
 }
@@ -284,6 +292,24 @@ pub fn next_node_id(&self) -> NodeId {
     pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler {
         &self.parse_sess.span_diagnostic
     }
+
+    /// Analogous to calling `.span_note` on the given DiagnosticBuilder, but
+    /// deduplicates on span and message for this `Session`.
+    //
+    // FIXME: if the need arises for one-time diagnostics other than
+    // `span_note`, we almost certainly want to generalize this
+    // "check/insert-into the one-time diagnostics map, then set message if
+    // it's not already there" code to accomodate all of them
+    pub fn diag_span_note_once<'a, 'b>(&'a self,
+                                       diag_builder: &'b mut DiagnosticBuilder<'a>,
+                                       span: Span, message: &str) {
+        let span_message = (span, message.to_owned());
+        let fresh = self.one_time_diagnostics.borrow_mut().insert(span_message);
+        if fresh {
+            diag_builder.span_note(span, &message);
+        }
+    }
+
     pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap {
         self.parse_sess.codemap()
     }
@@ -306,9 +332,13 @@ pub fn print_llvm_passes(&self) -> bool {
     pub fn lto(&self) -> bool {
         self.opts.cg.lto
     }
+    /// Returns the panic strategy for this compile session. If the user explicitly selected one
+    /// using '-C panic', use that, otherwise use the panic strategy defined by the target.
+    pub fn panic_strategy(&self) -> PanicStrategy {
+        self.opts.cg.panic.unwrap_or(self.target.target.options.panic_strategy)
+    }
     pub fn no_landing_pads(&self) -> bool {
-        self.opts.debugging_opts.no_landing_pads ||
-            self.opts.cg.panic == PanicStrategy::Abort
+        self.opts.debugging_opts.no_landing_pads || self.panic_strategy() == PanicStrategy::Abort
     }
     pub fn unstable_options(&self) -> bool {
         self.opts.debugging_opts.unstable_options
@@ -433,6 +463,11 @@ pub fn print_perf_stats(&self) {
                  duration_to_secs_str(self.perf_stats.incr_comp_hashes_time.get()));
         println!("Total number of incr. comp. hashes computed:   {}",
                  self.perf_stats.incr_comp_hashes_count.get());
+        println!("Total number of bytes hashed for incr. comp.:  {}",
+                 self.perf_stats.incr_comp_bytes_hashed.get());
+        println!("Average bytes hashed per incr. comp. HIR node: {}",
+                 self.perf_stats.incr_comp_bytes_hashed.get() /
+                 self.perf_stats.incr_comp_hashes_count.get());
         println!("Total time spent computing symbol hashes:      {}",
                  duration_to_secs_str(self.perf_stats.symbol_hash_time.get()));
     }
@@ -449,7 +484,8 @@ pub fn build_session(sopts: config::Options,
                                local_crate_source_file,
                                registry,
                                cstore,
-                               Rc::new(codemap::CodeMap::new()))
+                               Rc::new(codemap::CodeMap::new()),
+                               None)
 }
 
 pub fn build_session_with_codemap(sopts: config::Options,
@@ -457,7 +493,8 @@ pub fn build_session_with_codemap(sopts: config::Options,
                                   local_crate_source_file: Option<PathBuf>,
                                   registry: errors::registry::Registry,
                                   cstore: Rc<for<'a> CrateStore<'a>>,
-                                  codemap: Rc<codemap::CodeMap>)
+                                  codemap: Rc<codemap::CodeMap>,
+                                  emitter_dest: Option<Box<Write + Send>>)
                                   -> Session {
     // FIXME: This is not general enough to make the warning lint completely override
     // normal diagnostic warnings, since the warning lint can also be denied and changed
@@ -470,14 +507,21 @@ pub fn build_session_with_codemap(sopts: config::Options,
         .unwrap_or(true);
     let treat_err_as_bug = sopts.debugging_opts.treat_err_as_bug;
 
-    let emitter: Box<Emitter> = match sopts.error_format {
-        config::ErrorOutputType::HumanReadable(color_config) => {
+    let emitter: Box<Emitter> = match (sopts.error_format, emitter_dest) {
+        (config::ErrorOutputType::HumanReadable(color_config), None) => {
             Box::new(EmitterWriter::stderr(color_config,
                                            Some(codemap.clone())))
         }
-        config::ErrorOutputType::Json => {
+        (config::ErrorOutputType::HumanReadable(_), Some(dst)) => {
+            Box::new(EmitterWriter::new(dst,
+                                        Some(codemap.clone())))
+        }
+        (config::ErrorOutputType::Json, None) => {
             Box::new(JsonEmitter::stderr(Some(registry), codemap.clone()))
         }
+        (config::ErrorOutputType::Json, Some(dst)) => {
+            Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone()))
+        }
     };
 
     let diagnostic_handler =
@@ -539,6 +583,7 @@ pub fn build_session_(sopts: config::Options,
         working_dir: env::current_dir().unwrap(),
         lint_store: RefCell::new(lint::LintStore::new()),
         lints: RefCell::new(NodeMap()),
+        one_time_diagnostics: RefCell::new(FnvHashSet()),
         plugin_llvm_passes: RefCell::new(Vec::new()),
         mir_passes: RefCell::new(mir_pass::Passes::new()),
         plugin_attributes: RefCell::new(Vec::new()),
@@ -556,6 +601,7 @@ pub fn build_session_(sopts: config::Options,
             svh_time: Cell::new(Duration::from_secs(0)),
             incr_comp_hashes_time: Cell::new(Duration::from_secs(0)),
             incr_comp_hashes_count: Cell::new(0),
+            incr_comp_bytes_hashed: Cell::new(0),
             symbol_hash_time: Cell::new(Duration::from_secs(0)),
         }
     };