about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--RELEASES.md2
-rw-r--r--compiler/rustc_lint/src/unused.rs12
-rw-r--r--compiler/rustc_typeck/src/check/check.rs29
-rw-r--r--src/doc/rustdoc/src/unstable-features.md14
-rw-r--r--src/librustdoc/config.rs5
-rw-r--r--src/librustdoc/core.rs4
-rw-r--r--src/librustdoc/doctest.rs8
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/test/rustdoc-ui/check-cfg-test.rs12
-rw-r--r--src/test/rustdoc-ui/check-cfg-test.stderr11
-rw-r--r--src/test/rustdoc-ui/check-cfg-test.stdout6
-rw-r--r--src/test/rustdoc-ui/check-cfg-unstable.rs2
-rw-r--r--src/test/rustdoc-ui/check-cfg-unstable.stderr2
-rw-r--r--src/test/rustdoc-ui/check-cfg.rs7
-rw-r--r--src/test/rustdoc-ui/check-cfg.stderr10
-rw-r--r--src/test/ui/extern/extern-static-size-overflow.rs43
-rw-r--r--src/test/ui/extern/extern-static-size-overflow.stderr20
-rw-r--r--src/test/ui/lint/unused/must_use-array.stderr2
-rw-r--r--src/test/ui/lint/unused/must_use-trait.stderr4
-rw-r--r--src/test/ui/lint/unused/must_use-tuple.stderr6
20 files changed, 182 insertions, 18 deletions
diff --git a/RELEASES.md b/RELEASES.md
index b96eb18cf86..971a63b240f 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -58,6 +58,7 @@ Stabilized APIs
 - [`NonZeroU32::is_power_of_two`][is_power_of_two32]
 - [`NonZeroU64::is_power_of_two`][is_power_of_two64]
 - [`NonZeroU128::is_power_of_two`][is_power_of_two128]
+- [`NonZeroUsize::is_power_of_two`][is_power_of_two_usize]
 - [`DoubleEndedIterator for ToLowercase`][lowercase]
 - [`DoubleEndedIterator for ToUppercase`][uppercase]
 - [`TryFrom<&mut [T]> for [T; N]`][tryfrom_ref_arr]
@@ -178,6 +179,7 @@ and related tools.
 [is_power_of_two32]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU32.html#method.is_power_of_two
 [is_power_of_two64]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU64.html#method.is_power_of_two
 [is_power_of_two128]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU128.html#method.is_power_of_two
+[is_power_of_two_usize]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroUsize.html#method.is_power_of_two
 [stdarch/1266]: https://github.com/rust-lang/stdarch/pull/1266
 
 Version 1.58.1 (2022-01-19)
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index b71ffa43d85..16d222f68a3 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -240,17 +240,17 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                 }
                 ty::Tuple(ref tys) => {
                     let mut has_emitted = false;
-                    let spans = if let hir::ExprKind::Tup(comps) = &expr.kind {
+                    let comps = if let hir::ExprKind::Tup(comps) = expr.kind {
                         debug_assert_eq!(comps.len(), tys.len());
-                        comps.iter().map(|e| e.span).collect()
+                        comps
                     } else {
-                        vec![]
+                        &[]
                     };
                     for (i, ty) in tys.iter().enumerate() {
                         let descr_post = &format!(" in tuple element {}", i);
-                        let span = *spans.get(i).unwrap_or(&span);
-                        if check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, plural_len)
-                        {
+                        let e = comps.get(i).unwrap_or(expr);
+                        let span = e.span;
+                        if check_must_use_ty(cx, ty, e, span, descr_pre, descr_post, plural_len) {
                             has_emitted = true;
                         }
                     }
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 7dca95ebdd6..8ed87497f1b 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -14,7 +14,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
 use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::layout::MAX_SIMD_LANES;
+use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
 use rustc_middle::ty::{self, OpaqueTypeKey, ParamEnv, Ty, TyCtxt};
@@ -417,10 +417,31 @@ fn check_static_inhabited<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Spa
     // have UB during initialization if they are uninhabited, but there also seems to be no good
     // reason to allow any statics to be uninhabited.
     let ty = tcx.type_of(def_id);
-    let Ok(layout) = tcx.layout_of(ParamEnv::reveal_all().and(ty)) else {
+    let layout = match tcx.layout_of(ParamEnv::reveal_all().and(ty)) {
+        Ok(l) => l,
+        // Foreign statics that overflow their allowed size should emit an error
+        Err(LayoutError::SizeOverflow(_))
+            if {
+                let node = tcx.hir().get_by_def_id(def_id);
+                matches!(
+                    node,
+                    hir::Node::ForeignItem(hir::ForeignItem {
+                        kind: hir::ForeignItemKind::Static(..),
+                        ..
+                    })
+                )
+            } =>
+        {
+            tcx.sess
+                .struct_span_err(span, "extern static is too large for the current architecture")
+                .emit();
+            return;
+        }
         // Generic statics are rejected, but we still reach this case.
-        tcx.sess.delay_span_bug(span, "generic static must be rejected");
-        return;
+        Err(e) => {
+            tcx.sess.delay_span_bug(span, &e.to_string());
+            return;
+        }
     };
     if layout.abi.is_uninhabited() {
         tcx.struct_span_lint_hir(
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index c7fd5ed6fcb..141d5d2d2b2 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -512,3 +512,17 @@ crate being documented (`foobar`) and a path to output the calls
 
 To scrape examples from test code, e.g. functions marked `#[test]`, then
 add the `--scrape-tests` flag.
+
+### `--check-cfg`: check configuration flags
+
+This flag accepts the same values as `rustc --check-cfg`, and uses it to check configuration flags.
+
+Using this flag looks like this:
+
+```bash
+$ rustdoc src/lib.rs -Z unstable-options \
+    --check-cfg='names()' --check-cfg='values(feature, "foo", "bar")'
+```
+
+The example above check every well known names (`target_os`, `doc`, `test`, ... via `names()`)
+and check the values of `feature`: `foo` and `bar`.
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 6e483d27f33..93f90b90e0a 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -80,6 +80,8 @@ crate struct Options {
     crate extern_strs: Vec<String>,
     /// List of `cfg` flags to hand to the compiler. Always includes `rustdoc`.
     crate cfgs: Vec<String>,
+    /// List of check cfg flags to hand to the compiler.
+    crate check_cfgs: Vec<String>,
     /// Codegen options to hand to the compiler.
     crate codegen_options: CodegenOptions,
     /// Codegen options strings to hand to the compiler.
@@ -172,6 +174,7 @@ impl fmt::Debug for Options {
             .field("libs", &self.libs)
             .field("externs", &FmtExterns(&self.externs))
             .field("cfgs", &self.cfgs)
+            .field("check-cfgs", &self.check_cfgs)
             .field("codegen_options", &"...")
             .field("debugging_options", &"...")
             .field("target", &self.target)
@@ -506,6 +509,7 @@ impl Options {
         };
 
         let cfgs = matches.opt_strs("cfg");
+        let check_cfgs = matches.opt_strs("check-cfg");
 
         let extension_css = matches.opt_str("e").map(|s| PathBuf::from(&s));
 
@@ -677,6 +681,7 @@ impl Options {
             externs,
             extern_strs,
             cfgs,
+            check_cfgs,
             codegen_options,
             codegen_options_strs,
             debugging_opts,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index c2f6f7aea75..2b82575f710 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -192,6 +192,7 @@ crate fn create_config(
         libs,
         externs,
         mut cfgs,
+        check_cfgs,
         codegen_options,
         debugging_opts,
         target,
@@ -219,6 +220,7 @@ crate fn create_config(
         // these are definitely not part of rustdoc, but we want to warn on them anyway.
         rustc_lint::builtin::RENAMED_AND_REMOVED_LINTS.name.to_string(),
         rustc_lint::builtin::UNKNOWN_LINTS.name.to_string(),
+        rustc_lint::builtin::UNEXPECTED_CFGS.name.to_string(),
     ];
     lints_to_show.extend(crate::lint::RUSTDOC_LINTS.iter().map(|lint| lint.name.to_string()));
 
@@ -253,7 +255,7 @@ crate fn create_config(
     interface::Config {
         opts: sessopts,
         crate_cfg: interface::parse_cfgspecs(cfgs),
-        crate_check_cfg: interface::parse_check_cfg(vec![]),
+        crate_check_cfg: interface::parse_check_cfg(check_cfgs),
         input,
         input_path: cpath,
         output_file: None,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index eabf10eda97..5b6c7626239 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -91,7 +91,7 @@ crate fn run(options: RustdocOptions) -> Result<(), ErrorReported> {
     let config = interface::Config {
         opts: sessopts,
         crate_cfg: interface::parse_cfgspecs(cfgs),
-        crate_check_cfg: interface::parse_check_cfg(vec![]),
+        crate_check_cfg: interface::parse_check_cfg(options.check_cfgs.clone()),
         input,
         input_path: None,
         output_file: None,
@@ -321,6 +321,12 @@ fn run_test(
     for cfg in &rustdoc_options.cfgs {
         compiler.arg("--cfg").arg(&cfg);
     }
+    if !rustdoc_options.check_cfgs.is_empty() {
+        compiler.arg("-Z").arg("unstable-options");
+        for check_cfg in &rustdoc_options.check_cfgs {
+            compiler.arg("--check-cfg").arg(&check_cfg);
+        }
+    }
     if let Some(sysroot) = rustdoc_options.maybe_sysroot {
         compiler.arg("--sysroot").arg(sysroot);
     }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index f4cb9352464..5c8a8fb80f1 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -260,6 +260,7 @@ fn opts() -> Vec<RustcOptGroup> {
             o.optmulti("L", "library-path", "directory to add to crate search path", "DIR")
         }),
         stable("cfg", |o| o.optmulti("", "cfg", "pass a --cfg to rustc", "")),
+        unstable("check-cfg", |o| o.optmulti("", "check-cfg", "pass a --check-cfg to rustc", "")),
         stable("extern", |o| o.optmulti("", "extern", "pass an --extern to rustc", "NAME[=PATH]")),
         unstable("extern-html-root-url", |o| {
             o.optmulti(
diff --git a/src/test/rustdoc-ui/check-cfg-test.rs b/src/test/rustdoc-ui/check-cfg-test.rs
new file mode 100644
index 00000000000..626cc838704
--- /dev/null
+++ b/src/test/rustdoc-ui/check-cfg-test.rs
@@ -0,0 +1,12 @@
+// check-pass
+// compile-flags: --test --nocapture --check-cfg=values(feature,"test") -Z unstable-options
+// normalize-stderr-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// The doctest will produce a warning because feature invalid is unexpected
+/// ```
+/// #[cfg(feature = "invalid")]
+/// assert!(false);
+/// ```
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/check-cfg-test.stderr b/src/test/rustdoc-ui/check-cfg-test.stderr
new file mode 100644
index 00000000000..dc25205da77
--- /dev/null
+++ b/src/test/rustdoc-ui/check-cfg-test.stderr
@@ -0,0 +1,11 @@
+warning: unexpected `cfg` condition value
+  --> $DIR/check-cfg-test.rs:9:7
+   |
+LL | #[cfg(feature = "invalid")]
+   |       ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unexpected_cfgs)]` on by default
+   = note: expected values for `feature` are: test
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/check-cfg-test.stdout b/src/test/rustdoc-ui/check-cfg-test.stdout
new file mode 100644
index 00000000000..b7db49bcfa8
--- /dev/null
+++ b/src/test/rustdoc-ui/check-cfg-test.stdout
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/check-cfg-test.rs - Foo (line 8) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/check-cfg-unstable.rs b/src/test/rustdoc-ui/check-cfg-unstable.rs
new file mode 100644
index 00000000000..5c500ce6ce0
--- /dev/null
+++ b/src/test/rustdoc-ui/check-cfg-unstable.rs
@@ -0,0 +1,2 @@
+// check-fail
+// compile-flags: --check-cfg=names()
diff --git a/src/test/rustdoc-ui/check-cfg-unstable.stderr b/src/test/rustdoc-ui/check-cfg-unstable.stderr
new file mode 100644
index 00000000000..9b27c2bc058
--- /dev/null
+++ b/src/test/rustdoc-ui/check-cfg-unstable.stderr
@@ -0,0 +1,2 @@
+error: the `-Z unstable-options` flag must also be passed to enable the flag `check-cfg`
+
diff --git a/src/test/rustdoc-ui/check-cfg.rs b/src/test/rustdoc-ui/check-cfg.rs
new file mode 100644
index 00000000000..fa8789ad3ed
--- /dev/null
+++ b/src/test/rustdoc-ui/check-cfg.rs
@@ -0,0 +1,7 @@
+// check-pass
+// compile-flags: --check-cfg=names() -Z unstable-options
+
+/// uniz is nor a builtin nor pass as arguments so is unexpected
+#[cfg(uniz)]
+//~^ WARNING unexpected `cfg` condition name
+pub struct Bar;
diff --git a/src/test/rustdoc-ui/check-cfg.stderr b/src/test/rustdoc-ui/check-cfg.stderr
new file mode 100644
index 00000000000..1db8e1d91c2
--- /dev/null
+++ b/src/test/rustdoc-ui/check-cfg.stderr
@@ -0,0 +1,10 @@
+warning: unexpected `cfg` condition name
+  --> $DIR/check-cfg.rs:5:7
+   |
+LL | #[cfg(uniz)]
+   |       ^^^^ help: did you mean: `unix`
+   |
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/extern/extern-static-size-overflow.rs b/src/test/ui/extern/extern-static-size-overflow.rs
new file mode 100644
index 00000000000..30a0c445466
--- /dev/null
+++ b/src/test/ui/extern/extern-static-size-overflow.rs
@@ -0,0 +1,43 @@
+#[repr(C)]
+struct ReallyBig {
+    _a: [u8; usize::MAX],
+}
+
+// The limit for "too big for the current architecture" is dependent on the target pointer size
+// however it's artifically limited on 64 bits
+// logic copied from rustc_target::abi::TargetDataLayout::obj_size_bound()
+const fn max_size() -> usize {
+    #[cfg(target_pointer_width = "16")]
+    {
+        1 << 15
+    }
+
+    #[cfg(target_pointer_width = "32")]
+    {
+        1 << 31
+    }
+
+    #[cfg(target_pointer_width = "64")]
+    {
+        1 << 47
+    }
+
+    #[cfg(not(any(
+        target_pointer_width = "16",
+        target_pointer_width = "32",
+        target_pointer_width = "64"
+    )))]
+    {
+        isize::MAX as usize
+    }
+}
+
+extern "C" {
+    static FOO: [u8; 1];
+    static BAR: [u8; max_size() - 1];
+    static BAZ: [u8; max_size()]; //~ ERROR extern static is too large
+    static UWU: [usize; usize::MAX]; //~ ERROR extern static is too large
+    static A: ReallyBig; //~ ERROR extern static is too large
+}
+
+fn main() {}
diff --git a/src/test/ui/extern/extern-static-size-overflow.stderr b/src/test/ui/extern/extern-static-size-overflow.stderr
new file mode 100644
index 00000000000..f5173feec75
--- /dev/null
+++ b/src/test/ui/extern/extern-static-size-overflow.stderr
@@ -0,0 +1,20 @@
+error: extern static is too large for the current architecture
+  --> $DIR/extern-static-size-overflow.rs:38:5
+   |
+LL |     static BAZ: [u8; max_size()];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: extern static is too large for the current architecture
+  --> $DIR/extern-static-size-overflow.rs:39:5
+   |
+LL |     static UWU: [usize; usize::MAX];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: extern static is too large for the current architecture
+  --> $DIR/extern-static-size-overflow.rs:40:5
+   |
+LL |     static A: ReallyBig;
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/lint/unused/must_use-array.stderr b/src/test/ui/lint/unused/must_use-array.stderr
index c42223b5198..45a5317fccc 100644
--- a/src/test/ui/lint/unused/must_use-array.stderr
+++ b/src/test/ui/lint/unused/must_use-array.stderr
@@ -32,7 +32,7 @@ error: unused array of boxed `T` trait objects in tuple element 1 that must be u
   --> $DIR/must_use-array.rs:43:5
    |
 LL |     impl_array();
-   |     ^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^
 
 error: unused array of arrays of arrays of `S` that must be used
   --> $DIR/must_use-array.rs:45:5
diff --git a/src/test/ui/lint/unused/must_use-trait.stderr b/src/test/ui/lint/unused/must_use-trait.stderr
index 11555d80825..a42eb884178 100644
--- a/src/test/ui/lint/unused/must_use-trait.stderr
+++ b/src/test/ui/lint/unused/must_use-trait.stderr
@@ -26,13 +26,13 @@ error: unused boxed `Critical` trait object in tuple element 1 that must be used
   --> $DIR/must_use-trait.rs:37:5
    |
 LL |     get_critical_tuple();
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error: unused implementer of `Critical` in tuple element 2 that must be used
   --> $DIR/must_use-trait.rs:37:5
    |
 LL |     get_critical_tuple();
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/lint/unused/must_use-tuple.stderr b/src/test/ui/lint/unused/must_use-tuple.stderr
index 0532d89e039..e5709a5f0af 100644
--- a/src/test/ui/lint/unused/must_use-tuple.stderr
+++ b/src/test/ui/lint/unused/must_use-tuple.stderr
@@ -31,15 +31,15 @@ error: unused `Result` in tuple element 0 that must be used
   --> $DIR/must_use-tuple.rs:14:5
    |
 LL |     foo();
-   |     ^^^^^^
+   |     ^^^^^
    |
    = note: this `Result` may be an `Err` variant, which should be handled
 
 error: unused `Result` in tuple element 0 that must be used
-  --> $DIR/must_use-tuple.rs:16:6
+  --> $DIR/must_use-tuple.rs:16:7
    |
 LL |     ((Err::<(), ()>(()), ()), ());
-   |      ^^^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^
    |
    = note: this `Result` may be an `Err` variant, which should be handled