1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 pub use self::code_stats
::{CodeStats, DataTypeKind, FieldInfo}
;
12 pub use self::code_stats
::{SizeKind, TypeSizeInfo, VariantInfo}
;
14 use dep_graph
::DepGraph
;
15 use hir
::def_id
::{CrateNum, DefIndex}
;
18 use middle
::cstore
::CrateStore
;
19 use middle
::dependency_format
;
20 use session
::search_paths
::PathKind
;
21 use session
::config
::DebugInfoLevel
;
23 use util
::nodemap
::{FxHashMap, FxHashSet}
;
24 use util
::common
::duration_to_secs_str
;
26 use syntax
::ast
::NodeId
;
27 use errors
::{self, DiagnosticBuilder}
;
28 use errors
::emitter
::{Emitter, EmitterWriter}
;
29 use syntax
::json
::JsonEmitter
;
30 use syntax
::feature_gate
;
32 use syntax
::parse
::ParseSess
;
33 use syntax
::symbol
::Symbol
;
34 use syntax
::{ast, codemap}
;
35 use syntax
::feature_gate
::AttributeType
;
36 use syntax_pos
::{Span, MultiSpan}
;
38 use rustc_back
::{LinkerFlavor, PanicStrategy}
;
39 use rustc_back
::target
::Target
;
40 use rustc_data_structures
::flock
;
42 use std
::path
::{Path, PathBuf}
;
43 use std
::cell
::{self, Cell, RefCell}
;
44 use std
::collections
::HashMap
;
49 use std
::time
::Duration
;
56 // Represents the data associated with a compilation
57 // session for a single crate.
59 pub dep_graph
: DepGraph
,
60 pub target
: config
::Config
,
62 pub opts
: config
::Options
,
63 pub cstore
: Rc
<CrateStore
>,
64 pub parse_sess
: ParseSess
,
65 // For a library crate, this is always none
66 pub entry_fn
: RefCell
<Option
<(NodeId
, Span
)>>,
67 pub entry_type
: Cell
<Option
<config
::EntryFnType
>>,
68 pub plugin_registrar_fn
: Cell
<Option
<ast
::NodeId
>>,
69 pub derive_registrar_fn
: Cell
<Option
<ast
::NodeId
>>,
70 pub default_sysroot
: Option
<PathBuf
>,
71 // The name of the root source file of the crate, in the local file system.
72 // The path is always expected to be absolute. `None` means that there is no
74 pub local_crate_source_file
: Option
<String
>,
75 // The directory the compiler has been executed in plus a flag indicating
76 // if the value stored here has been affected by path remapping.
77 pub working_dir
: (String
, bool
),
78 pub lint_store
: RefCell
<lint
::LintStore
>,
79 pub lints
: RefCell
<lint
::LintTable
>,
80 /// Set of (LintId, span, message) tuples tracking lint (sub)diagnostics
81 /// that have been set once, but should not be set again, in order to avoid
82 /// redundantly verbose output (Issue #24690).
83 pub one_time_diagnostics
: RefCell
<FxHashSet
<(lint
::LintId
, Span
, String
)>>,
84 pub plugin_llvm_passes
: RefCell
<Vec
<String
>>,
85 pub plugin_attributes
: RefCell
<Vec
<(String
, AttributeType
)>>,
86 pub crate_types
: RefCell
<Vec
<config
::CrateType
>>,
87 pub dependency_formats
: RefCell
<dependency_format
::Dependencies
>,
88 // The crate_disambiguator is constructed out of all the `-C metadata`
89 // arguments passed to the compiler. Its value together with the crate-name
90 // forms a unique global identifier for the crate. It is used to allow
91 // multiple crates with the same name to coexist. See the
92 // trans::back::symbol_names module for more information.
93 pub crate_disambiguator
: RefCell
<Symbol
>,
94 pub features
: RefCell
<feature_gate
::Features
>,
96 /// The maximum recursion limit for potentially infinitely recursive
97 /// operations such as auto-dereference and monomorphization.
98 pub recursion_limit
: Cell
<usize>,
100 /// The maximum length of types during monomorphization.
101 pub type_length_limit
: Cell
<usize>,
103 /// The metadata::creader module may inject an allocator/panic_runtime
104 /// dependency if it didn't already find one, and this tracks what was
106 pub injected_allocator
: Cell
<Option
<CrateNum
>>,
107 pub injected_panic_runtime
: Cell
<Option
<CrateNum
>>,
109 /// Map from imported macro spans (which consist of
110 /// the localized span for the macro body) to the
111 /// macro name and defintion span in the source crate.
112 pub imported_macro_spans
: RefCell
<HashMap
<Span
, (String
, Span
)>>,
114 incr_comp_session
: RefCell
<IncrCompSession
>,
116 /// Some measurements that are being gathered during compilation.
117 pub perf_stats
: PerfStats
,
119 /// Data about code being compiled, gathered during compilation.
120 pub code_stats
: RefCell
<CodeStats
>,
122 next_node_id
: Cell
<ast
::NodeId
>,
124 /// If -zfuel=crate=n is specified, Some(crate).
125 optimization_fuel_crate
: Option
<String
>,
126 /// If -zfuel=crate=n is specified, initially set to n. Otherwise 0.
127 optimization_fuel_limit
: Cell
<u64>,
128 /// We're rejecting all further optimizations.
129 out_of_fuel
: Cell
<bool
>,
131 // The next two are public because the driver needs to read them.
133 /// If -zprint-fuel=crate, Some(crate).
134 pub print_fuel_crate
: Option
<String
>,
135 /// Always set to zero and incremented so that we can print fuel expended by a crate.
136 pub print_fuel
: Cell
<u64>,
139 pub struct PerfStats
{
140 // The accumulated time needed for computing the SVH of the crate
141 pub svh_time
: Cell
<Duration
>,
142 // The accumulated time spent on computing incr. comp. hashes
143 pub incr_comp_hashes_time
: Cell
<Duration
>,
144 // The number of incr. comp. hash computations performed
145 pub incr_comp_hashes_count
: Cell
<u64>,
146 // The number of bytes hashed when computing ICH values
147 pub incr_comp_bytes_hashed
: Cell
<u64>,
148 // The accumulated time spent on computing symbol hashes
149 pub symbol_hash_time
: Cell
<Duration
>,
150 // The accumulated time spent decoding def path tables from metadata
151 pub decode_def_path_tables_time
: Cell
<Duration
>,
155 pub fn local_crate_disambiguator(&self) -> Symbol
{
156 *self.crate_disambiguator
.borrow()
158 pub fn struct_span_warn
<'a
, S
: Into
<MultiSpan
>>(&'a
self,
161 -> DiagnosticBuilder
<'a
> {
162 self.diagnostic().struct_span_warn(sp
, msg
)
164 pub fn struct_span_warn_with_code
<'a
, S
: Into
<MultiSpan
>>(&'a
self,
168 -> DiagnosticBuilder
<'a
> {
169 self.diagnostic().struct_span_warn_with_code(sp
, msg
, code
)
171 pub fn struct_warn
<'a
>(&'a
self, msg
: &str) -> DiagnosticBuilder
<'a
> {
172 self.diagnostic().struct_warn(msg
)
174 pub fn struct_span_err
<'a
, S
: Into
<MultiSpan
>>(&'a
self,
177 -> DiagnosticBuilder
<'a
> {
178 self.diagnostic().struct_span_err(sp
, msg
)
180 pub fn struct_span_err_with_code
<'a
, S
: Into
<MultiSpan
>>(&'a
self,
184 -> DiagnosticBuilder
<'a
> {
185 self.diagnostic().struct_span_err_with_code(sp
, msg
, code
)
187 // FIXME: This method should be removed (every error should have an associated error code).
188 pub fn struct_err
<'a
>(&'a
self, msg
: &str) -> DiagnosticBuilder
<'a
> {
189 self.diagnostic().struct_err(msg
)
191 pub fn struct_err_with_code
<'a
>(&'a
self, msg
: &str, code
: &str) -> DiagnosticBuilder
<'a
> {
192 self.diagnostic().struct_err_with_code(msg
, code
)
194 pub fn struct_span_fatal
<'a
, S
: Into
<MultiSpan
>>(&'a
self,
197 -> DiagnosticBuilder
<'a
> {
198 self.diagnostic().struct_span_fatal(sp
, msg
)
200 pub fn struct_span_fatal_with_code
<'a
, S
: Into
<MultiSpan
>>(&'a
self,
204 -> DiagnosticBuilder
<'a
> {
205 self.diagnostic().struct_span_fatal_with_code(sp
, msg
, code
)
207 pub fn struct_fatal
<'a
>(&'a
self, msg
: &str) -> DiagnosticBuilder
<'a
> {
208 self.diagnostic().struct_fatal(msg
)
211 pub fn span_fatal
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) -> ! {
212 panic
!(self.diagnostic().span_fatal(sp
, msg
))
214 pub fn span_fatal_with_code
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str, code
: &str) -> ! {
215 panic
!(self.diagnostic().span_fatal_with_code(sp
, msg
, code
))
217 pub fn fatal(&self, msg
: &str) -> ! {
218 panic
!(self.diagnostic().fatal(msg
))
220 pub fn span_err_or_warn
<S
: Into
<MultiSpan
>>(&self, is_warning
: bool
, sp
: S
, msg
: &str) {
222 self.span_warn(sp
, msg
);
224 self.span_err(sp
, msg
);
227 pub fn span_err
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) {
228 self.diagnostic().span_err(sp
, msg
)
230 pub fn span_err_with_code
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str, code
: &str) {
231 self.diagnostic().span_err_with_code(sp
, &msg
, code
)
233 pub fn err(&self, msg
: &str) {
234 self.diagnostic().err(msg
)
236 pub fn err_count(&self) -> usize {
237 self.diagnostic().err_count()
239 pub fn has_errors(&self) -> bool
{
240 self.diagnostic().has_errors()
242 pub fn abort_if_errors(&self) {
243 self.diagnostic().abort_if_errors();
245 pub fn track_errors
<F
, T
>(&self, f
: F
) -> Result
<T
, usize>
246 where F
: FnOnce() -> T
248 let old_count
= self.err_count();
250 let errors
= self.err_count() - old_count
;
257 pub fn span_warn
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) {
258 self.diagnostic().span_warn(sp
, msg
)
260 pub fn span_warn_with_code
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str, code
: &str) {
261 self.diagnostic().span_warn_with_code(sp
, msg
, code
)
263 pub fn warn(&self, msg
: &str) {
264 self.diagnostic().warn(msg
)
266 pub fn opt_span_warn
<S
: Into
<MultiSpan
>>(&self, opt_sp
: Option
<S
>, msg
: &str) {
268 Some(sp
) => self.span_warn(sp
, msg
),
269 None
=> self.warn(msg
),
272 /// Delay a span_bug() call until abort_if_errors()
273 pub fn delay_span_bug
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) {
274 self.diagnostic().delay_span_bug(sp
, msg
)
276 pub fn note_without_error(&self, msg
: &str) {
277 self.diagnostic().note_without_error(msg
)
279 pub fn span_note_without_error
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) {
280 self.diagnostic().span_note_without_error(sp
, msg
)
282 pub fn span_unimpl
<S
: Into
<MultiSpan
>>(&self, sp
: S
, msg
: &str) -> ! {
283 self.diagnostic().span_unimpl(sp
, msg
)
285 pub fn unimpl(&self, msg
: &str) -> ! {
286 self.diagnostic().unimpl(msg
)
289 pub fn add_lint
<S
: Into
<MultiSpan
>>(&self,
290 lint
: &'
static lint
::Lint
,
295 self.lints
.borrow_mut().add_lint(lint
, id
, sp
, msg
);
298 pub fn add_lint_diagnostic
<M
>(&self,
299 lint
: &'
static lint
::Lint
,
302 where M
: lint
::IntoEarlyLint
,
304 self.lints
.borrow_mut().add_lint_diagnostic(lint
, id
, msg
);
307 pub fn reserve_node_ids(&self, count
: usize) -> ast
::NodeId
{
308 let id
= self.next_node_id
.get();
310 match id
.as_usize().checked_add(count
) {
312 self.next_node_id
.set(ast
::NodeId
::new(next
));
314 None
=> bug
!("Input too large, ran out of node ids!")
319 pub fn next_node_id(&self) -> NodeId
{
320 self.reserve_node_ids(1)
322 pub fn diagnostic
<'a
>(&'a
self) -> &'a errors
::Handler
{
323 &self.parse_sess
.span_diagnostic
326 /// Analogous to calling `.span_note` on the given DiagnosticBuilder, but
327 /// deduplicates on lint ID, span, and message for this `Session` if we're
328 /// not outputting in JSON mode.
330 // FIXME: if the need arises for one-time diagnostics other than
331 // `span_note`, we almost certainly want to generalize this
332 // "check/insert-into the one-time diagnostics map, then set message if
333 // it's not already there" code to accomodate all of them
334 pub fn diag_span_note_once
<'a
, 'b
>(&'a
self,
335 diag_builder
: &'b
mut DiagnosticBuilder
<'a
>,
336 lint
: &'
static lint
::Lint
, span
: Span
, message
: &str) {
337 match self.opts
.error_format
{
338 // when outputting JSON for tool consumption, the tool might want
340 config
::ErrorOutputType
::Json
=> {
341 diag_builder
.span_note(span
, &message
);
344 let lint_id
= lint
::LintId
::of(lint
);
345 let id_span_message
= (lint_id
, span
, message
.to_owned());
346 let fresh
= self.one_time_diagnostics
.borrow_mut().insert(id_span_message
);
348 diag_builder
.span_note(span
, &message
);
354 pub fn codemap
<'a
>(&'a
self) -> &'a codemap
::CodeMap
{
355 self.parse_sess
.codemap()
357 pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose }
358 pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes }
359 pub fn count_llvm_insns(&self) -> bool
{
360 self.opts
.debugging_opts
.count_llvm_insns
362 pub fn time_llvm_passes(&self) -> bool
{
363 self.opts
.debugging_opts
.time_llvm_passes
365 pub fn trans_stats(&self) -> bool { self.opts.debugging_opts.trans_stats }
366 pub fn meta_stats(&self) -> bool { self.opts.debugging_opts.meta_stats }
367 pub fn asm_comments(&self) -> bool { self.opts.debugging_opts.asm_comments }
368 pub fn no_verify(&self) -> bool { self.opts.debugging_opts.no_verify }
369 pub fn borrowck_stats(&self) -> bool { self.opts.debugging_opts.borrowck_stats }
370 pub fn print_llvm_passes(&self) -> bool
{
371 self.opts
.debugging_opts
.print_llvm_passes
373 pub fn lto(&self) -> bool
{
376 /// Returns the panic strategy for this compile session. If the user explicitly selected one
377 /// using '-C panic', use that, otherwise use the panic strategy defined by the target.
378 pub fn panic_strategy(&self) -> PanicStrategy
{
379 self.opts
.cg
.panic
.unwrap_or(self.target
.target
.options
.panic_strategy
)
381 pub fn linker_flavor(&self) -> LinkerFlavor
{
382 self.opts
.debugging_opts
.linker_flavor
.unwrap_or(self.target
.target
.linker_flavor
)
384 pub fn no_landing_pads(&self) -> bool
{
385 self.opts
.debugging_opts
.no_landing_pads
|| self.panic_strategy() == PanicStrategy
::Abort
387 pub fn unstable_options(&self) -> bool
{
388 self.opts
.debugging_opts
.unstable_options
390 pub fn nonzeroing_move_hints(&self) -> bool
{
391 self.opts
.debugging_opts
.enable_nonzeroing_move_hints
393 pub fn overflow_checks(&self) -> bool
{
394 self.opts
.cg
.overflow_checks
395 .or(self.opts
.debugging_opts
.force_overflow_checks
)
396 .unwrap_or(self.opts
.debug_assertions
)
399 pub fn must_not_eliminate_frame_pointers(&self) -> bool
{
400 self.opts
.debuginfo
!= DebugInfoLevel
::NoDebugInfo
||
401 !self.target
.target
.options
.eliminate_frame_pointer
404 /// Returns the symbol name for the registrar function,
405 /// given the crate Svh and the function DefIndex.
406 pub fn generate_plugin_registrar_symbol(&self, disambiguator
: Symbol
, index
: DefIndex
)
408 format
!("__rustc_plugin_registrar__{}_{}", disambiguator
, index
.as_usize())
411 pub fn generate_derive_registrar_symbol(&self, disambiguator
: Symbol
, index
: DefIndex
)
413 format
!("__rustc_derive_registrar__{}_{}", disambiguator
, index
.as_usize())
416 pub fn sysroot
<'a
>(&'a
self) -> &'a Path
{
417 match self.opts
.maybe_sysroot
{
418 Some (ref sysroot
) => sysroot
,
419 None
=> self.default_sysroot
.as_ref()
420 .expect("missing sysroot and default_sysroot in Session")
423 pub fn target_filesearch(&self, kind
: PathKind
) -> filesearch
::FileSearch
{
424 filesearch
::FileSearch
::new(self.sysroot(),
425 &self.opts
.target_triple
,
426 &self.opts
.search_paths
,
429 pub fn host_filesearch(&self, kind
: PathKind
) -> filesearch
::FileSearch
{
430 filesearch
::FileSearch
::new(
432 config
::host_triple(),
433 &self.opts
.search_paths
,
437 pub fn init_incr_comp_session(&self,
438 session_dir
: PathBuf
,
439 lock_file
: flock
::Lock
) {
440 let mut incr_comp_session
= self.incr_comp_session
.borrow_mut();
442 if let IncrCompSession
::NotInitialized
= *incr_comp_session { }
else {
443 bug
!("Trying to initialize IncrCompSession `{:?}`", *incr_comp_session
)
446 *incr_comp_session
= IncrCompSession
::Active
{
447 session_directory
: session_dir
,
448 lock_file
: lock_file
,
452 pub fn finalize_incr_comp_session(&self, new_directory_path
: PathBuf
) {
453 let mut incr_comp_session
= self.incr_comp_session
.borrow_mut();
455 if let IncrCompSession
::Active { .. }
= *incr_comp_session { }
else {
456 bug
!("Trying to finalize IncrCompSession `{:?}`", *incr_comp_session
)
459 // Note: This will also drop the lock file, thus unlocking the directory
460 *incr_comp_session
= IncrCompSession
::Finalized
{
461 session_directory
: new_directory_path
,
465 pub fn mark_incr_comp_session_as_invalid(&self) {
466 let mut incr_comp_session
= self.incr_comp_session
.borrow_mut();
468 let session_directory
= match *incr_comp_session
{
469 IncrCompSession
::Active { ref session_directory, .. }
=> {
470 session_directory
.clone()
472 _
=> bug
!("Trying to invalidate IncrCompSession `{:?}`",
476 // Note: This will also drop the lock file, thus unlocking the directory
477 *incr_comp_session
= IncrCompSession
::InvalidBecauseOfErrors
{
478 session_directory
: session_directory
482 pub fn incr_comp_session_dir(&self) -> cell
::Ref
<PathBuf
> {
483 let incr_comp_session
= self.incr_comp_session
.borrow();
484 cell
::Ref
::map(incr_comp_session
, |incr_comp_session
| {
485 match *incr_comp_session
{
486 IncrCompSession
::NotInitialized
=> {
487 bug
!("Trying to get session directory from IncrCompSession `{:?}`",
490 IncrCompSession
::Active { ref session_directory, .. }
|
491 IncrCompSession
::Finalized { ref session_directory }
|
492 IncrCompSession
::InvalidBecauseOfErrors { ref session_directory }
=> {
499 pub fn incr_comp_session_dir_opt(&self) -> Option
<cell
::Ref
<PathBuf
>> {
500 if self.opts
.incremental
.is_some() {
501 Some(self.incr_comp_session_dir())
507 pub fn print_perf_stats(&self) {
508 println
!("Total time spent computing SVHs: {}",
509 duration_to_secs_str(self.perf_stats
.svh_time
.get()));
510 println
!("Total time spent computing incr. comp. hashes: {}",
511 duration_to_secs_str(self.perf_stats
.incr_comp_hashes_time
.get()));
512 println
!("Total number of incr. comp. hashes computed: {}",
513 self.perf_stats
.incr_comp_hashes_count
.get());
514 println
!("Total number of bytes hashed for incr. comp.: {}",
515 self.perf_stats
.incr_comp_bytes_hashed
.get());
516 println
!("Average bytes hashed per incr. comp. HIR node: {}",
517 self.perf_stats
.incr_comp_bytes_hashed
.get() /
518 self.perf_stats
.incr_comp_hashes_count
.get());
519 println
!("Total time spent computing symbol hashes: {}",
520 duration_to_secs_str(self.perf_stats
.symbol_hash_time
.get()));
521 println
!("Total time spent decoding DefPath tables: {}",
522 duration_to_secs_str(self.perf_stats
.decode_def_path_tables_time
.get()));
525 /// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
526 /// This expends fuel if applicable, and records fuel if applicable.
527 pub fn consider_optimizing
<T
: Fn() -> String
>(&self, crate_name
: &str, msg
: T
) -> bool
{
529 match self.optimization_fuel_crate
{
530 Some(ref c
) if c
== crate_name
=> {
531 let fuel
= self.optimization_fuel_limit
.get();
533 if fuel
== 0 && !self.out_of_fuel
.get() {
534 println
!("optimization-fuel-exhausted: {}", msg());
535 self.out_of_fuel
.set(true);
537 self.optimization_fuel_limit
.set(fuel
-1);
542 match self.print_fuel_crate
{
543 Some(ref c
) if c
== crate_name
=> {
544 self.print_fuel
.set(self.print_fuel
.get()+1);
552 pub fn build_session(sopts
: config
::Options
,
553 dep_graph
: &DepGraph
,
554 local_crate_source_file
: Option
<PathBuf
>,
555 registry
: errors
::registry
::Registry
,
556 cstore
: Rc
<CrateStore
>)
558 let file_path_mapping
= sopts
.file_path_mapping();
560 build_session_with_codemap(sopts
,
562 local_crate_source_file
,
565 Rc
::new(codemap
::CodeMap
::new(file_path_mapping
)),
569 pub fn build_session_with_codemap(sopts
: config
::Options
,
570 dep_graph
: &DepGraph
,
571 local_crate_source_file
: Option
<PathBuf
>,
572 registry
: errors
::registry
::Registry
,
573 cstore
: Rc
<CrateStore
>,
574 codemap
: Rc
<codemap
::CodeMap
>,
575 emitter_dest
: Option
<Box
<Write
+ Send
>>)
577 // FIXME: This is not general enough to make the warning lint completely override
578 // normal diagnostic warnings, since the warning lint can also be denied and changed
579 // later via the source code.
580 let can_print_warnings
= sopts
.lint_opts
582 .filter(|&&(ref key
, _
)| *key
== "warnings")
583 .map(|&(_
, ref level
)| *level
!= lint
::Allow
)
586 let treat_err_as_bug
= sopts
.debugging_opts
.treat_err_as_bug
;
588 let emitter
: Box
<Emitter
> = match (sopts
.error_format
, emitter_dest
) {
589 (config
::ErrorOutputType
::HumanReadable(color_config
), None
) => {
590 Box
::new(EmitterWriter
::stderr(color_config
,
591 Some(codemap
.clone())))
593 (config
::ErrorOutputType
::HumanReadable(_
), Some(dst
)) => {
594 Box
::new(EmitterWriter
::new(dst
,
595 Some(codemap
.clone())))
597 (config
::ErrorOutputType
::Json
, None
) => {
598 Box
::new(JsonEmitter
::stderr(Some(registry
), codemap
.clone()))
600 (config
::ErrorOutputType
::Json
, Some(dst
)) => {
601 Box
::new(JsonEmitter
::new(dst
, Some(registry
), codemap
.clone()))
605 let diagnostic_handler
=
606 errors
::Handler
::with_emitter(can_print_warnings
,
610 build_session_(sopts
,
612 local_crate_source_file
,
618 pub fn build_session_(sopts
: config
::Options
,
619 dep_graph
: &DepGraph
,
620 local_crate_source_file
: Option
<PathBuf
>,
621 span_diagnostic
: errors
::Handler
,
622 codemap
: Rc
<codemap
::CodeMap
>,
623 cstore
: Rc
<CrateStore
>)
625 let host
= match Target
::search(config
::host_triple()) {
628 panic
!(span_diagnostic
.fatal(&format
!("Error loading host specification: {}", e
)));
631 let target_cfg
= config
::build_target_config(&sopts
, &span_diagnostic
);
633 let p_s
= parse
::ParseSess
::with_span_handler(span_diagnostic
, codemap
);
634 let default_sysroot
= match sopts
.maybe_sysroot
{
636 None
=> Some(filesearch
::get_or_default_sysroot())
639 let file_path_mapping
= sopts
.file_path_mapping();
641 // Make the path absolute, if necessary
642 let local_crate_source_file
= local_crate_source_file
.map(|path
| {
643 file_path_mapping
.map_prefix(path
.to_string_lossy().into_owned()).0
646 let optimization_fuel_crate
= sopts
.debugging_opts
.fuel
.as_ref().map(|i
| i
.0.clone());
647 let optimization_fuel_limit
= Cell
::new(sopts
.debugging_opts
.fuel
.as_ref()
648 .map(|i
| i
.1).unwrap_or(0));
649 let print_fuel_crate
= sopts
.debugging_opts
.print_fuel
.clone();
650 let print_fuel
= Cell
::new(0);
652 let working_dir
= env
::current_dir().unwrap().to_string_lossy().into_owned();
653 let working_dir
= file_path_mapping
.map_prefix(working_dir
);
656 dep_graph
: dep_graph
.clone(),
662 // For a library crate, this is always none
663 entry_fn
: RefCell
::new(None
),
664 entry_type
: Cell
::new(None
),
665 plugin_registrar_fn
: Cell
::new(None
),
666 derive_registrar_fn
: Cell
::new(None
),
667 default_sysroot
: default_sysroot
,
668 local_crate_source_file
: local_crate_source_file
,
669 working_dir
: working_dir
,
670 lint_store
: RefCell
::new(lint
::LintStore
::new()),
671 lints
: RefCell
::new(lint
::LintTable
::new()),
672 one_time_diagnostics
: RefCell
::new(FxHashSet()),
673 plugin_llvm_passes
: RefCell
::new(Vec
::new()),
674 plugin_attributes
: RefCell
::new(Vec
::new()),
675 crate_types
: RefCell
::new(Vec
::new()),
676 dependency_formats
: RefCell
::new(FxHashMap()),
677 crate_disambiguator
: RefCell
::new(Symbol
::intern("")),
678 features
: RefCell
::new(feature_gate
::Features
::new()),
679 recursion_limit
: Cell
::new(64),
680 type_length_limit
: Cell
::new(1048576),
681 next_node_id
: Cell
::new(NodeId
::new(1)),
682 injected_allocator
: Cell
::new(None
),
683 injected_panic_runtime
: Cell
::new(None
),
684 imported_macro_spans
: RefCell
::new(HashMap
::new()),
685 incr_comp_session
: RefCell
::new(IncrCompSession
::NotInitialized
),
686 perf_stats
: PerfStats
{
687 svh_time
: Cell
::new(Duration
::from_secs(0)),
688 incr_comp_hashes_time
: Cell
::new(Duration
::from_secs(0)),
689 incr_comp_hashes_count
: Cell
::new(0),
690 incr_comp_bytes_hashed
: Cell
::new(0),
691 symbol_hash_time
: Cell
::new(Duration
::from_secs(0)),
692 decode_def_path_tables_time
: Cell
::new(Duration
::from_secs(0)),
694 code_stats
: RefCell
::new(CodeStats
::new()),
695 optimization_fuel_crate
: optimization_fuel_crate
,
696 optimization_fuel_limit
: optimization_fuel_limit
,
697 print_fuel_crate
: print_fuel_crate
,
698 print_fuel
: print_fuel
,
699 out_of_fuel
: Cell
::new(false),
705 /// Holds data on the current incremental compilation session, if there is one.
707 pub enum IncrCompSession
{
708 // This is the state the session will be in until the incr. comp. dir is
711 // This is the state during which the session directory is private and can
714 session_directory
: PathBuf
,
715 lock_file
: flock
::Lock
,
717 // This is the state after the session directory has been finalized. In this
718 // state, the contents of the directory must not be modified any more.
720 session_directory
: PathBuf
,
722 // This is an error state that is reached when some compilation error has
723 // occurred. It indicates that the contents of the session directory must
724 // not be used, since they might be invalid.
725 InvalidBecauseOfErrors
{
726 session_directory
: PathBuf
,
730 pub fn early_error(output
: config
::ErrorOutputType
, msg
: &str) -> ! {
731 let emitter
: Box
<Emitter
> = match output
{
732 config
::ErrorOutputType
::HumanReadable(color_config
) => {
733 Box
::new(EmitterWriter
::stderr(color_config
,
736 config
::ErrorOutputType
::Json
=> Box
::new(JsonEmitter
::basic()),
738 let handler
= errors
::Handler
::with_emitter(true, false, emitter
);
739 handler
.emit(&MultiSpan
::new(), msg
, errors
::Level
::Fatal
);
740 panic
!(errors
::FatalError
);
743 pub fn early_warn(output
: config
::ErrorOutputType
, msg
: &str) {
744 let emitter
: Box
<Emitter
> = match output
{
745 config
::ErrorOutputType
::HumanReadable(color_config
) => {
746 Box
::new(EmitterWriter
::stderr(color_config
,
749 config
::ErrorOutputType
::Json
=> Box
::new(JsonEmitter
::basic()),
751 let handler
= errors
::Handler
::with_emitter(true, false, emitter
);
752 handler
.emit(&MultiSpan
::new(), msg
, errors
::Level
::Warning
);
755 // Err(0) means compilation was stopped, but no errors were found.
756 // This would be better as a dedicated enum, but using try! is so convenient.
757 pub type CompileResult
= Result
<(), usize>;
759 pub fn compile_result_from_err_count(err_count
: usize) -> CompileResult
{
769 pub fn bug_fmt(file
: &'
static str, line
: u32, args
: fmt
::Arguments
) -> ! {
770 // this wrapper mostly exists so I don't have to write a fully
771 // qualified path of None::<Span> inside the bug!() macro defintion
772 opt_span_bug_fmt(file
, line
, None
::<Span
>, args
);
777 pub fn span_bug_fmt
<S
: Into
<MultiSpan
>>(file
: &'
static str,
780 args
: fmt
::Arguments
) -> ! {
781 opt_span_bug_fmt(file
, line
, Some(span
), args
);
784 fn opt_span_bug_fmt
<S
: Into
<MultiSpan
>>(file
: &'
static str,
787 args
: fmt
::Arguments
) -> ! {
788 tls
::with_opt(move |tcx
| {
789 let msg
= format
!("{}:{}: {}", file
, line
, args
);
791 (Some(tcx
), Some(span
)) => tcx
.sess
.diagnostic().span_bug(span
, &msg
),
792 (Some(tcx
), None
) => tcx
.sess
.diagnostic().bug(&msg
),
793 (None
, _
) => panic
!(msg
)