Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Commit 60da121

Browse files
committed
Adapt to newest rustc interface changes in the main rls package
1 parent 05fa70e commit 60da121

File tree

2 files changed

+109
-113
lines changed

2 files changed

+109
-113
lines changed

rls/src/build/rustc.rs

Lines changed: 102 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ extern crate rustc_driver;
1111
#[allow(unused_extern_crates)]
1212
extern crate rustc_errors;
1313
#[allow(unused_extern_crates)]
14+
extern crate rustc_interface;
15+
#[allow(unused_extern_crates)]
1416
extern crate rustc_metadata;
1517
#[allow(unused_extern_crates)]
1618
extern crate rustc_plugin;
@@ -37,10 +39,10 @@ use crate::build::environment::{Environment, EnvironmentLockFacade};
3739
use crate::build::{BufWriter, BuildResult};
3840
use crate::build::plan::{Crate, Edition};
3941
use crate::config::{ClippyPreference, Config};
40-
use self::rustc_driver::driver::CompileController;
41-
use self::rustc_driver::{run, run_compiler, CompilerCalls, RustcDefaultCalls};
42+
use self::rustc_driver::{run_compiler};
4243
use self::rustc_save_analysis as save;
4344
use self::rustc_save_analysis::CallbackHandler;
45+
use self::rustc_interface::interface;
4446
use self::rustc::session::Session;
4547
use self::rustc::session::config::Input;
4648
use self::syntax::source_map::{FileLoader, RealFileLoader};
@@ -68,7 +70,7 @@ pub(crate) fn rustc(
6870

6971
let mut local_envs = envs.clone();
7072

71-
let clippy_pref = {
73+
let clippy_preference = {
7274
let config = rls_config.lock().unwrap();
7375
if config.clear_env_rust_log {
7476
local_envs.insert(String::from("RUST_LOG"), None);
@@ -84,11 +86,11 @@ pub(crate) fn rustc(
8486

8587
let buf = Arc::new(Mutex::new(vec![]));
8688
let err_buf = buf.clone();
87-
let args: Vec<_> = if cfg!(feature = "clippy") && clippy_pref != ClippyPreference::Off {
89+
let args: Vec<_> = if cfg!(feature = "clippy") && clippy_preference != ClippyPreference::Off {
8890
// Allow feature gating in the same way as `cargo clippy`
8991
let mut clippy_args = vec!["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()];
9092

91-
if clippy_pref == ClippyPreference::OptIn {
93+
if clippy_preference == ClippyPreference::OptIn {
9294
// `OptIn`: Require explicit `#![warn(clippy::all)]` annotation in each workspace crate
9395
clippy_args.push("-A".to_owned());
9496
clippy_args.push("clippy::all".to_owned());
@@ -99,21 +101,20 @@ pub(crate) fn rustc(
99101
args.to_owned()
100102
};
101103

102-
let analysis = Arc::default();
103-
let input_files = Arc::default();
104-
let controller =
105-
Box::new(RlsRustcCalls::new(Arc::clone(&analysis), Arc::clone(&input_files), clippy_pref));
104+
let mut callbacks = RlsRustcCalls { clippy_preference, ..Default::default() };
105+
let analysis = Arc::clone(&callbacks.analysis);
106+
let input_files = Arc::clone(&callbacks.input_files);
106107

107108
// rustc explicitly panics in `run_compiler()` on compile failure, regardless
108109
// of whether it encounters an ICE (internal compiler error) or not.
109110
// TODO: Change librustc_driver behaviour to distinguish between ICEs and
110111
// regular compilation failure with errors?
111112
let result = ::std::panic::catch_unwind(|| {
112-
run(move || {
113+
rustc_driver::report_ices_to_stderr_if_any(move || {
113114
// Replace stderr so we catch most errors.
114115
run_compiler(
115116
&args,
116-
controller,
117+
&mut callbacks,
117118
Some(Box::new(ReplacedFileLoader::new(changed))),
118119
Some(Box::new(BufWriter(buf))),
119120
)
@@ -139,36 +140,113 @@ pub(crate) fn rustc(
139140

140141
// Our compiler controller. We mostly delegate to the default rustc
141142
// controller, but use our own callback for save-analysis.
142-
#[derive(Clone)]
143+
#[derive(Clone, Default)]
143144
struct RlsRustcCalls {
144145
analysis: Arc<Mutex<Option<Analysis>>>,
145146
input_files: Arc<Mutex<HashMap<PathBuf, HashSet<Crate>>>>,
146147
clippy_preference: ClippyPreference,
147148
}
148149

149-
impl RlsRustcCalls {
150-
fn new(
151-
analysis: Arc<Mutex<Option<Analysis>>>,
152-
input_files: Arc<Mutex<HashMap<PathBuf, HashSet<Crate>>>>,
153-
clippy_preference: ClippyPreference,
154-
) -> RlsRustcCalls {
155-
RlsRustcCalls { analysis, input_files, clippy_preference }
150+
impl rustc_driver::Callbacks for RlsRustcCalls {
151+
fn config(&mut self, config: &mut interface::Config) {
152+
// This also prevents the compiler from dropping expanded AST, which we
153+
// still need in the `after_analysis` callback in order to process and
154+
// pass the computed analysis in-memory.
155+
config.opts.debugging_opts.save_analysis = true;
156+
}
157+
158+
fn after_parsing(&mut self, _compiler: &interface::Compiler) -> bool {
159+
#[cfg(feature = "clippy")]
160+
{
161+
if self.clippy_preference != ClippyPreference::Off {
162+
clippy_after_parse_callback(_compiler);
163+
}
164+
}
165+
// Continue execution
166+
true
167+
}
168+
169+
fn after_analysis(&mut self, compiler: &interface::Compiler) -> bool {
170+
let sess = compiler.session();
171+
let input = compiler.input();
172+
let crate_name = compiler.crate_name().unwrap().peek().clone();
173+
174+
let cwd = &sess.working_dir.0;
175+
176+
let src_path = match input {
177+
Input::File(ref name) => Some(name.to_path_buf()),
178+
Input::Str { .. } => None,
179+
}
180+
.and_then(|path| src_path(Some(cwd), path));
181+
182+
let krate = Crate {
183+
name: crate_name.to_owned(),
184+
src_path,
185+
disambiguator: sess.local_crate_disambiguator().to_fingerprint().as_value(),
186+
edition: match sess.edition() {
187+
RustcEdition::Edition2015 => Edition::Edition2015,
188+
RustcEdition::Edition2018 => Edition::Edition2018,
189+
},
190+
};
191+
let files = fetch_input_files(sess);
192+
193+
let mut input_files = self.input_files.lock().unwrap();
194+
for file in &files {
195+
input_files.entry(file.to_path_buf()).or_default().insert(krate.clone());
196+
}
197+
198+
// Guaranteed to not be dropped yet in the pipeline thanks to the
199+
// `config.opts.debugging_opts.save_analysis` value being set to `true`.
200+
let expanded_crate = &compiler.expansion().unwrap().peek().0;
201+
compiler.global_ctxt().unwrap().peek_mut().enter(|tcx| {
202+
// There are two ways to move the data from rustc to the RLS, either
203+
// directly or by serialising and deserialising. We only want to do
204+
// the latter when there are compatibility issues between crates.
205+
206+
// This version passes via JSON, it is more easily backwards compatible.
207+
// save::process_crate(state.tcx.unwrap(),
208+
// state.expanded_crate.unwrap(),
209+
// state.analysis.unwrap(),
210+
// state.crate_name.unwrap(),
211+
// state.input,
212+
// None,
213+
// save::DumpHandler::new(state.out_dir,
214+
// state.crate_name.unwrap()));
215+
// This version passes directly, it is more efficient.
216+
save::process_crate(
217+
tcx,
218+
&expanded_crate,
219+
&crate_name,
220+
&input,
221+
None,
222+
CallbackHandler {
223+
callback: &mut |a| {
224+
let mut analysis = self.analysis.lock().unwrap();
225+
let a = unsafe { ::std::mem::transmute(a.clone()) };
226+
*analysis = Some(a);
227+
},
228+
},
229+
);
230+
});
231+
232+
true
156233
}
157234
}
158235

159236
#[cfg(feature = "clippy")]
160-
fn clippy_after_parse_callback(state: &mut rustc_driver::driver::CompileState<'_, '_>) {
237+
fn clippy_after_parse_callback(compiler: &interface::Compiler) {
161238
use self::rustc_plugin::registry::Registry;
162239

240+
let sess = compiler.session();
163241
let mut registry = Registry::new(
164-
state.session,
165-
state
166-
.krate
167-
.as_ref()
242+
sess,
243+
compiler
244+
.parse()
168245
.expect(
169246
"at this compilation stage \
170247
the crate must be parsed",
171248
)
249+
.peek()
172250
.span,
173251
);
174252
registry.args_hidden = Some(Vec::new());
@@ -179,7 +257,6 @@ fn clippy_after_parse_callback(state: &mut rustc_driver::driver::CompileState<'_
179257
let Registry {
180258
early_lint_passes, late_lint_passes, lint_groups, llvm_passes, attributes, ..
181259
} = registry;
182-
let sess = &state.session;
183260
let mut ls = sess.lint_store.borrow_mut();
184261
for pass in early_lint_passes {
185262
ls.register_early_pass(Some(sess), true, false, pass);
@@ -198,93 +275,6 @@ fn clippy_after_parse_callback(state: &mut rustc_driver::driver::CompileState<'_
198275
sess.plugin_attributes.borrow_mut().extend(attributes);
199276
}
200277

201-
impl<'a> CompilerCalls<'a> for RlsRustcCalls {
202-
#[allow(clippy::boxed_local)] // https://github.com/rust-lang/rust-clippy/issues/1123
203-
fn build_controller(
204-
self: Box<Self>,
205-
sess: &Session,
206-
matches: &getopts::Matches,
207-
) -> CompileController<'a> {
208-
let analysis = self.analysis.clone();
209-
let input_files = self.input_files.clone();
210-
#[cfg(feature = "clippy")]
211-
let clippy_preference = self.clippy_preference;
212-
let mut result = Box::new(RustcDefaultCalls).build_controller(sess, matches);
213-
result.keep_ast = true;
214-
215-
#[cfg(feature = "clippy")]
216-
{
217-
if clippy_preference != ClippyPreference::Off {
218-
result.after_parse.callback = Box::new(clippy_after_parse_callback);
219-
}
220-
}
221-
222-
result.after_expand.callback = Box::new(move |state| {
223-
let cwd = &state.session.working_dir.0;
224-
225-
let src_path = match state.input {
226-
Input::File(ref name) => Some(name.to_path_buf()),
227-
Input::Str { .. } => None,
228-
}
229-
.and_then(|path| src_path(Some(cwd), path));
230-
231-
let krate = Crate {
232-
name: state.crate_name.expect("missing crate name").to_owned(),
233-
src_path,
234-
disambiguator: state
235-
.session
236-
.local_crate_disambiguator()
237-
.to_fingerprint()
238-
.as_value(),
239-
edition: match state.session.edition() {
240-
RustcEdition::Edition2015 => Edition::Edition2015,
241-
RustcEdition::Edition2018 => Edition::Edition2018,
242-
},
243-
};
244-
let files = fetch_input_files(state.session);
245-
246-
let mut input_files = input_files.lock().unwrap();
247-
for file in &files {
248-
input_files.entry(file.to_path_buf()).or_default().insert(krate.clone());
249-
}
250-
});
251-
252-
result.after_analysis.callback = Box::new(move |state| {
253-
// There are two ways to move the data from rustc to the RLS, either
254-
// directly or by serialising and deserialising. We only want to do
255-
// the latter when there are compatibility issues between crates.
256-
257-
// This version passes via JSON, it is more easily backwards compatible.
258-
// save::process_crate(state.tcx.unwrap(),
259-
// state.expanded_crate.unwrap(),
260-
// state.analysis.unwrap(),
261-
// state.crate_name.unwrap(),
262-
// state.input,
263-
// None,
264-
// save::DumpHandler::new(state.out_dir,
265-
// state.crate_name.unwrap()));
266-
// This version passes directly, it is more efficient.
267-
save::process_crate(
268-
state.tcx.expect("missing tcx"),
269-
state.expanded_crate.expect("missing crate"),
270-
state.crate_name.expect("missing crate name"),
271-
state.input,
272-
None,
273-
CallbackHandler {
274-
callback: &mut |a| {
275-
let mut analysis = analysis.lock().unwrap();
276-
let a = unsafe { ::std::mem::transmute(a.clone()) };
277-
*analysis = Some(a);
278-
},
279-
},
280-
);
281-
});
282-
result.after_analysis.run_callback_on_error = true;
283-
284-
result
285-
}
286-
}
287-
288278
fn fetch_input_files(sess: &Session) -> Vec<PathBuf> {
289279
let cwd = &sess.working_dir.0;
290280

rls/src/config.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ impl Default for Config {
181181
jobs: None,
182182
all_targets: true,
183183
racer_completion: true,
184-
clippy_preference: ClippyPreference::OptIn,
184+
clippy_preference: ClippyPreference::default(),
185185
full_docs: Inferrable::Inferred(false),
186186
show_hover_context: true,
187187
rustfmt_path: None,
@@ -326,6 +326,12 @@ pub enum ClippyPreference {
326326
On,
327327
}
328328

329+
impl Default for ClippyPreference {
330+
fn default() -> Self {
331+
ClippyPreference::OptIn
332+
}
333+
}
334+
329335
/// Permissive deserialization for `ClippyPreference`
330336
/// "opt-in", "Optin" -> `ClippyPreference::OptIn`
331337
impl FromStr for ClippyPreference {

0 commit comments

Comments
 (0)