1 pub use crate::passes
::BoxedResolver
;
4 use rustc_ast
::ast
::{self, MetaItemKind}
;
6 use rustc_codegen_ssa
::traits
::CodegenBackend
;
7 use rustc_data_structures
::fx
::{FxHashMap, FxHashSet}
;
8 use rustc_data_structures
::sync
::Lrc
;
9 use rustc_data_structures
::OnDrop
;
10 use rustc_errors
::registry
::Registry
;
11 use rustc_errors
::ErrorReported
;
12 use rustc_lint
::LintStore
;
14 use rustc_parse
::new_parser_from_source_str
;
15 use rustc_session
::config
::{self, ErrorOutputType, Input, OutputFilenames}
;
16 use rustc_session
::early_error
;
17 use rustc_session
::lint
;
18 use rustc_session
::parse
::{CrateConfig, ParseSess}
;
19 use rustc_session
::{DiagnosticOutput, Session}
;
20 use rustc_span
::edition
;
21 use rustc_span
::source_map
::{FileLoader, FileName}
;
22 use std
::path
::PathBuf
;
24 use std
::sync
::{Arc, Mutex}
;
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 pub(crate) input
: Input
,
35 pub(crate) input_path
: Option
<PathBuf
>,
36 pub(crate) output_dir
: Option
<PathBuf
>,
37 pub(crate) output_file
: Option
<PathBuf
>,
38 pub(crate) crate_name
: Option
<String
>,
39 pub(crate) register_lints
: Option
<Box
<dyn Fn(&Session
, &mut LintStore
) + Send
+ Sync
>>,
40 pub(crate) override_queries
:
41 Option
<fn(&Session
, &mut ty
::query
::Providers
<'_
>, &mut ty
::query
::Providers
<'_
>)>,
45 pub fn session(&self) -> &Lrc
<Session
> {
48 pub fn codegen_backend(&self) -> &Lrc
<Box
<dyn CodegenBackend
>> {
51 pub fn input(&self) -> &Input
{
54 pub fn output_dir(&self) -> &Option
<PathBuf
> {
57 pub fn output_file(&self) -> &Option
<PathBuf
> {
60 pub fn build_output_filenames(
63 attrs
: &[ast
::Attribute
],
64 ) -> OutputFilenames
{
65 util
::build_output_filenames(
75 /// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
76 pub fn parse_cfgspecs(cfgspecs
: Vec
<String
>) -> FxHashSet
<(String
, Option
<String
>)> {
77 rustc_ast
::with_default_globals(move || {
81 let sess
= ParseSess
::with_silent_emitter();
82 let filename
= FileName
::cfg_spec_source_code(&s
);
83 let mut parser
= new_parser_from_source_str(&sess
, filename
, s
.to_string());
88 ErrorOutputType
::default(),
89 &format
!(concat
!("invalid `--cfg` argument: `{}` (", $reason
, ")"), s
),
94 match &mut parser
.parse_meta_item() {
95 Ok(meta_item
) if parser
.token
== token
::Eof
=> {
96 if meta_item
.path
.segments
.len() != 1 {
97 error
!("argument key must be an identifier");
99 match &meta_item
.kind
{
100 MetaItemKind
::List(..) => {
101 error
!(r
#"expected `key` or `key="value"`"#);
103 MetaItemKind
::NameValue(lit
) if !lit
.kind
.is_str() => {
104 error
!("argument value must be a string");
106 MetaItemKind
::NameValue(..) | MetaItemKind
::Word
=> {
107 let ident
= meta_item
.ident().expect("multi-segment cfg key");
108 return (ident
.name
, meta_item
.value_str());
113 Err(err
) => err
.cancel(),
116 error
!(r
#"expected `key` or `key="value"`"#);
118 .collect
::<CrateConfig
>();
119 cfg
.into_iter().map(|(a
, b
)| (a
.to_string(), b
.map(|b
| b
.to_string()))).collect()
123 /// The compiler configuration
125 /// Command line options
126 pub opts
: config
::Options
,
128 /// cfg! configuration in addition to the default ones
129 pub crate_cfg
: FxHashSet
<(String
, Option
<String
>)>,
132 pub input_path
: Option
<PathBuf
>,
133 pub output_dir
: Option
<PathBuf
>,
134 pub output_file
: Option
<PathBuf
>,
135 pub file_loader
: Option
<Box
<dyn FileLoader
+ Send
+ Sync
>>,
136 pub diagnostic_output
: DiagnosticOutput
,
138 /// Set to capture stderr output during compiler execution
139 pub stderr
: Option
<Arc
<Mutex
<Vec
<u8>>>>,
141 pub crate_name
: Option
<String
>,
142 pub lint_caps
: FxHashMap
<lint
::LintId
, lint
::Level
>,
144 /// This is a callback from the driver that is called when we're registering lints;
145 /// it is called during plugin registration when we have the LintStore in a non-shared state.
147 /// Note that if you find a Some here you probably want to call that function in the new
148 /// function being registered.
149 pub register_lints
: Option
<Box
<dyn Fn(&Session
, &mut LintStore
) + Send
+ Sync
>>,
151 /// This is a callback from the driver that is called just after we have populated
152 /// the list of queries.
154 /// The second parameter is local providers and the third parameter is external providers.
155 pub override_queries
:
156 Option
<fn(&Session
, &mut ty
::query
::Providers
<'_
>, &mut ty
::query
::Providers
<'_
>)>,
158 /// Registry of diagnostics codes.
159 pub registry
: Registry
,
162 pub fn run_compiler_in_existing_thread_pool
<R
>(
164 f
: impl FnOnce(&Compiler
) -> R
,
166 let registry
= &config
.registry
;
167 let (sess
, codegen_backend
) = util
::create_session(
170 config
.diagnostic_output
,
172 config
.input_path
.clone(),
177 let compiler
= Compiler
{
181 input_path
: config
.input_path
,
182 output_dir
: config
.output_dir
,
183 output_file
: config
.output_file
,
184 crate_name
: config
.crate_name
,
185 register_lints
: config
.register_lints
,
186 override_queries
: config
.override_queries
,
190 let _sess_abort_error
= OnDrop(|| {
191 compiler
.sess
.finish_diagnostics(registry
);
197 let prof
= compiler
.sess
.prof
.clone();
198 prof
.generic_activity("drop_compiler").run(move || drop(compiler
));
202 pub fn run_compiler
<R
: Send
>(mut config
: Config
, f
: impl FnOnce(&Compiler
) -> R
+ Send
) -> R
{
203 let stderr
= config
.stderr
.take();
204 util
::spawn_thread_pool(
206 config
.opts
.debugging_opts
.threads
,
208 || run_compiler_in_existing_thread_pool(config
, f
),
212 pub fn default_thread_pool
<R
: Send
>(edition
: edition
::Edition
, f
: impl FnOnce() -> R
+ Send
) -> R
{
213 // the 1 here is duplicating code in config.opts.debugging_opts.threads
214 // which also defaults to 1; it ultimately doesn't matter as the default
215 // isn't threaded, and just ignores this parameter
216 util
::spawn_thread_pool(edition
, 1, &None
, f
)