From 75b15c68f81094ad6f1da6f29bd42a1197585257 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Thu, 24 Feb 2022 14:10:41 -0500 Subject: [PATCH 1/5] don't ice when an extern static is too big --- compiler/rustc_typeck/src/check/check.rs | 29 +++++++++++-- .../ui/extern/extern-static-size-overflow.rs | 43 +++++++++++++++++++ .../extern/extern-static-size-overflow.stderr | 20 +++++++++ 3 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/extern/extern-static-size-overflow.rs create mode 100644 src/test/ui/extern/extern-static-size-overflow.stderr diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 30ae382de4278..158c3e261b8f1 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}; @@ -415,10 +415,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/test/ui/extern/extern-static-size-overflow.rs b/src/test/ui/extern/extern-static-size-overflow.rs new file mode 100644 index 0000000000000..30a0c44546686 --- /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 0000000000000..f5173feec75d4 --- /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 + From 97059397caa797cd9a56585d43c2ee873baf9cde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20BRANSTETT?= Date: Sat, 19 Feb 2022 14:31:20 +0100 Subject: [PATCH 2/5] Wire up --check-cfg to rustdoc --- src/librustdoc/config.rs | 5 +++++ src/librustdoc/core.rs | 4 +++- src/librustdoc/doctest.rs | 8 +++++++- src/librustdoc/lib.rs | 1 + src/test/rustdoc-ui/check-cfg-test.rs | 12 ++++++++++++ src/test/rustdoc-ui/check-cfg-test.stderr | 11 +++++++++++ src/test/rustdoc-ui/check-cfg-test.stdout | 6 ++++++ src/test/rustdoc-ui/check-cfg-unstable.rs | 2 ++ src/test/rustdoc-ui/check-cfg-unstable.stderr | 2 ++ src/test/rustdoc-ui/check-cfg.rs | 7 +++++++ src/test/rustdoc-ui/check-cfg.stderr | 10 ++++++++++ 11 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 src/test/rustdoc-ui/check-cfg-test.rs create mode 100644 src/test/rustdoc-ui/check-cfg-test.stderr create mode 100644 src/test/rustdoc-ui/check-cfg-test.stdout create mode 100644 src/test/rustdoc-ui/check-cfg-unstable.rs create mode 100644 src/test/rustdoc-ui/check-cfg-unstable.stderr create mode 100644 src/test/rustdoc-ui/check-cfg.rs create mode 100644 src/test/rustdoc-ui/check-cfg.stderr diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 6e483d27f336b..93f90b90e0a0d 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -80,6 +80,8 @@ crate struct Options { crate extern_strs: Vec, /// List of `cfg` flags to hand to the compiler. Always includes `rustdoc`. crate cfgs: Vec, + /// List of check cfg flags to hand to the compiler. + crate check_cfgs: Vec, /// 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 c2f6f7aea757e..2b82575f71083 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 5ccc3dabe83b7..cc68defd5a957 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 7eff725989cc9..365934e91a110 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -259,6 +259,7 @@ fn opts() -> Vec { 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 0000000000000..626cc838704b3 --- /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 0000000000000..dc25205da772e --- /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 0000000000000..b7db49bcfa87a --- /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 0000000000000..5c500ce6ce082 --- /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 0000000000000..9b27c2bc058a7 --- /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 0000000000000..fa8789ad3ede4 --- /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 0000000000000..1db8e1d91c249 --- /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 + From a31ae159bc29ae26396160b1f3cb0fb358b4eae7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20BRANSTETT?= Date: Sun, 20 Feb 2022 17:13:38 +0100 Subject: [PATCH 3/5] Add documentation for `--check-cfg` in rustdoc book --- src/doc/rustdoc/src/unstable-features.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index c7fd5ed6fcb2e..141d5d2d2b2d0 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`. From bbe3447313b52db1c0162061a77948e4da275809 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 25 Feb 2022 11:30:16 +0000 Subject: [PATCH 4/5] Fix debug_assert in unused lint pass This fixes a debug assertion in the unused lint pass. As a side effect, this also improves the span generated for tuples in the `unused_must_use` lint. --- compiler/rustc_lint/src/unused.rs | 12 ++++++------ src/test/ui/lint/unused/must_use-array.stderr | 2 +- src/test/ui/lint/unused/must_use-trait.stderr | 4 ++-- src/test/ui/lint/unused/must_use-tuple.stderr | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index b71ffa43d85dc..16d222f68a321 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/src/test/ui/lint/unused/must_use-array.stderr b/src/test/ui/lint/unused/must_use-array.stderr index c42223b519851..45a5317fccc6e 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 11555d80825a4..a42eb8841789d 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 0532d89e039eb..e5709a5f0af5a 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 From eb104bb8776d2c21d08a3f13b174ecf9d388e30b Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Fri, 25 Feb 2022 13:32:21 -0500 Subject: [PATCH 5/5] Add missing item to release notes --- RELEASES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index b96eb18cf86d8..971a63b240f3e 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)