]> git.lizzy.rs Git - rust.git/blobdiff - src/driver.rs
ExprUseVisitor::Delegate consume only when moving
[rust.git] / src / driver.rs
index ef31c72481a236793b026fac2c02ca820268ac2c..0c82f37d6a22e32572c15956bdf6ecd7e0c32d80 100644 (file)
@@ -4,17 +4,19 @@
 // warn on lints, that are included in `rust-lang/rust`s bootstrap
 #![warn(rust_2018_idioms, unused_lifetimes)]
 // warn on rustc internal lints
-#![deny(rustc::internal)]
+#![warn(rustc::internal)]
 
 // FIXME: switch to something more ergonomic here, once available.
 // (Currently there is no way to opt into sysroot crates without `extern crate`.)
 extern crate rustc_driver;
 extern crate rustc_errors;
 extern crate rustc_interface;
-extern crate rustc_middle;
+extern crate rustc_session;
+extern crate rustc_span;
 
 use rustc_interface::interface;
-use rustc_middle::ty::TyCtxt;
+use rustc_session::parse::ParseSess;
+use rustc_span::symbol::Symbol;
 use rustc_tools_util::VersionInfo;
 
 use std::borrow::Cow;
@@ -61,31 +63,60 @@ fn test_arg_value() {
     assert_eq!(arg_value(args, "--foo", |_| true), None);
 }
 
+fn track_clippy_args(parse_sess: &mut ParseSess, args_env_var: &Option<String>) {
+    parse_sess.env_depinfo.get_mut().insert((
+        Symbol::intern("CLIPPY_ARGS"),
+        args_env_var.as_deref().map(Symbol::intern),
+    ));
+}
+
 struct DefaultCallbacks;
 impl rustc_driver::Callbacks for DefaultCallbacks {}
 
-struct ClippyCallbacks;
+/// This is different from `DefaultCallbacks` that it will inform Cargo to track the value of
+/// `CLIPPY_ARGS` environment variable.
+struct RustcCallbacks {
+    clippy_args_var: Option<String>,
+}
+
+impl rustc_driver::Callbacks for RustcCallbacks {
+    fn config(&mut self, config: &mut interface::Config) {
+        let clippy_args_var = self.clippy_args_var.take();
+        config.parse_sess_created = Some(Box::new(move |parse_sess| {
+            track_clippy_args(parse_sess, &clippy_args_var);
+        }));
+    }
+}
+
+struct ClippyCallbacks {
+    clippy_args_var: Option<String>,
+}
+
 impl rustc_driver::Callbacks for ClippyCallbacks {
     fn config(&mut self, config: &mut interface::Config) {
         let previous = config.register_lints.take();
-        config.register_lints = Some(Box::new(move |sess, mut lint_store| {
+        let clippy_args_var = self.clippy_args_var.take();
+        config.parse_sess_created = Some(Box::new(move |parse_sess| {
+            track_clippy_args(parse_sess, &clippy_args_var);
+        }));
+        config.register_lints = Some(Box::new(move |sess, lint_store| {
             // technically we're ~guaranteed that this is none but might as well call anything that
             // is there already. Certainly it can't hurt.
             if let Some(previous) = &previous {
                 (previous)(sess, lint_store);
             }
 
-            let conf = clippy_lints::read_conf(&[], &sess);
-            clippy_lints::register_plugins(&mut lint_store, &sess, &conf);
-            clippy_lints::register_pre_expansion_lints(&mut lint_store);
-            clippy_lints::register_renamed(&mut lint_store);
+            let conf = clippy_lints::read_conf(sess);
+            clippy_lints::register_plugins(lint_store, sess, &conf);
+            clippy_lints::register_pre_expansion_lints(lint_store);
+            clippy_lints::register_renamed(lint_store);
         }));
 
         // FIXME: #4825; This is required, because Clippy lints that are based on MIR have to be
         // run on the unoptimized MIR. On the other hand this results in some false negatives. If
         // MIR passes can be enabled / disabled separately, we should figure out, what passes to
         // use for Clippy.
-        config.opts.debugging_opts.mir_opt_level = 0;
+        config.opts.debugging_opts.mir_opt_level = Some(0);
     }
 }
 
@@ -160,7 +191,7 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
     ];
 
     for note in &xs {
-        handler.note_without_error(&note);
+        handler.note_without_error(note);
     }
 
     // If backtraces are enabled, also print the query stack
@@ -168,7 +199,7 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
 
     let num_frames = if backtrace { None } else { Some(2) };
 
-    TyCtxt::try_print_query_stack(&handler, num_frames);
+    interface::try_print_query_stack(&handler, num_frames);
 }
 
 fn toolchain_path(home: Option<String>, toolchain: Option<String>) -> Option<PathBuf> {
@@ -182,6 +213,7 @@ fn toolchain_path(home: Option<String>, toolchain: Option<String>) -> Option<Pat
     })
 }
 
+#[allow(clippy::too_many_lines)]
 pub fn main() {
     rustc_driver::init_rustc_env_logger();
     SyncLazy::force(&ICE_HOOK);
@@ -277,27 +309,41 @@ pub fn main() {
             args.extend(vec!["--sysroot".into(), sys_root]);
         };
 
-        // this check ensures that dependencies are built but not linted and the final
-        // crate is linted but not built
-        let clippy_enabled = env::var("CLIPPY_TESTS").map_or(false, |val| val == "true")
-            || arg_value(&orig_args, "--cap-lints", |val| val == "allow").is_none();
+        let mut no_deps = false;
+        let clippy_args_var = env::var("CLIPPY_ARGS").ok();
+        let clippy_args = clippy_args_var
+            .as_deref()
+            .unwrap_or_default()
+            .split("__CLIPPY_HACKERY__")
+            .filter_map(|s| match s {
+                "" => None,
+                "--no-deps" => {
+                    no_deps = true;
+                    None
+                },
+                _ => Some(s.to_string()),
+            })
+            .chain(vec!["--cfg".into(), r#"feature="cargo-clippy""#.into()])
+            .collect::<Vec<String>>();
+
+        // We enable Clippy if one of the following conditions is met
+        // - IF Clippy is run on its test suite OR
+        // - IF Clippy is run on the main crate, not on deps (`!cap_lints_allow`) THEN
+        //    - IF `--no-deps` is not set (`!no_deps`) OR
+        //    - IF `--no-deps` is set and Clippy is run on the specified primary package
+        let clippy_tests_set = env::var("__CLIPPY_INTERNAL_TESTS").map_or(false, |val| val == "true");
+        let cap_lints_allow = arg_value(&orig_args, "--cap-lints", |val| val == "allow").is_some();
+        let in_primary_package = env::var("CARGO_PRIMARY_PACKAGE").is_ok();
+
+        let clippy_enabled = clippy_tests_set || (!cap_lints_allow && (!no_deps || in_primary_package));
+        if clippy_enabled {
+            args.extend(clippy_args);
+        }
 
         if clippy_enabled {
-            args.extend(vec!["--cfg".into(), r#"feature="cargo-clippy""#.into()]);
-            if let Ok(extra_args) = env::var("CLIPPY_ARGS") {
-                args.extend(extra_args.split("__CLIPPY_HACKERY__").filter_map(|s| {
-                    if s.is_empty() {
-                        None
-                    } else {
-                        Some(s.to_string())
-                    }
-                }));
-            }
+            rustc_driver::RunCompiler::new(&args, &mut ClippyCallbacks { clippy_args_var }).run()
+        } else {
+            rustc_driver::RunCompiler::new(&args, &mut RustcCallbacks { clippy_args_var }).run()
         }
-        let mut clippy = ClippyCallbacks;
-        let mut default = DefaultCallbacks;
-        let callbacks: &mut (dyn rustc_driver::Callbacks + Send) =
-            if clippy_enabled { &mut clippy } else { &mut default };
-        rustc_driver::RunCompiler::new(&args, callbacks).run()
     }))
 }