2 pub use crate::passes
::BoxedResolver
;
5 use rustc
::session
::early_error
;
6 use rustc
::session
::config
::{self, Input, ErrorOutputType}
;
7 use rustc
::session
::{DiagnosticOutput, Session}
;
8 use rustc
::util
::common
::ErrorReported
;
9 use rustc_codegen_utils
::codegen_backend
::CodegenBackend
;
10 use rustc_data_structures
::OnDrop
;
11 use rustc_data_structures
::sync
::Lrc
;
12 use rustc_data_structures
::fx
::{FxHashSet, FxHashMap}
;
13 use rustc_errors
::registry
::Registry
;
14 use rustc_parse
::new_parser_from_source_str
;
16 use std
::path
::PathBuf
;
18 use std
::sync
::{Arc, Mutex}
;
19 use syntax
::ast
::{self, MetaItemKind}
;
21 use syntax
::source_map
::{FileName, FileLoader, SourceMap}
;
22 use syntax
::sess
::ParseSess
;
23 use syntax_pos
::edition
;
25 pub type Result
<T
> = result
::Result
<T
, ErrorReported
>;
27 /// Represents a compiler session.
28 /// Can be used run `rustc_interface` queries.
29 /// Created by passing `Config` to `run_compiler`.
31 pub(crate) sess
: Lrc
<Session
>,
32 codegen_backend
: Lrc
<Box
<dyn CodegenBackend
>>,
33 source_map
: Lrc
<SourceMap
>,
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 lint
::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 source_map(&self) -> &Lrc
<SourceMap
> {
54 pub fn input(&self) -> &Input
{
57 pub fn output_dir(&self) -> &Option
<PathBuf
> {
60 pub fn output_file(&self) -> &Option
<PathBuf
> {
65 /// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
66 pub fn parse_cfgspecs(cfgspecs
: Vec
<String
>) -> FxHashSet
<(String
, Option
<String
>)> {
67 syntax
::with_default_globals(move || {
68 let cfg
= cfgspecs
.into_iter().map(|s
| {
69 let sess
= ParseSess
::with_silent_emitter();
70 let filename
= FileName
::cfg_spec_source_code(&s
);
71 let mut parser
= new_parser_from_source_str(&sess
, filename
, s
.to_string());
73 macro_rules
! error
{($reason
: expr
) => {
74 early_error(ErrorOutputType
::default(),
75 &format
!(concat
!("invalid `--cfg` argument: `{}` (", $reason
, ")"), s
));
78 match &mut parser
.parse_meta_item() {
79 Ok(meta_item
) if parser
.token
== token
::Eof
=> {
80 if meta_item
.path
.segments
.len() != 1 {
81 error
!("argument key must be an identifier");
83 match &meta_item
.kind
{
84 MetaItemKind
::List(..) => {
85 error
!(r
#"expected `key` or `key="value"`"#);
87 MetaItemKind
::NameValue(lit
) if !lit
.kind
.is_str() => {
88 error
!("argument value must be a string");
90 MetaItemKind
::NameValue(..) | MetaItemKind
::Word
=> {
91 let ident
= meta_item
.ident().expect("multi-segment cfg key");
92 return (ident
.name
, meta_item
.value_str());
97 Err(err
) => err
.cancel(),
100 error
!(r
#"expected `key` or `key="value"`"#);
101 }).collect
::<ast
::CrateConfig
>();
102 cfg
.into_iter().map(|(a
, b
)| {
103 (a
.to_string(), b
.map(|b
| b
.to_string()))
108 /// The compiler configuration
110 /// Command line options
111 pub opts
: config
::Options
,
113 /// cfg! configuration in addition to the default ones
114 pub crate_cfg
: FxHashSet
<(String
, Option
<String
>)>,
117 pub input_path
: Option
<PathBuf
>,
118 pub output_dir
: Option
<PathBuf
>,
119 pub output_file
: Option
<PathBuf
>,
120 pub file_loader
: Option
<Box
<dyn FileLoader
+ Send
+ Sync
>>,
121 pub diagnostic_output
: DiagnosticOutput
,
123 /// Set to capture stderr output during compiler execution
124 pub stderr
: Option
<Arc
<Mutex
<Vec
<u8>>>>,
126 pub crate_name
: Option
<String
>,
127 pub lint_caps
: FxHashMap
<lint
::LintId
, lint
::Level
>,
129 /// This is a callback from the driver that is called when we're registering lints;
130 /// it is called during plugin registration when we have the LintStore in a non-shared state.
132 /// Note that if you find a Some here you probably want to call that function in the new
133 /// function being registered.
134 pub register_lints
: Option
<Box
<dyn Fn(&Session
, &mut lint
::LintStore
) + Send
+ Sync
>>,
136 /// This is a callback from the driver that is called just after we have populated
137 /// the list of queries.
139 /// The second parameter is local providers and the third parameter is external providers.
140 pub override_queries
:
141 Option
<fn(&Session
, &mut ty
::query
::Providers
<'_
>, &mut ty
::query
::Providers
<'_
>)>,
143 /// Registry of diagnostics codes.
144 pub registry
: Registry
,
147 pub fn run_compiler_in_existing_thread_pool
<R
>(
149 f
: impl FnOnce(&Compiler
) -> R
,
151 let registry
= &config
.registry
;
152 let (sess
, codegen_backend
, source_map
) = util
::create_session(
155 config
.diagnostic_output
,
157 config
.input_path
.clone(),
162 let compiler
= Compiler
{
167 input_path
: config
.input_path
,
168 output_dir
: config
.output_dir
,
169 output_file
: config
.output_file
,
170 crate_name
: config
.crate_name
,
171 register_lints
: config
.register_lints
,
172 override_queries
: config
.override_queries
,
175 let _sess_abort_error
= OnDrop(|| {
176 compiler
.sess
.diagnostic().print_error_count(registry
);
182 pub fn run_compiler
<R
: Send
>(mut config
: Config
, f
: impl FnOnce(&Compiler
) -> R
+ Send
) -> R
{
183 let stderr
= config
.stderr
.take();
184 util
::spawn_thread_pool(
186 config
.opts
.debugging_opts
.threads
,
188 || run_compiler_in_existing_thread_pool(config
, f
),
192 pub fn default_thread_pool
<R
: Send
>(edition
: edition
::Edition
, f
: impl FnOnce() -> R
+ Send
) -> R
{
193 // the 1 here is duplicating code in config.opts.debugging_opts.threads
194 // which also defaults to 1; it ultimately doesn't matter as the default
195 // isn't threaded, and just ignores this parameter
196 util
::spawn_thread_pool(edition
, 1, &None
, f
)