]> git.lizzy.rs Git - rust.git/blob - src/librustc/session/mod.rs
Rollup merge of #65809 - roblabla:eficall-abi, r=nagisa
[rust.git] / src / librustc / session / mod.rs
1 pub use self::code_stats::{DataTypeKind, SizeKind, FieldInfo, VariantInfo};
2 use self::code_stats::CodeStats;
3
4 use crate::dep_graph::cgu_reuse_tracker::CguReuseTracker;
5 use crate::hir::def_id::CrateNum;
6 use rustc_data_structures::fingerprint::Fingerprint;
7
8 use crate::lint;
9 use crate::lint::builtin::BuiltinLintDiagnostics;
10 use crate::session::config::{OutputType, PrintRequest, Sanitizer, SwitchWithOptPath};
11 use crate::session::search_paths::{PathKind, SearchPath};
12 use crate::util::nodemap::{FxHashMap, FxHashSet};
13 use crate::util::common::{duration_to_secs_str, ErrorReported};
14
15 use rustc_data_structures::base_n;
16 use rustc_data_structures::sync::{
17     self, Lrc, Lock, OneThread, Once, AtomicU64, AtomicUsize, Ordering,
18     Ordering::SeqCst,
19 };
20
21 use errors::{DiagnosticBuilder, DiagnosticId, Applicability};
22 use errors::emitter::{Emitter, EmitterWriter};
23 use errors::emitter::HumanReadableErrorType;
24 use errors::annotate_snippet_emitter_writer::{AnnotateSnippetEmitterWriter};
25 use syntax::ast::{self, NodeId};
26 use syntax::edition::Edition;
27 use syntax::expand::allocator::AllocatorKind;
28 use syntax::feature_gate::{self, AttributeType};
29 use syntax::json::JsonEmitter;
30 use syntax::source_map;
31 use syntax::sess::ParseSess;
32 use syntax::symbol::Symbol;
33 use syntax_pos::{MultiSpan, Span};
34 use crate::util::profiling::{SelfProfiler, SelfProfilerRef};
35
36 use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple};
37 use rustc_data_structures::flock;
38 use rustc_data_structures::jobserver;
39 use ::jobserver::Client;
40
41 use std;
42 use std::cell::{self, Cell, RefCell};
43 use std::env;
44 use std::fmt;
45 use std::io::Write;
46 use std::path::PathBuf;
47 use std::time::Duration;
48 use std::sync::Arc;
49
50 mod code_stats;
51 pub mod config;
52 pub mod filesearch;
53 pub mod search_paths;
54
55 pub struct OptimizationFuel {
56     /// If `-zfuel=crate=n` is specified, initially set to `n`, otherwise `0`.
57     remaining: u64,
58     /// We're rejecting all further optimizations.
59     out_of_fuel: bool,
60 }
61
62 /// Represents the data associated with a compilation
63 /// session for a single crate.
64 pub struct Session {
65     pub target: config::Config,
66     pub host: Target,
67     pub opts: config::Options,
68     pub host_tlib_path: SearchPath,
69     /// `None` if the host and target are the same.
70     pub target_tlib_path: Option<SearchPath>,
71     pub parse_sess: ParseSess,
72     pub sysroot: PathBuf,
73     /// The name of the root source file of the crate, in the local file system.
74     /// `None` means that there is no source file.
75     pub local_crate_source_file: Option<PathBuf>,
76     /// The directory the compiler has been executed in plus a flag indicating
77     /// if the value stored here has been affected by path remapping.
78     pub working_dir: (PathBuf, bool),
79
80     /// This is intended to be used from a single thread.
81     ///
82     /// FIXME: there was a previous comment about this not being thread safe,
83     /// but it's not clear how or why that's the case. The LintBuffer itself is certainly thread
84     /// safe at least from a "Rust safety" standpoint.
85     pub buffered_lints: Lock<Option<lint::LintBuffer>>,
86
87     /// Set of `(DiagnosticId, Option<Span>, message)` tuples tracking
88     /// (sub)diagnostics that have been set once, but should not be set again,
89     /// in order to avoid redundantly verbose output (Issue #24690, #44953).
90     pub one_time_diagnostics: Lock<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
91     pub plugin_llvm_passes: OneThread<RefCell<Vec<String>>>,
92     pub plugin_attributes: Lock<Vec<(Symbol, AttributeType)>>,
93     pub crate_types: Once<Vec<config::CrateType>>,
94     /// The `crate_disambiguator` is constructed out of all the `-C metadata`
95     /// arguments passed to the compiler. Its value together with the crate-name
96     /// forms a unique global identifier for the crate. It is used to allow
97     /// multiple crates with the same name to coexist. See the
98     /// `rustc_codegen_llvm::back::symbol_names` module for more information.
99     pub crate_disambiguator: Once<CrateDisambiguator>,
100
101     features: Once<feature_gate::Features>,
102
103     /// The maximum recursion limit for potentially infinitely recursive
104     /// operations such as auto-dereference and monomorphization.
105     pub recursion_limit: Once<usize>,
106
107     /// The maximum length of types during monomorphization.
108     pub type_length_limit: Once<usize>,
109
110     /// The maximum number of stackframes allowed in const eval.
111     pub const_eval_stack_frame_limit: usize,
112
113     /// The `metadata::creader` module may inject an allocator/`panic_runtime`
114     /// dependency if it didn't already find one, and this tracks what was
115     /// injected.
116     pub allocator_kind: Once<Option<AllocatorKind>>,
117     pub injected_panic_runtime: Once<Option<CrateNum>>,
118
119     /// Map from imported macro spans (which consist of
120     /// the localized span for the macro body) to the
121     /// macro name and definition span in the source crate.
122     pub imported_macro_spans: OneThread<RefCell<FxHashMap<Span, (String, Span)>>>,
123
124     incr_comp_session: OneThread<RefCell<IncrCompSession>>,
125     /// Used for incremental compilation tests. Will only be populated if
126     /// `-Zquery-dep-graph` is specified.
127     pub cgu_reuse_tracker: CguReuseTracker,
128
129     /// Used by `-Z self-profile`.
130     pub prof: SelfProfilerRef,
131
132     /// Some measurements that are being gathered during compilation.
133     pub perf_stats: PerfStats,
134
135     /// Data about code being compiled, gathered during compilation.
136     pub code_stats: Lock<CodeStats>,
137
138     next_node_id: OneThread<Cell<ast::NodeId>>,
139
140     /// If `-zfuel=crate=n` is specified, `Some(crate)`.
141     optimization_fuel_crate: Option<String>,
142
143     /// Tracks fuel info if `-zfuel=crate=n` is specified.
144     optimization_fuel: Lock<OptimizationFuel>,
145
146     // The next two are public because the driver needs to read them.
147     /// If `-zprint-fuel=crate`, `Some(crate)`.
148     pub print_fuel_crate: Option<String>,
149     /// Always set to zero and incremented so that we can print fuel expended by a crate.
150     pub print_fuel: AtomicU64,
151
152     /// Loaded up early on in the initialization of this `Session` to avoid
153     /// false positives about a job server in our environment.
154     pub jobserver: Client,
155
156     /// Metadata about the allocators for the current crate being compiled.
157     pub has_global_allocator: Once<bool>,
158
159     /// Metadata about the panic handlers for the current crate being compiled.
160     pub has_panic_handler: Once<bool>,
161
162     /// Cap lint level specified by a driver specifically.
163     pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
164
165     /// `Span`s of trait methods that weren't found to avoid emitting object safety errors
166     pub trait_methods_not_found: Lock<FxHashSet<Span>>,
167
168     /// Mapping from ident span to path span for paths that don't exist as written, but that
169     /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
170     pub confused_type_with_std_module: Lock<FxHashMap<Span, Span>>,
171 }
172
173 pub struct PerfStats {
174     /// The accumulated time spent on computing symbol hashes.
175     pub symbol_hash_time: Lock<Duration>,
176     /// The accumulated time spent decoding def path tables from metadata.
177     pub decode_def_path_tables_time: Lock<Duration>,
178     /// Total number of values canonicalized queries constructed.
179     pub queries_canonicalized: AtomicUsize,
180     /// Number of times this query is invoked.
181     pub normalize_ty_after_erasing_regions: AtomicUsize,
182     /// Number of times this query is invoked.
183     pub normalize_projection_ty: AtomicUsize,
184 }
185
186 /// Enum to support dispatch of one-time diagnostics (in `Session.diag_once`).
187 enum DiagnosticBuilderMethod {
188     Note,
189     SpanNote,
190     SpanSuggestion(String), // suggestion
191                             // Add more variants as needed to support one-time diagnostics.
192 }
193
194 /// Diagnostic message ID, used by `Session.one_time_diagnostics` to avoid
195 /// emitting the same message more than once.
196 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
197 pub enum DiagnosticMessageId {
198     ErrorId(u16), // EXXXX error code as integer
199     LintId(lint::LintId),
200     StabilityId(u32), // issue number
201 }
202
203 impl From<&'static lint::Lint> for DiagnosticMessageId {
204     fn from(lint: &'static lint::Lint) -> Self {
205         DiagnosticMessageId::LintId(lint::LintId::of(lint))
206     }
207 }
208
209 impl Session {
210     pub fn local_crate_disambiguator(&self) -> CrateDisambiguator {
211         *self.crate_disambiguator.get()
212     }
213
214     pub fn struct_span_warn<S: Into<MultiSpan>>(
215         &self,
216         sp: S,
217         msg: &str,
218     ) -> DiagnosticBuilder<'_> {
219         self.diagnostic().struct_span_warn(sp, msg)
220     }
221     pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
222         &self,
223         sp: S,
224         msg: &str,
225         code: DiagnosticId,
226     ) -> DiagnosticBuilder<'_> {
227         self.diagnostic().struct_span_warn_with_code(sp, msg, code)
228     }
229     pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
230         self.diagnostic().struct_warn(msg)
231     }
232     pub fn struct_span_err<S: Into<MultiSpan>>(
233         &self,
234         sp: S,
235         msg: &str,
236     ) -> DiagnosticBuilder<'_> {
237         self.diagnostic().struct_span_err(sp, msg)
238     }
239     pub fn struct_span_err_with_code<S: Into<MultiSpan>>(
240         &self,
241         sp: S,
242         msg: &str,
243         code: DiagnosticId,
244     ) -> DiagnosticBuilder<'_> {
245         self.diagnostic().struct_span_err_with_code(sp, msg, code)
246     }
247     // FIXME: This method should be removed (every error should have an associated error code).
248     pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> {
249         self.diagnostic().struct_err(msg)
250     }
251     pub fn struct_err_with_code(
252         &self,
253         msg: &str,
254         code: DiagnosticId,
255     ) -> DiagnosticBuilder<'_> {
256         self.diagnostic().struct_err_with_code(msg, code)
257     }
258     pub fn struct_span_fatal<S: Into<MultiSpan>>(
259         &self,
260         sp: S,
261         msg: &str,
262     ) -> DiagnosticBuilder<'_> {
263         self.diagnostic().struct_span_fatal(sp, msg)
264     }
265     pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
266         &self,
267         sp: S,
268         msg: &str,
269         code: DiagnosticId,
270     ) -> DiagnosticBuilder<'_> {
271         self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
272     }
273     pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_> {
274         self.diagnostic().struct_fatal(msg)
275     }
276
277     pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
278         self.diagnostic().span_fatal(sp, msg).raise()
279     }
280     pub fn span_fatal_with_code<S: Into<MultiSpan>>(
281         &self,
282         sp: S,
283         msg: &str,
284         code: DiagnosticId,
285     ) -> ! {
286         self.diagnostic()
287             .span_fatal_with_code(sp, msg, code)
288             .raise()
289     }
290     pub fn fatal(&self, msg: &str) -> ! {
291         self.diagnostic().fatal(msg).raise()
292     }
293     pub fn span_err_or_warn<S: Into<MultiSpan>>(&self, is_warning: bool, sp: S, msg: &str) {
294         if is_warning {
295             self.span_warn(sp, msg);
296         } else {
297             self.span_err(sp, msg);
298         }
299     }
300     pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
301         self.diagnostic().span_err(sp, msg)
302     }
303     pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
304         self.diagnostic().span_err_with_code(sp, &msg, code)
305     }
306     pub fn err(&self, msg: &str) {
307         self.diagnostic().err(msg)
308     }
309     pub fn err_count(&self) -> usize {
310         self.diagnostic().err_count()
311     }
312     pub fn has_errors(&self) -> bool {
313         self.diagnostic().has_errors()
314     }
315     pub fn abort_if_errors(&self) {
316         self.diagnostic().abort_if_errors();
317     }
318     pub fn compile_status(&self) -> Result<(), ErrorReported> {
319         if self.has_errors() {
320             self.diagnostic().emit_stashed_diagnostics();
321             Err(ErrorReported)
322         } else {
323             Ok(())
324         }
325     }
326     // FIXME(matthewjasper) Remove this method, it should never be needed.
327     pub fn track_errors<F, T>(&self, f: F) -> Result<T, ErrorReported>
328     where
329         F: FnOnce() -> T,
330     {
331         let old_count = self.err_count();
332         let result = f();
333         let errors = self.err_count() - old_count;
334         if errors == 0 {
335             Ok(result)
336         } else {
337             Err(ErrorReported)
338         }
339     }
340     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
341         self.diagnostic().span_warn(sp, msg)
342     }
343     pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
344         self.diagnostic().span_warn_with_code(sp, msg, code)
345     }
346     pub fn warn(&self, msg: &str) {
347         self.diagnostic().warn(msg)
348     }
349     pub fn opt_span_warn<S: Into<MultiSpan>>(&self, opt_sp: Option<S>, msg: &str) {
350         match opt_sp {
351             Some(sp) => self.span_warn(sp, msg),
352             None => self.warn(msg),
353         }
354     }
355     /// Delay a span_bug() call until abort_if_errors()
356     pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
357         self.diagnostic().delay_span_bug(sp, msg)
358     }
359     pub fn note_without_error(&self, msg: &str) {
360         self.diagnostic().note_without_error(msg)
361     }
362     pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
363         self.diagnostic().span_note_without_error(sp, msg)
364     }
365
366     pub fn buffer_lint<S: Into<MultiSpan>>(
367         &self,
368         lint: &'static lint::Lint,
369         id: ast::NodeId,
370         sp: S,
371         msg: &str,
372     ) {
373         match *self.buffered_lints.borrow_mut() {
374             Some(ref mut buffer) => {
375                 buffer.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal)
376             }
377             None => bug!("can't buffer lints after HIR lowering"),
378         }
379     }
380
381     pub fn buffer_lint_with_diagnostic<S: Into<MultiSpan>>(
382         &self,
383         lint: &'static lint::Lint,
384         id: ast::NodeId,
385         sp: S,
386         msg: &str,
387         diagnostic: BuiltinLintDiagnostics,
388     ) {
389         match *self.buffered_lints.borrow_mut() {
390             Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(), msg, diagnostic),
391             None => bug!("can't buffer lints after HIR lowering"),
392         }
393     }
394
395     pub fn reserve_node_ids(&self, count: usize) -> ast::NodeId {
396         let id = self.next_node_id.get();
397
398         match id.as_usize().checked_add(count) {
399             Some(next) => {
400                 self.next_node_id.set(ast::NodeId::from_usize(next));
401             }
402             None => bug!("input too large; ran out of node-IDs!"),
403         }
404
405         id
406     }
407     pub fn next_node_id(&self) -> NodeId {
408         self.reserve_node_ids(1)
409     }
410     pub fn diagnostic(&self) -> &errors::Handler {
411         &self.parse_sess.span_diagnostic
412     }
413
414     /// Analogous to calling methods on the given `DiagnosticBuilder`, but
415     /// deduplicates on lint ID, span (if any), and message for this `Session`
416     fn diag_once<'a, 'b>(
417         &'a self,
418         diag_builder: &'b mut DiagnosticBuilder<'a>,
419         method: DiagnosticBuilderMethod,
420         msg_id: DiagnosticMessageId,
421         message: &str,
422         span_maybe: Option<Span>,
423     ) {
424         let id_span_message = (msg_id, span_maybe, message.to_owned());
425         let fresh = self.one_time_diagnostics
426             .borrow_mut()
427             .insert(id_span_message);
428         if fresh {
429             match method {
430                 DiagnosticBuilderMethod::Note => {
431                     diag_builder.note(message);
432                 }
433                 DiagnosticBuilderMethod::SpanNote => {
434                     let span = span_maybe.expect("`span_note` needs a span");
435                     diag_builder.span_note(span, message);
436                 }
437                 DiagnosticBuilderMethod::SpanSuggestion(suggestion) => {
438                     let span = span_maybe.expect("`span_suggestion_*` needs a span");
439                     diag_builder.span_suggestion(
440                         span,
441                         message,
442                         suggestion,
443                         Applicability::Unspecified,
444                     );
445                 }
446             }
447         }
448     }
449
450     pub fn diag_span_note_once<'a, 'b>(
451         &'a self,
452         diag_builder: &'b mut DiagnosticBuilder<'a>,
453         msg_id: DiagnosticMessageId,
454         span: Span,
455         message: &str,
456     ) {
457         self.diag_once(
458             diag_builder,
459             DiagnosticBuilderMethod::SpanNote,
460             msg_id,
461             message,
462             Some(span),
463         );
464     }
465
466     pub fn diag_note_once<'a, 'b>(
467         &'a self,
468         diag_builder: &'b mut DiagnosticBuilder<'a>,
469         msg_id: DiagnosticMessageId,
470         message: &str,
471     ) {
472         self.diag_once(
473             diag_builder,
474             DiagnosticBuilderMethod::Note,
475             msg_id,
476             message,
477             None,
478         );
479     }
480
481     pub fn diag_span_suggestion_once<'a, 'b>(
482         &'a self,
483         diag_builder: &'b mut DiagnosticBuilder<'a>,
484         msg_id: DiagnosticMessageId,
485         span: Span,
486         message: &str,
487         suggestion: String,
488     ) {
489         self.diag_once(
490             diag_builder,
491             DiagnosticBuilderMethod::SpanSuggestion(suggestion),
492             msg_id,
493             message,
494             Some(span),
495         );
496     }
497
498     pub fn source_map(&self) -> &source_map::SourceMap {
499         self.parse_sess.source_map()
500     }
501     pub fn verbose(&self) -> bool {
502         self.opts.debugging_opts.verbose
503     }
504     pub fn time_passes(&self) -> bool {
505         self.opts.debugging_opts.time_passes || self.opts.debugging_opts.time
506     }
507     pub fn time_extended(&self) -> bool {
508         self.opts.debugging_opts.time_passes
509     }
510     pub fn instrument_mcount(&self) -> bool {
511         self.opts.debugging_opts.instrument_mcount
512     }
513     pub fn time_llvm_passes(&self) -> bool {
514         self.opts.debugging_opts.time_llvm_passes
515     }
516     pub fn meta_stats(&self) -> bool {
517         self.opts.debugging_opts.meta_stats
518     }
519     pub fn asm_comments(&self) -> bool {
520         self.opts.debugging_opts.asm_comments
521     }
522     pub fn verify_llvm_ir(&self) -> bool {
523         self.opts.debugging_opts.verify_llvm_ir
524             || cfg!(always_verify_llvm_ir)
525     }
526     pub fn borrowck_stats(&self) -> bool {
527         self.opts.debugging_opts.borrowck_stats
528     }
529     pub fn print_llvm_passes(&self) -> bool {
530         self.opts.debugging_opts.print_llvm_passes
531     }
532     pub fn binary_dep_depinfo(&self) -> bool {
533         self.opts.debugging_opts.binary_dep_depinfo
534     }
535
536     /// Gets the features enabled for the current compilation session.
537     /// DO NOT USE THIS METHOD if there is a TyCtxt available, as it circumvents
538     /// dependency tracking. Use tcx.features() instead.
539     #[inline]
540     pub fn features_untracked(&self) -> &feature_gate::Features {
541         self.features.get()
542     }
543
544     pub fn init_features(&self, features: feature_gate::Features) {
545         self.features.set(features);
546     }
547
548     /// Calculates the flavor of LTO to use for this compilation.
549     pub fn lto(&self) -> config::Lto {
550         // If our target has codegen requirements ignore the command line
551         if self.target.target.options.requires_lto {
552             return config::Lto::Fat;
553         }
554
555         // If the user specified something, return that. If they only said `-C
556         // lto` and we've for whatever reason forced off ThinLTO via the CLI,
557         // then ensure we can't use a ThinLTO.
558         match self.opts.cg.lto {
559             config::LtoCli::Unspecified => {
560                 // The compiler was invoked without the `-Clto` flag. Fall
561                 // through to the default handling
562             }
563             config::LtoCli::No => {
564                 // The user explicitly opted out of any kind of LTO
565                 return config::Lto::No;
566             }
567             config::LtoCli::Yes |
568             config::LtoCli::Fat |
569             config::LtoCli::NoParam => {
570                 // All of these mean fat LTO
571                 return config::Lto::Fat;
572             }
573             config::LtoCli::Thin => {
574                 return if self.opts.cli_forced_thinlto_off {
575                     config::Lto::Fat
576                 } else {
577                     config::Lto::Thin
578                 };
579             }
580         }
581
582         // Ok at this point the target doesn't require anything and the user
583         // hasn't asked for anything. Our next decision is whether or not
584         // we enable "auto" ThinLTO where we use multiple codegen units and
585         // then do ThinLTO over those codegen units. The logic below will
586         // either return `No` or `ThinLocal`.
587
588         // If processing command line options determined that we're incompatible
589         // with ThinLTO (e.g., `-C lto --emit llvm-ir`) then return that option.
590         if self.opts.cli_forced_thinlto_off {
591             return config::Lto::No;
592         }
593
594         // If `-Z thinlto` specified process that, but note that this is mostly
595         // a deprecated option now that `-C lto=thin` exists.
596         if let Some(enabled) = self.opts.debugging_opts.thinlto {
597             if enabled {
598                 return config::Lto::ThinLocal;
599             } else {
600                 return config::Lto::No;
601             }
602         }
603
604         // If there's only one codegen unit and LTO isn't enabled then there's
605         // no need for ThinLTO so just return false.
606         if self.codegen_units() == 1 {
607             return config::Lto::No;
608         }
609
610         // Now we're in "defaults" territory. By default we enable ThinLTO for
611         // optimized compiles (anything greater than O0).
612         match self.opts.optimize {
613             config::OptLevel::No => config::Lto::No,
614             _ => config::Lto::ThinLocal,
615         }
616     }
617
618     /// Returns the panic strategy for this compile session. If the user explicitly selected one
619     /// using '-C panic', use that, otherwise use the panic strategy defined by the target.
620     pub fn panic_strategy(&self) -> PanicStrategy {
621         self.opts
622             .cg
623             .panic
624             .unwrap_or(self.target.target.options.panic_strategy)
625     }
626     pub fn fewer_names(&self) -> bool {
627         let more_names = self.opts
628             .output_types
629             .contains_key(&OutputType::LlvmAssembly)
630             || self.opts.output_types.contains_key(&OutputType::Bitcode);
631
632         // Address sanitizer and memory sanitizer use alloca name when reporting an issue.
633         let more_names = match self.opts.debugging_opts.sanitizer {
634             Some(Sanitizer::Address) => true,
635             Some(Sanitizer::Memory) => true,
636             _ => more_names,
637         };
638
639         self.opts.debugging_opts.fewer_names || !more_names
640     }
641
642     pub fn no_landing_pads(&self) -> bool {
643         self.opts.debugging_opts.no_landing_pads || self.panic_strategy() == PanicStrategy::Abort
644     }
645     pub fn unstable_options(&self) -> bool {
646         self.opts.debugging_opts.unstable_options
647     }
648     pub fn overflow_checks(&self) -> bool {
649         self.opts
650             .cg
651             .overflow_checks
652             .or(self.opts.debugging_opts.force_overflow_checks)
653             .unwrap_or(self.opts.debug_assertions)
654     }
655
656     pub fn crt_static(&self) -> bool {
657         // If the target does not opt in to crt-static support, use its default.
658         if self.target.target.options.crt_static_respected {
659             self.crt_static_feature()
660         } else {
661             self.target.target.options.crt_static_default
662         }
663     }
664
665     pub fn crt_static_feature(&self) -> bool {
666         let requested_features = self.opts.cg.target_feature.split(',');
667         let found_negative = requested_features.clone().any(|r| r == "-crt-static");
668         let found_positive = requested_features.clone().any(|r| r == "+crt-static");
669
670         // If the target we're compiling for requests a static crt by default,
671         // then see if the `-crt-static` feature was passed to disable that.
672         // Otherwise if we don't have a static crt by default then see if the
673         // `+crt-static` feature was passed.
674         if self.target.target.options.crt_static_default {
675             !found_negative
676         } else {
677             found_positive
678         }
679     }
680
681     pub fn must_not_eliminate_frame_pointers(&self) -> bool {
682         // "mcount" function relies on stack pointer.
683         // See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
684         if self.instrument_mcount() {
685             true
686         } else if let Some(x) = self.opts.cg.force_frame_pointers {
687             x
688         } else {
689             !self.target.target.options.eliminate_frame_pointer
690         }
691     }
692
693     /// Returns the symbol name for the registrar function,
694     /// given the crate `Svh` and the function `DefIndex`.
695     pub fn generate_plugin_registrar_symbol(&self, disambiguator: CrateDisambiguator) -> String {
696         format!(
697             "__rustc_plugin_registrar_{}__",
698             disambiguator.to_fingerprint().to_hex()
699         )
700     }
701
702     pub fn generate_proc_macro_decls_symbol(&self, disambiguator: CrateDisambiguator) -> String {
703         format!(
704             "__rustc_proc_macro_decls_{}__",
705             disambiguator.to_fingerprint().to_hex()
706         )
707     }
708
709     pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
710         filesearch::FileSearch::new(
711             &self.sysroot,
712             self.opts.target_triple.triple(),
713             &self.opts.search_paths,
714             // `target_tlib_path == None` means it's the same as `host_tlib_path`.
715             self.target_tlib_path.as_ref().unwrap_or(&self.host_tlib_path),
716             kind,
717         )
718     }
719     pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
720         filesearch::FileSearch::new(
721             &self.sysroot,
722             config::host_triple(),
723             &self.opts.search_paths,
724             &self.host_tlib_path,
725             kind,
726         )
727     }
728
729     pub fn set_incr_session_load_dep_graph(&self, load: bool) {
730         let mut incr_comp_session = self.incr_comp_session.borrow_mut();
731
732         if let IncrCompSession::Active { ref mut load_dep_graph, .. } = *incr_comp_session {
733             *load_dep_graph = load;
734         }
735     }
736
737     pub fn incr_session_load_dep_graph(&self) -> bool {
738         let incr_comp_session = self.incr_comp_session.borrow();
739         match *incr_comp_session {
740             IncrCompSession::Active { load_dep_graph, .. } => load_dep_graph,
741             _ => false,
742         }
743     }
744
745     pub fn init_incr_comp_session(
746         &self,
747         session_dir: PathBuf,
748         lock_file: flock::Lock,
749         load_dep_graph: bool,
750     ) {
751         let mut incr_comp_session = self.incr_comp_session.borrow_mut();
752
753         if let IncrCompSession::NotInitialized = *incr_comp_session {
754         } else {
755             bug!(
756                 "Trying to initialize IncrCompSession `{:?}`",
757                 *incr_comp_session
758             )
759         }
760
761         *incr_comp_session = IncrCompSession::Active {
762             session_directory: session_dir,
763             lock_file,
764             load_dep_graph,
765         };
766     }
767
768     pub fn finalize_incr_comp_session(&self, new_directory_path: PathBuf) {
769         let mut incr_comp_session = self.incr_comp_session.borrow_mut();
770
771         if let IncrCompSession::Active { .. } = *incr_comp_session {
772         } else {
773             bug!(
774                 "trying to finalize `IncrCompSession` `{:?}`",
775                 *incr_comp_session
776             );
777         }
778
779         // Note: this will also drop the lock file, thus unlocking the directory.
780         *incr_comp_session = IncrCompSession::Finalized {
781             session_directory: new_directory_path,
782         };
783     }
784
785     pub fn mark_incr_comp_session_as_invalid(&self) {
786         let mut incr_comp_session = self.incr_comp_session.borrow_mut();
787
788         let session_directory = match *incr_comp_session {
789             IncrCompSession::Active {
790                 ref session_directory,
791                 ..
792             } => session_directory.clone(),
793             IncrCompSession::InvalidBecauseOfErrors { .. } => return,
794             _ => bug!(
795                 "trying to invalidate `IncrCompSession` `{:?}`",
796                 *incr_comp_session
797             ),
798         };
799
800         // Note: this will also drop the lock file, thus unlocking the directory.
801         *incr_comp_session = IncrCompSession::InvalidBecauseOfErrors {
802             session_directory,
803         };
804     }
805
806     pub fn incr_comp_session_dir(&self) -> cell::Ref<'_, PathBuf> {
807         let incr_comp_session = self.incr_comp_session.borrow();
808         cell::Ref::map(
809             incr_comp_session,
810             |incr_comp_session| match *incr_comp_session {
811                 IncrCompSession::NotInitialized => bug!(
812                     "trying to get session directory from `IncrCompSession`: {:?}",
813                     *incr_comp_session,
814                 ),
815                 IncrCompSession::Active {
816                     ref session_directory,
817                     ..
818                 }
819                 | IncrCompSession::Finalized {
820                     ref session_directory,
821                 }
822                 | IncrCompSession::InvalidBecauseOfErrors {
823                     ref session_directory,
824                 } => session_directory,
825             },
826         )
827     }
828
829     pub fn incr_comp_session_dir_opt(&self) -> Option<cell::Ref<'_, PathBuf>> {
830         if self.opts.incremental.is_some() {
831             Some(self.incr_comp_session_dir())
832         } else {
833             None
834         }
835     }
836
837     pub fn print_perf_stats(&self) {
838         println!(
839             "Total time spent computing symbol hashes:      {}",
840             duration_to_secs_str(*self.perf_stats.symbol_hash_time.lock())
841         );
842         println!(
843             "Total time spent decoding DefPath tables:      {}",
844             duration_to_secs_str(*self.perf_stats.decode_def_path_tables_time.lock())
845         );
846         println!("Total queries canonicalized:                   {}",
847                  self.perf_stats.queries_canonicalized.load(Ordering::Relaxed));
848         println!("normalize_ty_after_erasing_regions:            {}",
849                  self.perf_stats.normalize_ty_after_erasing_regions.load(Ordering::Relaxed));
850         println!("normalize_projection_ty:                       {}",
851                  self.perf_stats.normalize_projection_ty.load(Ordering::Relaxed));
852     }
853
854     /// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
855     /// This expends fuel if applicable, and records fuel if applicable.
856     pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
857         let mut ret = true;
858         if let Some(ref c) = self.optimization_fuel_crate {
859             if c == crate_name {
860                 assert_eq!(self.threads(), 1);
861                 let mut fuel = self.optimization_fuel.lock();
862                 ret = fuel.remaining != 0;
863                 if fuel.remaining == 0 && !fuel.out_of_fuel {
864                     eprintln!("optimization-fuel-exhausted: {}", msg());
865                     fuel.out_of_fuel = true;
866                 } else if fuel.remaining > 0 {
867                     fuel.remaining -= 1;
868                 }
869             }
870         }
871         if let Some(ref c) = self.print_fuel_crate {
872             if c == crate_name {
873                 assert_eq!(self.threads(), 1);
874                 self.print_fuel.fetch_add(1, SeqCst);
875             }
876         }
877         ret
878     }
879
880     /// Returns the number of query threads that should be used for this
881     /// compilation
882     pub fn threads(&self) -> usize {
883         self.opts.debugging_opts.threads
884     }
885
886     /// Returns the number of codegen units that should be used for this
887     /// compilation
888     pub fn codegen_units(&self) -> usize {
889         if let Some(n) = self.opts.cli_forced_codegen_units {
890             return n;
891         }
892         if let Some(n) = self.target.target.options.default_codegen_units {
893             return n as usize;
894         }
895
896         // Why is 16 codegen units the default all the time?
897         //
898         // The main reason for enabling multiple codegen units by default is to
899         // leverage the ability for the codegen backend to do codegen and
900         // optimization in parallel. This allows us, especially for large crates, to
901         // make good use of all available resources on the machine once we've
902         // hit that stage of compilation. Large crates especially then often
903         // take a long time in codegen/optimization and this helps us amortize that
904         // cost.
905         //
906         // Note that a high number here doesn't mean that we'll be spawning a
907         // large number of threads in parallel. The backend of rustc contains
908         // global rate limiting through the `jobserver` crate so we'll never
909         // overload the system with too much work, but rather we'll only be
910         // optimizing when we're otherwise cooperating with other instances of
911         // rustc.
912         //
913         // Rather a high number here means that we should be able to keep a lot
914         // of idle cpus busy. By ensuring that no codegen unit takes *too* long
915         // to build we'll be guaranteed that all cpus will finish pretty closely
916         // to one another and we should make relatively optimal use of system
917         // resources
918         //
919         // Note that the main cost of codegen units is that it prevents LLVM
920         // from inlining across codegen units. Users in general don't have a lot
921         // of control over how codegen units are split up so it's our job in the
922         // compiler to ensure that undue performance isn't lost when using
923         // codegen units (aka we can't require everyone to slap `#[inline]` on
924         // everything).
925         //
926         // If we're compiling at `-O0` then the number doesn't really matter too
927         // much because performance doesn't matter and inlining is ok to lose.
928         // In debug mode we just want to try to guarantee that no cpu is stuck
929         // doing work that could otherwise be farmed to others.
930         //
931         // In release mode, however (O1 and above) performance does indeed
932         // matter! To recover the loss in performance due to inlining we'll be
933         // enabling ThinLTO by default (the function for which is just below).
934         // This will ensure that we recover any inlining wins we otherwise lost
935         // through codegen unit partitioning.
936         //
937         // ---
938         //
939         // Ok that's a lot of words but the basic tl;dr; is that we want a high
940         // number here -- but not too high. Additionally we're "safe" to have it
941         // always at the same number at all optimization levels.
942         //
943         // As a result 16 was chosen here! Mostly because it was a power of 2
944         // and most benchmarks agreed it was roughly a local optimum. Not very
945         // scientific.
946         16
947     }
948
949     pub fn teach(&self, code: &DiagnosticId) -> bool {
950         self.opts.debugging_opts.teach && self.diagnostic().must_teach(code)
951     }
952
953     pub fn rust_2015(&self) -> bool {
954         self.opts.edition == Edition::Edition2015
955     }
956
957     /// Are we allowed to use features from the Rust 2018 edition?
958     pub fn rust_2018(&self) -> bool {
959         self.opts.edition >= Edition::Edition2018
960     }
961
962     pub fn edition(&self) -> Edition {
963         self.opts.edition
964     }
965
966     /// Returns `true` if we cannot skip the PLT for shared library calls.
967     pub fn needs_plt(&self) -> bool {
968         // Check if the current target usually needs PLT to be enabled.
969         // The user can use the command line flag to override it.
970         let needs_plt = self.target.target.options.needs_plt;
971
972         let dbg_opts = &self.opts.debugging_opts;
973
974         let relro_level = dbg_opts.relro_level
975             .unwrap_or(self.target.target.options.relro_level);
976
977         // Only enable this optimization by default if full relro is also enabled.
978         // In this case, lazy binding was already unavailable, so nothing is lost.
979         // This also ensures `-Wl,-z,now` is supported by the linker.
980         let full_relro = RelroLevel::Full == relro_level;
981
982         // If user didn't explicitly forced us to use / skip the PLT,
983         // then try to skip it where possible.
984         dbg_opts.plt.unwrap_or(needs_plt || !full_relro)
985     }
986 }
987
988 pub fn build_session(
989     sopts: config::Options,
990     local_crate_source_file: Option<PathBuf>,
991     registry: errors::registry::Registry,
992 ) -> Session {
993     let file_path_mapping = sopts.file_path_mapping();
994
995     build_session_with_source_map(
996         sopts,
997         local_crate_source_file,
998         registry,
999         Lrc::new(source_map::SourceMap::new(file_path_mapping)),
1000         DiagnosticOutput::Default,
1001         Default::default(),
1002     )
1003 }
1004
1005 fn default_emitter(
1006     sopts: &config::Options,
1007     registry: errors::registry::Registry,
1008     source_map: &Lrc<source_map::SourceMap>,
1009     emitter_dest: Option<Box<dyn Write + Send>>,
1010 ) -> Box<dyn Emitter + sync::Send> {
1011     let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
1012     match (sopts.error_format, emitter_dest) {
1013         (config::ErrorOutputType::HumanReadable(kind), dst) => {
1014             let (short, color_config) = kind.unzip();
1015
1016             if let HumanReadableErrorType::AnnotateSnippet(_) = kind {
1017                 let emitter = AnnotateSnippetEmitterWriter::new(
1018                     Some(source_map.clone()),
1019                     short,
1020                     external_macro_backtrace,
1021                 );
1022                 Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing))
1023             } else {
1024                 let emitter = match dst {
1025                     None => EmitterWriter::stderr(
1026                         color_config,
1027                         Some(source_map.clone()),
1028                         short,
1029                         sopts.debugging_opts.teach,
1030                         sopts.debugging_opts.terminal_width,
1031                         external_macro_backtrace,
1032                     ),
1033                     Some(dst) => EmitterWriter::new(
1034                         dst,
1035                         Some(source_map.clone()),
1036                         short,
1037                         false, // no teach messages when writing to a buffer
1038                         false, // no colors when writing to a buffer
1039                         None,  // no terminal width
1040                         external_macro_backtrace,
1041                     ),
1042                 };
1043                 Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing))
1044             }
1045         },
1046         (config::ErrorOutputType::Json { pretty, json_rendered }, None) => Box::new(
1047             JsonEmitter::stderr(
1048                 Some(registry),
1049                 source_map.clone(),
1050                 pretty,
1051                 json_rendered,
1052                 external_macro_backtrace,
1053             ).ui_testing(sopts.debugging_opts.ui_testing),
1054         ),
1055         (config::ErrorOutputType::Json { pretty, json_rendered }, Some(dst)) => Box::new(
1056             JsonEmitter::new(
1057                 dst,
1058                 Some(registry),
1059                 source_map.clone(),
1060                 pretty,
1061                 json_rendered,
1062                 external_macro_backtrace,
1063             ).ui_testing(sopts.debugging_opts.ui_testing),
1064         ),
1065     }
1066 }
1067
1068 pub enum DiagnosticOutput {
1069     Default,
1070     Raw(Box<dyn Write + Send>)
1071 }
1072
1073 pub fn build_session_with_source_map(
1074     sopts: config::Options,
1075     local_crate_source_file: Option<PathBuf>,
1076     registry: errors::registry::Registry,
1077     source_map: Lrc<source_map::SourceMap>,
1078     diagnostics_output: DiagnosticOutput,
1079     lint_caps: FxHashMap<lint::LintId, lint::Level>,
1080 ) -> Session {
1081     // FIXME: This is not general enough to make the warning lint completely override
1082     // normal diagnostic warnings, since the warning lint can also be denied and changed
1083     // later via the source code.
1084     let warnings_allow = sopts
1085         .lint_opts
1086         .iter()
1087         .filter(|&&(ref key, _)| *key == "warnings")
1088         .map(|&(_, ref level)| *level == lint::Allow)
1089         .last()
1090         .unwrap_or(false);
1091     let cap_lints_allow = sopts.lint_cap.map_or(false, |cap| cap == lint::Allow);
1092
1093     let can_emit_warnings = !(warnings_allow || cap_lints_allow);
1094
1095     let treat_err_as_bug = sopts.debugging_opts.treat_err_as_bug;
1096     let dont_buffer_diagnostics = sopts.debugging_opts.dont_buffer_diagnostics;
1097     let report_delayed_bugs = sopts.debugging_opts.report_delayed_bugs;
1098
1099     let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
1100
1101     let emitter = match diagnostics_output {
1102         DiagnosticOutput::Default => default_emitter(&sopts, registry, &source_map, None),
1103         DiagnosticOutput::Raw(write) => {
1104             default_emitter(&sopts, registry, &source_map, Some(write))
1105         }
1106     };
1107
1108     let diagnostic_handler = errors::Handler::with_emitter_and_flags(
1109         emitter,
1110         errors::HandlerFlags {
1111             can_emit_warnings,
1112             treat_err_as_bug,
1113             report_delayed_bugs,
1114             dont_buffer_diagnostics,
1115             external_macro_backtrace,
1116             ..Default::default()
1117         },
1118     );
1119
1120     build_session_(sopts, local_crate_source_file, diagnostic_handler, source_map, lint_caps)
1121 }
1122
1123 fn build_session_(
1124     sopts: config::Options,
1125     local_crate_source_file: Option<PathBuf>,
1126     span_diagnostic: errors::Handler,
1127     source_map: Lrc<source_map::SourceMap>,
1128     driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
1129 ) -> Session {
1130     let self_profiler =
1131         if let SwitchWithOptPath::Enabled(ref d) = sopts.debugging_opts.self_profile {
1132             let directory = if let Some(ref directory) = d {
1133                 directory
1134             } else {
1135                 std::path::Path::new(".")
1136             };
1137
1138             let profiler = SelfProfiler::new(
1139                 directory,
1140                 sopts.crate_name.as_ref().map(|s| &s[..]),
1141                 &sopts.debugging_opts.self_profile_events
1142             );
1143             match profiler {
1144                 Ok(profiler) => {
1145                     crate::ty::query::QueryName::register_with_profiler(&profiler);
1146                     Some(Arc::new(profiler))
1147                 },
1148                 Err(e) => {
1149                     early_warn(sopts.error_format, &format!("failed to create profiler: {}", e));
1150                     None
1151                 }
1152             }
1153         }
1154         else { None };
1155
1156     let host_triple = TargetTriple::from_triple(config::host_triple());
1157     let host = Target::search(&host_triple).unwrap_or_else(|e|
1158         span_diagnostic
1159             .fatal(&format!("Error loading host specification: {}", e))
1160             .raise()
1161     );
1162     let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
1163
1164     let parse_sess = ParseSess::with_span_handler(
1165         span_diagnostic,
1166         source_map,
1167     );
1168     let sysroot = match &sopts.maybe_sysroot {
1169         Some(sysroot) => sysroot.clone(),
1170         None => filesearch::get_or_default_sysroot(),
1171     };
1172
1173     let host_triple = config::host_triple();
1174     let target_triple = sopts.target_triple.triple();
1175     let host_tlib_path = SearchPath::from_sysroot_and_triple(&sysroot, host_triple);
1176     let target_tlib_path = if host_triple == target_triple {
1177         None
1178     } else {
1179         Some(SearchPath::from_sysroot_and_triple(&sysroot, target_triple))
1180     };
1181
1182     let file_path_mapping = sopts.file_path_mapping();
1183
1184     let local_crate_source_file =
1185         local_crate_source_file.map(|path| file_path_mapping.map_prefix(path).0);
1186
1187     let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
1188     let optimization_fuel = Lock::new(OptimizationFuel {
1189         remaining: sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0),
1190         out_of_fuel: false,
1191     });
1192     let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
1193     let print_fuel = AtomicU64::new(0);
1194
1195     let working_dir = env::current_dir().unwrap_or_else(|e|
1196         parse_sess.span_diagnostic
1197             .fatal(&format!("Current directory is invalid: {}", e))
1198             .raise()
1199     );
1200     let working_dir = file_path_mapping.map_prefix(working_dir);
1201
1202     let cgu_reuse_tracker = if sopts.debugging_opts.query_dep_graph {
1203         CguReuseTracker::new()
1204     } else {
1205         CguReuseTracker::new_disabled()
1206     };
1207
1208     let sess = Session {
1209         target: target_cfg,
1210         host,
1211         opts: sopts,
1212         host_tlib_path,
1213         target_tlib_path,
1214         parse_sess,
1215         sysroot,
1216         local_crate_source_file,
1217         working_dir,
1218         buffered_lints: Lock::new(Some(Default::default())),
1219         one_time_diagnostics: Default::default(),
1220         plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())),
1221         plugin_attributes: Lock::new(Vec::new()),
1222         crate_types: Once::new(),
1223         crate_disambiguator: Once::new(),
1224         features: Once::new(),
1225         recursion_limit: Once::new(),
1226         type_length_limit: Once::new(),
1227         const_eval_stack_frame_limit: 100,
1228         next_node_id: OneThread::new(Cell::new(NodeId::from_u32(1))),
1229         allocator_kind: Once::new(),
1230         injected_panic_runtime: Once::new(),
1231         imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())),
1232         incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
1233         cgu_reuse_tracker,
1234         prof: SelfProfilerRef::new(self_profiler),
1235         perf_stats: PerfStats {
1236             symbol_hash_time: Lock::new(Duration::from_secs(0)),
1237             decode_def_path_tables_time: Lock::new(Duration::from_secs(0)),
1238             queries_canonicalized: AtomicUsize::new(0),
1239             normalize_ty_after_erasing_regions: AtomicUsize::new(0),
1240             normalize_projection_ty: AtomicUsize::new(0),
1241         },
1242         code_stats: Default::default(),
1243         optimization_fuel_crate,
1244         optimization_fuel,
1245         print_fuel_crate,
1246         print_fuel,
1247         jobserver: jobserver::client(),
1248         has_global_allocator: Once::new(),
1249         has_panic_handler: Once::new(),
1250         driver_lint_caps,
1251         trait_methods_not_found: Lock::new(Default::default()),
1252         confused_type_with_std_module: Lock::new(Default::default()),
1253     };
1254
1255     validate_commandline_args_with_session_available(&sess);
1256
1257     sess
1258 }
1259
1260 // If it is useful to have a Session available already for validating a
1261 // commandline argument, you can do so here.
1262 fn validate_commandline_args_with_session_available(sess: &Session) {
1263     // Since we don't know if code in an rlib will be linked to statically or
1264     // dynamically downstream, rustc generates `__imp_` symbols that help the
1265     // MSVC linker deal with this lack of knowledge (#27438). Unfortunately,
1266     // these manually generated symbols confuse LLD when it tries to merge
1267     // bitcode during ThinLTO. Therefore we disallow dynamic linking on MSVC
1268     // when compiling for LLD ThinLTO. This way we can validly just not generate
1269     // the `dllimport` attributes and `__imp_` symbols in that case.
1270     if sess.opts.cg.linker_plugin_lto.enabled() &&
1271        sess.opts.cg.prefer_dynamic &&
1272        sess.target.target.options.is_like_msvc {
1273         sess.err("Linker plugin based LTO is not supported together with \
1274                   `-C prefer-dynamic` when targeting MSVC");
1275     }
1276
1277     // Make sure that any given profiling data actually exists so LLVM can't
1278     // decide to silently skip PGO.
1279     if let Some(ref path) = sess.opts.cg.profile_use {
1280         if !path.exists() {
1281             sess.err(&format!("File `{}` passed to `-C profile-use` does not exist.",
1282                               path.display()));
1283         }
1284     }
1285
1286     // PGO does not work reliably with panic=unwind on Windows. Let's make it
1287     // an error to combine the two for now. It always runs into an assertions
1288     // if LLVM is built with assertions, but without assertions it sometimes
1289     // does not crash and will probably generate a corrupted binary.
1290     // We should only display this error if we're actually going to run PGO.
1291     // If we're just supposed to print out some data, don't show the error (#61002).
1292     if sess.opts.cg.profile_generate.enabled() &&
1293        sess.target.target.options.is_like_msvc &&
1294        sess.panic_strategy() == PanicStrategy::Unwind &&
1295        sess.opts.prints.iter().all(|&p| p == PrintRequest::NativeStaticLibs) {
1296         sess.err("Profile-guided optimization does not yet work in conjunction \
1297                   with `-Cpanic=unwind` on Windows when targeting MSVC. \
1298                   See https://github.com/rust-lang/rust/issues/61002 for details.");
1299     }
1300 }
1301
1302 /// Hash value constructed out of all the `-C metadata` arguments passed to the
1303 /// compiler. Together with the crate-name forms a unique global identifier for
1304 /// the crate.
1305 #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, RustcEncodable, RustcDecodable)]
1306 pub struct CrateDisambiguator(Fingerprint);
1307
1308 impl CrateDisambiguator {
1309     pub fn to_fingerprint(self) -> Fingerprint {
1310         self.0
1311     }
1312 }
1313
1314 impl fmt::Display for CrateDisambiguator {
1315     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
1316         let (a, b) = self.0.as_value();
1317         let as_u128 = a as u128 | ((b as u128) << 64);
1318         f.write_str(&base_n::encode(as_u128, base_n::CASE_INSENSITIVE))
1319     }
1320 }
1321
1322 impl From<Fingerprint> for CrateDisambiguator {
1323     fn from(fingerprint: Fingerprint) -> CrateDisambiguator {
1324         CrateDisambiguator(fingerprint)
1325     }
1326 }
1327
1328 impl_stable_hash_via_hash!(CrateDisambiguator);
1329
1330 /// Holds data on the current incremental compilation session, if there is one.
1331 #[derive(Debug)]
1332 pub enum IncrCompSession {
1333     /// This is the state the session will be in until the incr. comp. dir is
1334     /// needed.
1335     NotInitialized,
1336     /// This is the state during which the session directory is private and can
1337     /// be modified.
1338     Active {
1339         session_directory: PathBuf,
1340         lock_file: flock::Lock,
1341         load_dep_graph: bool,
1342     },
1343     /// This is the state after the session directory has been finalized. In this
1344     /// state, the contents of the directory must not be modified any more.
1345     Finalized { session_directory: PathBuf },
1346     /// This is an error state that is reached when some compilation error has
1347     /// occurred. It indicates that the contents of the session directory must
1348     /// not be used, since they might be invalid.
1349     InvalidBecauseOfErrors { session_directory: PathBuf },
1350 }
1351
1352 pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
1353     let emitter: Box<dyn Emitter + sync::Send> = match output {
1354         config::ErrorOutputType::HumanReadable(kind) => {
1355             let (short, color_config) = kind.unzip();
1356             Box::new(EmitterWriter::stderr(color_config, None, short, false, None, false))
1357         }
1358         config::ErrorOutputType::Json { pretty, json_rendered } =>
1359             Box::new(JsonEmitter::basic(pretty, json_rendered, false)),
1360     };
1361     let handler = errors::Handler::with_emitter(true, None, emitter);
1362     handler.struct_fatal(msg).emit();
1363     errors::FatalError.raise();
1364 }
1365
1366 pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
1367     let emitter: Box<dyn Emitter + sync::Send> = match output {
1368         config::ErrorOutputType::HumanReadable(kind) => {
1369             let (short, color_config) = kind.unzip();
1370             Box::new(EmitterWriter::stderr(color_config, None, short, false, None, false))
1371         }
1372         config::ErrorOutputType::Json { pretty, json_rendered } =>
1373             Box::new(JsonEmitter::basic(pretty, json_rendered, false)),
1374     };
1375     let handler = errors::Handler::with_emitter(true, None, emitter);
1376     handler.struct_warn(msg).emit();
1377 }
1378
1379 pub type CompileResult = Result<(), ErrorReported>;