about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorDavid Wood <david.wood@huawei.com>2022-07-25 13:02:39 +0100
committerDavid Wood <david.wood@huawei.com>2022-07-27 11:24:27 +0100
commit7bab769b58db292721ddcb73cc6a7e56cb2b08ab (patch)
tree9eb60f7c5aade2fca70d32ce361d88bea0d823c9 /src
parentf5e005f0ca0b6fbc427315fa7e6943f4b738e12d (diff)
downloadrust-7bab769b58db292721ddcb73cc6a7e56cb2b08ab.tar.gz
rust-7bab769b58db292721ddcb73cc6a7e56cb2b08ab.zip
lint: add bad opt access internal lint
Some command-line options accessible through `sess.opts` are best
accessed through wrapper functions on `Session`, `TyCtxt` or otherwise,
rather than through field access on the option struct in the `Session`.

Adds a new lint which triggers on those options that should be accessed
through a wrapper function so that this is prohibited. Options are
annotated with a new attribute `rustc_lint_opt_deny_field_access` which
can specify the error message (i.e. "use this other function instead")
to be emitted.

A simpler alternative would be to simply rename the options in the
option type so that it is clear they should not be used, however this
doesn't prevent uses, just discourages them. Another alternative would
be to make the option fields private, and adding accessor functions on
the option types, however the wrapper functions sometimes rely on
additional state from `Session` or `TyCtxt` which wouldn't be available
in an function on the option type, so the accessor would simply make the
field available and its use would be discouraged too.

Signed-off-by: David Wood <david.wood@huawei.com>
Diffstat (limited to 'src')
-rw-r--r--src/test/ui-fulldeps/internal-lints/bad_opt_access.rs22
-rw-r--r--src/test/ui-fulldeps/internal-lints/bad_opt_access.stderr20
-rw-r--r--src/tools/clippy/src/driver.rs2
3 files changed, 44 insertions, 0 deletions
diff --git a/src/test/ui-fulldeps/internal-lints/bad_opt_access.rs b/src/test/ui-fulldeps/internal-lints/bad_opt_access.rs
new file mode 100644
index 00000000000..d6bd6945e15
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/bad_opt_access.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Z unstable-options
+
+// Test that accessing command line options by field access triggers a lint for those fields
+// that have wrapper functions which should be used.
+
+#![crate_type = "lib"]
+#![feature(rustc_private)]
+#![deny(rustc::bad_opt_access)]
+
+extern crate rustc_session;
+use rustc_session::Session;
+
+pub fn access_bad_option(sess: Session) {
+    let _ = sess.opts.cg.split_debuginfo;
+    //~^ ERROR use `Session::split_debuginfo` instead of this field
+
+    let _ = sess.opts.crate_types;
+    //~^ ERROR use `Session::crate_types` instead of this field
+
+    let _ = sess.opts.crate_name;
+    // okay!
+}
diff --git a/src/test/ui-fulldeps/internal-lints/bad_opt_access.stderr b/src/test/ui-fulldeps/internal-lints/bad_opt_access.stderr
new file mode 100644
index 00000000000..e4145bff8be
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/bad_opt_access.stderr
@@ -0,0 +1,20 @@
+error: use `Session::split_debuginfo` instead of this field
+  --> $DIR/bad_opt_access.rs:14:13
+   |
+LL |     let _ = sess.opts.cg.split_debuginfo;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/bad_opt_access.rs:8:9
+   |
+LL | #![deny(rustc::bad_opt_access)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+error: use `Session::crate_types` instead of this field
+  --> $DIR/bad_opt_access.rs:17:13
+   |
+LL |     let _ = sess.opts.crate_types;
+   |             ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index c219c7de830..c1ec2bd5bd6 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -94,6 +94,8 @@ struct ClippyCallbacks {
 }
 
 impl rustc_driver::Callbacks for ClippyCallbacks {
+    // JUSTIFICATION: necessary in clippy driver to set `mir_opt_level`
+    #[cfg_attr(not(bootstrap), allow(rustc::bad_opt_access))]
     fn config(&mut self, config: &mut interface::Config) {
         let previous = config.register_lints.take();
         let clippy_args_var = self.clippy_args_var.take();