1 pub use crate::passes
::BoxedResolver
;
5 use rustc
::session
::config
::{self, ErrorOutputType, Input}
;
6 use rustc
::session
::early_error
;
7 use rustc
::session
::{DiagnosticOutput, Session}
;
9 use rustc
::util
::common
::ErrorReported
;
10 use rustc_codegen_utils
::codegen_backend
::CodegenBackend
;
11 use rustc_data_structures
::fx
::{FxHashMap, FxHashSet}
;
12 use rustc_data_structures
::sync
::Lrc
;
13 use rustc_data_structures
::OnDrop
;
14 use rustc_errors
::registry
::Registry
;
15 use rustc_lint
::LintStore
;
16 use rustc_parse
::new_parser_from_source_str
;
17 use rustc_span
::edition
;
18 use rustc_span
::source_map
::{FileLoader, FileName, SourceMap}
;
19 use std
::path
::PathBuf
;
21 use std
::sync
::{Arc, Mutex}
;
22 use syntax
::ast
::{self, MetaItemKind}
;
23 use syntax
::sess
::ParseSess
;
26 pub type Result
<T
> = result
::Result
<T
, ErrorReported
>;
28 /// Represents a compiler session.
29 /// Can be used to run `rustc_interface` queries.
30 /// Created by passing `Config` to `run_compiler`.
32 pub(crate) sess
: Lrc
<Session
>,
33 codegen_backend
: Lrc
<Box
<dyn CodegenBackend
>>,
34 source_map
: Lrc
<SourceMap
>,
35 pub(crate) input
: Input
,
36 pub(crate) input_path
: Option
<PathBuf
>,
37 pub(crate) output_dir
: Option
<PathBuf
>,
38 pub(crate) output_file
: Option
<PathBuf
>,
39 pub(crate) crate_name
: Option
<String
>,
40 pub(crate) register_lints
: Option
<Box
<dyn Fn(&Session
, &mut LintStore
) + Send
+ Sync
>>,
41 pub(crate) override_queries
:
42 Option
<fn(&Session
, &mut ty
::query
::Providers
<'_
>, &mut ty
::query
::Providers
<'_
>)>,
46 pub fn session(&self) -> &Lrc
<Session
> {
49 pub fn codegen_backend(&self) -> &Lrc
<Box
<dyn CodegenBackend
>> {
52 pub fn source_map(&self) -> &Lrc
<SourceMap
> {
55 pub fn input(&self) -> &Input
{
58 pub fn output_dir(&self) -> &Option
<PathBuf
> {
61 pub fn output_file(&self) -> &Option
<PathBuf
> {
66 /// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
67 pub fn parse_cfgspecs(cfgspecs
: Vec
<String
>) -> FxHashSet
<(String
, Option
<String
>)> {
68 syntax
::with_default_globals(move || {
72 let sess
= ParseSess
::with_silent_emitter();
73 let filename
= FileName
::cfg_spec_source_code(&s
);
74 let mut parser
= new_parser_from_source_str(&sess
, filename
, s
.to_string());
79 ErrorOutputType
::default(),
80 &format
!(concat
!("invalid `--cfg` argument: `{}` (", $reason
, ")"), s
),
85 match &mut parser
.parse_meta_item() {
86 Ok(meta_item
) if parser
.token
== token
::Eof
=> {
87 if meta_item
.path
.segments
.len() != 1 {
88 error
!("argument key must be an identifier");
90 match &meta_item
.kind
{
91 MetaItemKind
::List(..) => {
92 error
!(r
#"expected `key` or `key="value"`"#);
94 MetaItemKind
::NameValue(lit
) if !lit
.kind
.is_str() => {
95 error
!("argument value must be a string");
97 MetaItemKind
::NameValue(..) | MetaItemKind
::Word
=> {
98 let ident
= meta_item
.ident().expect("multi-segment cfg key");
99 return (ident
.name
, meta_item
.value_str());
104 Err(err
) => err
.cancel(),
107 error
!(r
#"expected `key` or `key="value"`"#);
109 .collect
::<ast
::CrateConfig
>();
110 cfg
.into_iter().map(|(a
, b
)| (a
.to_string(), b
.map(|b
| b
.to_string()))).collect()
114 /// The compiler configuration
116 /// Command line options
117 pub opts
: config
::Options
,
119 /// cfg! configuration in addition to the default ones
120 pub crate_cfg
: FxHashSet
<(String
, Option
<String
>)>,
123 pub input_path
: Option
<PathBuf
>,
124 pub output_dir
: Option
<PathBuf
>,
125 pub output_file
: Option
<PathBuf
>,
126 pub file_loader
: Option
<Box
<dyn FileLoader
+ Send
+ Sync
>>,
127 pub diagnostic_output
: DiagnosticOutput
,
129 /// Set to capture stderr output during compiler execution
130 pub stderr
: Option
<Arc
<Mutex
<Vec
<u8>>>>,
132 pub crate_name
: Option
<String
>,
133 pub lint_caps
: FxHashMap
<lint
::LintId
, lint
::Level
>,
135 /// This is a callback from the driver that is called when we're registering lints;
136 /// it is called during plugin registration when we have the LintStore in a non-shared state.
138 /// Note that if you find a Some here you probably want to call that function in the new
139 /// function being registered.
140 pub register_lints
: Option
<Box
<dyn Fn(&Session
, &mut LintStore
) + Send
+ Sync
>>,
142 /// This is a callback from the driver that is called just after we have populated
143 /// the list of queries.
145 /// The second parameter is local providers and the third parameter is external providers.
146 pub override_queries
:
147 Option
<fn(&Session
, &mut ty
::query
::Providers
<'_
>, &mut ty
::query
::Providers
<'_
>)>,
149 /// Registry of diagnostics codes.
150 pub registry
: Registry
,
153 pub fn run_compiler_in_existing_thread_pool
<R
>(
155 f
: impl FnOnce(&Compiler
) -> R
,
157 let registry
= &config
.registry
;
158 let (sess
, codegen_backend
, source_map
) = util
::create_session(
161 config
.diagnostic_output
,
163 config
.input_path
.clone(),
168 let compiler
= Compiler
{
173 input_path
: config
.input_path
,
174 output_dir
: config
.output_dir
,
175 output_file
: config
.output_file
,
176 crate_name
: config
.crate_name
,
177 register_lints
: config
.register_lints
,
178 override_queries
: config
.override_queries
,
182 let _sess_abort_error
= OnDrop(|| {
183 compiler
.sess
.diagnostic().print_error_count(registry
);
189 let prof
= compiler
.sess
.prof
.clone();
190 prof
.generic_activity("drop_compiler").run(move || drop(compiler
));
194 pub fn run_compiler
<R
: Send
>(mut config
: Config
, f
: impl FnOnce(&Compiler
) -> R
+ Send
) -> R
{
195 let stderr
= config
.stderr
.take();
196 util
::spawn_thread_pool(
198 config
.opts
.debugging_opts
.threads
,
200 || run_compiler_in_existing_thread_pool(config
, f
),
204 pub fn default_thread_pool
<R
: Send
>(edition
: edition
::Edition
, f
: impl FnOnce() -> R
+ Send
) -> R
{
205 // the 1 here is duplicating code in config.opts.debugging_opts.threads
206 // which also defaults to 1; it ultimately doesn't matter as the default
207 // isn't threaded, and just ignores this parameter
208 util
::spawn_thread_pool(edition
, 1, &None
, f
)