From 0a42a540c603846aa22f29f378a61a64c9d4383e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Wed, 7 Feb 2024 16:21:16 +0100 Subject: [PATCH 01/20] Make `io::BorrowedCursor::advance` safe This also keeps the old `advance` method under `advance_unchecked` name. This makes pattern like `std::io::default_read_buf` safe to write. --- library/core/src/io/borrowed_buf.rs | 22 +++++++++++++++++++++- library/core/tests/io/borrowed_buf.rs | 16 ++++------------ library/std/src/io/mod.rs | 12 ++---------- library/std/src/io/tests.rs | 2 +- library/std/src/io/util.rs | 2 +- library/std/src/sys/pal/hermit/net.rs | 2 +- library/std/src/sys/pal/solid/fs.rs | 2 +- library/std/src/sys/pal/solid/net.rs | 2 +- library/std/src/sys/pal/unix/fd.rs | 2 +- library/std/src/sys/pal/unix/net.rs | 2 +- library/std/src/sys/pal/wasi/fd.rs | 2 +- library/std/src/sys/pal/windows/handle.rs | 2 +- library/std/src/sys/pal/windows/net.rs | 2 +- library/std/src/sys/pal/windows/pipe.rs | 2 +- 14 files changed, 38 insertions(+), 34 deletions(-) diff --git a/library/core/src/io/borrowed_buf.rs b/library/core/src/io/borrowed_buf.rs index fe25cac280fe3..161bb4b6a1fc7 100644 --- a/library/core/src/io/borrowed_buf.rs +++ b/library/core/src/io/borrowed_buf.rs @@ -233,6 +233,26 @@ impl<'a> BorrowedCursor<'a> { &mut self.buf.buf[self.buf.filled..] } + /// Advance the cursor by asserting that `n` bytes have been filled. + /// + /// After advancing, the `n` bytes are no longer accessible via the cursor and can only be + /// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements + /// and its unfilled portion (and the capacity of this cursor) shrinks by `n` elements. + /// + /// If less than `n` bytes initialized (by the cursor's point of view), `set_init` should be + /// called first. + /// + /// # Panics + /// + /// Panics if there are less than `n` bytes initialized. + #[inline] + pub fn advance(&mut self, n: usize) -> &mut Self { + assert!(self.buf.init >= self.buf.filled + n); + + self.buf.filled += n; + self + } + /// Advance the cursor by asserting that `n` bytes have been filled. /// /// After advancing, the `n` bytes are no longer accessible via the cursor and can only be @@ -244,7 +264,7 @@ impl<'a> BorrowedCursor<'a> { /// The caller must ensure that the first `n` bytes of the cursor have been properly /// initialised. #[inline] - pub unsafe fn advance(&mut self, n: usize) -> &mut Self { + pub unsafe fn advance_unchecked(&mut self, n: usize) -> &mut Self { self.buf.filled += n; self.buf.init = cmp::max(self.buf.init, self.buf.filled); self diff --git a/library/core/tests/io/borrowed_buf.rs b/library/core/tests/io/borrowed_buf.rs index 69511e49acdbc..a5dd4e525777a 100644 --- a/library/core/tests/io/borrowed_buf.rs +++ b/library/core/tests/io/borrowed_buf.rs @@ -40,9 +40,7 @@ fn advance_filled() { let buf: &mut [_] = &mut [0; 16]; let mut rbuf: BorrowedBuf<'_> = buf.into(); - unsafe { - rbuf.unfilled().advance(1); - } + rbuf.unfilled().advance(1); assert_eq!(rbuf.filled().len(), 1); assert_eq!(rbuf.unfilled().capacity(), 15); @@ -53,9 +51,7 @@ fn clear() { let buf: &mut [_] = &mut [255; 16]; let mut rbuf: BorrowedBuf<'_> = buf.into(); - unsafe { - rbuf.unfilled().advance(16); - } + rbuf.unfilled().advance(16); assert_eq!(rbuf.filled().len(), 16); assert_eq!(rbuf.unfilled().capacity(), 0); @@ -79,9 +75,7 @@ fn set_init() { assert_eq!(rbuf.init_len(), 8); - unsafe { - rbuf.unfilled().advance(4); - } + rbuf.unfilled().advance(4); unsafe { rbuf.set_init(2); @@ -153,9 +147,7 @@ fn cursor_set_init() { assert_eq!(rbuf.unfilled().uninit_mut().len(), 8); assert_eq!(unsafe { rbuf.unfilled().as_mut() }.len(), 16); - unsafe { - rbuf.unfilled().advance(4); - } + rbuf.unfilled().advance(4); unsafe { rbuf.unfilled().set_init(2); diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index a238e74ed95cf..f842a0b6d554e 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -578,15 +578,7 @@ where F: FnOnce(&mut [u8]) -> Result, { let n = read(cursor.ensure_init().init_mut())?; - assert!( - n <= cursor.capacity(), - "read should not return more bytes than there is capacity for in the read buffer" - ); - unsafe { - // SAFETY: we initialised using `ensure_init` so there is no uninit data to advance to - // and we have checked that the read amount is not over capacity (see #120603) - cursor.advance(n); - } + cursor.advance(n); Ok(()) } @@ -2915,7 +2907,7 @@ impl Read for Take { unsafe { // SAFETY: filled bytes have been filled and therefore initialized - buf.advance(filled); + buf.advance_unchecked(filled); // SAFETY: new_init bytes of buf's unfilled buffer have been initialized buf.set_init(new_init); } diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index 33e9d8efed511..fd7e51688cdeb 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -655,7 +655,7 @@ fn bench_take_read_buf(b: &mut test::Bencher) { // Issue #120603 #[test] -#[should_panic = "read should not return more bytes than there is capacity for in the read buffer"] +#[should_panic] fn read_buf_broken_read() { struct MalformedRead; diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index a04bc4811460b..16eaed15e720c 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -198,7 +198,7 @@ impl Read for Repeat { // SAFETY: the entire unfilled portion of buf has been initialized unsafe { - buf.advance(remaining); + buf.advance_unchecked(remaining); } Ok(()) diff --git a/library/std/src/sys/pal/hermit/net.rs b/library/std/src/sys/pal/hermit/net.rs index 3cf63fccf2e71..871a2ccdfa49c 100644 --- a/library/std/src/sys/pal/hermit/net.rs +++ b/library/std/src/sys/pal/hermit/net.rs @@ -156,7 +156,7 @@ impl Socket { ) })?; unsafe { - buf.advance(ret as usize); + buf.advance_unchecked(ret as usize); } Ok(()) } diff --git a/library/std/src/sys/pal/solid/fs.rs b/library/std/src/sys/pal/solid/fs.rs index 6c66b93a3e1a3..a6c1336109ad7 100644 --- a/library/std/src/sys/pal/solid/fs.rs +++ b/library/std/src/sys/pal/solid/fs.rs @@ -388,7 +388,7 @@ impl File { // Safety: `num_bytes_read` bytes were written to the unfilled // portion of the buffer - cursor.advance(num_bytes_read); + cursor.advance_unchecked(num_bytes_read); Ok(()) } diff --git a/library/std/src/sys/pal/solid/net.rs b/library/std/src/sys/pal/solid/net.rs index 1c310648a3db5..6ea874e509e20 100644 --- a/library/std/src/sys/pal/solid/net.rs +++ b/library/std/src/sys/pal/solid/net.rs @@ -209,7 +209,7 @@ impl Socket { netc::recv(self.as_raw_fd(), buf.as_mut().as_mut_ptr().cast(), buf.capacity(), flags) })?; unsafe { - buf.advance(ret as usize); + buf.advance_unchecked(ret as usize); } Ok(()) } diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs index bf1fb3123c4ce..a1c0321876fa8 100644 --- a/library/std/src/sys/pal/unix/fd.rs +++ b/library/std/src/sys/pal/unix/fd.rs @@ -161,7 +161,7 @@ impl FileDesc { // Safety: `ret` bytes were written to the initialized portion of the buffer unsafe { - cursor.advance(ret as usize); + cursor.advance_unchecked(ret as usize); } Ok(()) } diff --git a/library/std/src/sys/pal/unix/net.rs b/library/std/src/sys/pal/unix/net.rs index 8f537de7026f5..1b6a6bb2c5c77 100644 --- a/library/std/src/sys/pal/unix/net.rs +++ b/library/std/src/sys/pal/unix/net.rs @@ -272,7 +272,7 @@ impl Socket { ) })?; unsafe { - buf.advance(ret as usize); + buf.advance_unchecked(ret as usize); } Ok(()) } diff --git a/library/std/src/sys/pal/wasi/fd.rs b/library/std/src/sys/pal/wasi/fd.rs index d7295a799daab..8966e4b80ad37 100644 --- a/library/std/src/sys/pal/wasi/fd.rs +++ b/library/std/src/sys/pal/wasi/fd.rs @@ -60,7 +60,7 @@ impl WasiFd { }]; match wasi::fd_read(self.as_raw_fd() as wasi::Fd, &bufs) { Ok(n) => { - buf.advance(n); + buf.advance_unchecked(n); Ok(()) } Err(e) => Err(err2io(e)), diff --git a/library/std/src/sys/pal/windows/handle.rs b/library/std/src/sys/pal/windows/handle.rs index c4495f81a5a3a..3f85bb0a099a9 100644 --- a/library/std/src/sys/pal/windows/handle.rs +++ b/library/std/src/sys/pal/windows/handle.rs @@ -121,7 +121,7 @@ impl Handle { Ok(read) => { // Safety: `read` bytes were written to the initialized portion of the buffer unsafe { - cursor.advance(read); + cursor.advance_unchecked(read); } Ok(()) } diff --git a/library/std/src/sys/pal/windows/net.rs b/library/std/src/sys/pal/windows/net.rs index c34e01e000aca..e37fbe9ef83e4 100644 --- a/library/std/src/sys/pal/windows/net.rs +++ b/library/std/src/sys/pal/windows/net.rs @@ -234,7 +234,7 @@ impl Socket { } } _ => { - unsafe { buf.advance(result as usize) }; + unsafe { buf.advance_unchecked(result as usize) }; Ok(()) } } diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs index 7624e746f5c89..fd10df82d8b47 100644 --- a/library/std/src/sys/pal/windows/pipe.rs +++ b/library/std/src/sys/pal/windows/pipe.rs @@ -273,7 +273,7 @@ impl AnonPipe { Err(e) => Err(e), Ok(n) => { unsafe { - buf.advance(n); + buf.advance_unchecked(n); } Ok(()) } From 01fa7209d597c770a51c44839a97d2731419392c Mon Sep 17 00:00:00 2001 From: Marcondiro <46560192+Marcondiro@users.noreply.github.com> Date: Thu, 8 Feb 2024 12:24:27 +0100 Subject: [PATCH 02/20] Bump Unicode to version 15.1.0, regenerate tables --- library/core/src/unicode/unicode_data.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index b25e9df286808..dd2ad9a58f679 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -99,21 +99,21 @@ fn skip_search( offset_idx % 2 == 1 } -pub const UNICODE_VERSION: (u8, u8, u8) = (15, 0, 0); +pub const UNICODE_VERSION: (u8, u8, u8) = (15, 1, 0); #[rustfmt::skip] pub mod alphabetic { - static SHORT_OFFSET_RUNS: [u32; 53] = [ + static SHORT_OFFSET_RUNS: [u32; 54] = [ 706, 33559113, 872420973, 952114966, 1161831606, 1310731264, 1314926597, 1394619392, 1444957632, 1447077005, 1451271693, 1459672996, 1648425216, 1658911342, 1661009214, 1707147904, 1793132343, 1887506048, 2040601600, 2392923872, 2481005466, 2504077200, 2514564144, 2520859648, 2527151687, 2529257472, 2531355193, 2533453376, 2564917240, 2596375766, 2600579056, 2606870819, 2621551356, 2642525184, 2644628480, 2665600678, 2743197440, 2791432848, 2841765072, 2850154464, 2854350336, 2887905584, 3026321408, - 3038947040, 3041048378, 3045248674, 3053644769, 3057842176, 3059939870, 3062038528, - 3064140619, 3066241968, 3071550384, + 3038947040, 3041048378, 3045248674, 3053644769, 3057839710, 3062036480, 3064134174, + 3066232832, 3068334923, 3070436272, 3075744688, ]; - static OFFSETS: [u8; 1465] = [ + static OFFSETS: [u8; 1467] = [ 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 42, 5, 1, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 2, 1, 6, 41, 39, 14, 1, 1, 1, 2, 1, 2, 1, 1, 8, 27, 4, 4, 29, 11, 5, 56, 1, 7, 14, 102, 1, 8, 4, 8, 4, 3, 10, @@ -167,7 +167,7 @@ pub mod alphabetic { 1, 2, 1, 15, 1, 197, 59, 68, 3, 1, 3, 1, 0, 4, 1, 27, 1, 2, 1, 1, 2, 1, 1, 10, 1, 4, 1, 1, 1, 1, 6, 1, 4, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 4, 1, 7, 1, 4, 1, 4, 1, 1, 1, 10, 1, 17, 5, 3, 1, 5, 1, 17, 0, 26, 6, 26, 6, 26, 0, 0, 32, - 0, 6, 222, 2, 0, 14, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 6, 222, 2, 0, 14, 0, 15, 0, 0, 0, 0, 0, 5, 0, 0, ]; pub fn lookup(c: char) -> bool { super::skip_search( From fffcb4c8771ad1a688bf9083d948769664d5fcb0 Mon Sep 17 00:00:00 2001 From: PizzasBear <43722034+PizzasBear@users.noreply.github.com> Date: Mon, 12 Feb 2024 16:00:15 +0200 Subject: [PATCH 03/20] Fix comment in core/src/str/validations.rs --- library/core/src/str/validations.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/str/validations.rs b/library/core/src/str/validations.rs index 2acef432f2063..a11d7fee8af0c 100644 --- a/library/core/src/str/validations.rs +++ b/library/core/src/str/validations.rs @@ -161,7 +161,7 @@ pub(super) const fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { // first E0 A0 80 last EF BF BF // excluding surrogates codepoints \u{d800} to \u{dfff} // ED A0 80 to ED BF BF - // 4-byte encoding is for codepoints \u{1000}0 to \u{10ff}ff + // 4-byte encoding is for codepoints \u{10000} to \u{10ffff} // first F0 90 80 80 last F4 8F BF BF // // Use the UTF-8 syntax from the RFC From 5233bc91da2f48f5bc79c688b5cfad846a8127da Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 14 Feb 2024 14:50:49 +1100 Subject: [PATCH 04/20] Add an `ErrorGuaranteed` to `ast::TyKind::Err`. This makes it more like `hir::TyKind::Err`, and avoids a `span_delayed_bug` call in `LoweringContext::lower_ty_direct`. It also requires adding `ast::TyKind::Dummy`, now that `ast::TyKind::Err` can't be used for that purpose in the absence of an error emission. There are a couple of cases that aren't as neat as I would have liked, marked with `FIXME` comments. --- compiler/rustc_ast/src/ast.rs | 6 +++-- compiler/rustc_ast/src/mut_visit.rs | 9 +++++-- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 3 ++- .../rustc_ast_passes/src/ast_validation.rs | 3 ++- compiler/rustc_ast_pretty/src/pprust/state.rs | 7 ++++- compiler/rustc_expand/src/base.rs | 9 ++++--- .../rustc_parse/src/parser/diagnostics.rs | 20 +++++++------- compiler/rustc_parse/src/parser/item.rs | 26 +++++++++++++++---- compiler/rustc_parse/src/parser/path.rs | 7 ++--- compiler/rustc_parse/src/parser/ty.rs | 10 ++++--- compiler/rustc_passes/src/hir_stats.rs | 5 ++-- .../clippy/clippy_utils/src/ast_utils.rs | 2 +- src/tools/rustfmt/src/types.rs | 2 +- 14 files changed, 75 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 098e2606a3be9..08fc8e3c6cca8 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2136,10 +2136,12 @@ pub enum TyKind { ImplicitSelf, /// A macro in the type position. MacCall(P), - /// Placeholder for a kind that has failed to be defined. - Err, /// Placeholder for a `va_list`. CVarArgs, + /// Sometimes we need a dummy value when no error has occurred. + Dummy, + /// Placeholder for a kind that has failed to be defined. + Err(ErrorGuaranteed), } impl TyKind { diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index d482ada170ee3..c42c41999732c 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -481,7 +481,12 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { let Ty { id, kind, span, tokens } = ty.deref_mut(); vis.visit_id(id); match kind { - TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err | TyKind::Never | TyKind::CVarArgs => {} + TyKind::Infer + | TyKind::ImplicitSelf + | TyKind::Err(_) + | TyKind::Dummy + | TyKind::Never + | TyKind::CVarArgs => {} TyKind::Slice(ty) => vis.visit_ty(ty), TyKind::Ptr(mt) => vis.visit_mt(mt), TyKind::Ref(lt, mt) => { @@ -1649,7 +1654,7 @@ impl DummyAstNode for Ty { fn dummy() -> Self { Ty { id: DUMMY_NODE_ID, - kind: TyKind::Err, + kind: TyKind::Dummy, span: Default::default(), tokens: Default::default(), } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 4aaaa0ba42457..83f6746bdeb23 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -447,7 +447,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl); } TyKind::Typeof(expression) => visitor.visit_anon_const(expression), - TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {} + TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Err(_) => {} TyKind::MacCall(mac) => visitor.visit_mac_call(mac), TyKind::Never | TyKind::CVarArgs => {} TyKind::AnonStruct(_, ref fields) | TyKind::AnonUnion(_, ref fields) => { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 6b5fc01424085..c1b7af94b02a0 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1285,7 +1285,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> { let kind = match &t.kind { TyKind::Infer => hir::TyKind::Infer, - TyKind::Err => hir::TyKind::Err(self.dcx().has_errors().unwrap()), + TyKind::Err(guar) => hir::TyKind::Err(*guar), // Lower the anonymous structs or unions in a nested lowering context. // // ``` @@ -1503,6 +1503,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); hir::TyKind::Err(guar) } + TyKind::Dummy => panic!("`TyKind::Dummy` should never be lowered"), }; hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index ebc5c17a4c4f2..fa0f532619611 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -881,7 +881,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { &item.vis, errors::VisibilityNotPermittedNote::TraitImpl, ); - if let TyKind::Err = self_ty.kind { + // njn: use Dummy here + if let TyKind::Err(_) = self_ty.kind { this.dcx().emit_err(errors::ObsoleteAuto { span: item.span }); } if let (&Unsafe::Yes(span), &ImplPolarity::Negative(sp)) = (unsafety, polarity) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index cda746894e865..480506272d2ba 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1048,11 +1048,16 @@ impl<'a> State<'a> { ast::TyKind::Infer => { self.word("_"); } - ast::TyKind::Err => { + ast::TyKind::Err(_) => { self.popen(); self.word("/*ERROR*/"); self.pclose(); } + ast::TyKind::Dummy => { + self.popen(); + self.word("/*DUMMY*/"); + self.pclose(); + } ast::TyKind::ImplicitSelf => { self.word("Self"); } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index cfeb31fc4c813..20cfc72f6d362 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -567,10 +567,13 @@ impl DummyResult { } /// A plain dummy type. - pub fn raw_ty(sp: Span, is_error: bool) -> P { + pub fn raw_ty(sp: Span) -> P { + // FIXME(nnethercote): you might expect `ast::TyKind::Dummy` to be used here, but some + // values produced here end up being lowered to HIR, which `ast::TyKind::Dummy` does not + // support, so we use an empty tuple instead. P(ast::Ty { id: ast::DUMMY_NODE_ID, - kind: if is_error { ast::TyKind::Err } else { ast::TyKind::Tup(ThinVec::new()) }, + kind: ast::TyKind::Tup(ThinVec::new()), span: sp, tokens: None, }) @@ -611,7 +614,7 @@ impl MacResult for DummyResult { } fn make_ty(self: Box) -> Option> { - Some(DummyResult::raw_ty(self.span, self.is_error)) + Some(DummyResult::raw_ty(self.span)) } fn make_arms(self: Box) -> Option> { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 445d5b2ce790c..69518287f38ec 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -46,14 +46,14 @@ use std::ops::{Deref, DerefMut}; use thin_vec::{thin_vec, ThinVec}; /// Creates a placeholder argument. -pub(super) fn dummy_arg(ident: Ident) -> Param { +pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param { let pat = P(Pat { id: ast::DUMMY_NODE_ID, kind: PatKind::Ident(BindingAnnotation::NONE, ident, None), span: ident.span, tokens: None, }); - let ty = Ty { kind: TyKind::Err, span: ident.span, id: ast::DUMMY_NODE_ID, tokens: None }; + let ty = Ty { kind: TyKind::Err(guar), span: ident.span, id: ast::DUMMY_NODE_ID, tokens: None }; Param { attrs: AttrVec::default(), id: ast::DUMMY_NODE_ID, @@ -1540,14 +1540,14 @@ impl<'a> Parser<'a> { pub(super) fn maybe_recover_from_question_mark(&mut self, ty: P) -> P { if self.token == token::Question { self.bump(); - self.dcx().emit_err(QuestionMarkInType { + let guar = self.dcx().emit_err(QuestionMarkInType { span: self.prev_token.span, sugg: QuestionMarkInTypeSugg { left: ty.span.shrink_to_lo(), right: self.prev_token.span, }, }); - self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err) + self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err(guar)) } else { ty } @@ -2304,8 +2304,8 @@ impl<'a> Parser<'a> { pub(super) fn recover_bad_self_param(&mut self, mut param: Param) -> PResult<'a, Param> { let span = param.pat.span; - param.ty.kind = TyKind::Err; - self.dcx().emit_err(SelfParamNotFirst { span }); + let guar = self.dcx().emit_err(SelfParamNotFirst { span }); + param.ty.kind = TyKind::Err(guar); Ok(param) } @@ -2437,7 +2437,7 @@ impl<'a> Parser<'a> { pub(super) fn deduplicate_recovered_params_names(&self, fn_inputs: &mut ThinVec) { let mut seen_inputs = FxHashSet::default(); for input in fn_inputs.iter_mut() { - let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err) = + let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err(_)) = (&input.pat.kind, &input.ty.kind) { Some(*ident) @@ -2644,8 +2644,10 @@ impl<'a> Parser<'a> { "::", Applicability::MaybeIncorrect, ); - err.emit(); - return Ok(GenericArg::Type(self.mk_ty(start.to(expr.span), TyKind::Err))); + let guar = err.emit(); + return Ok(GenericArg::Type( + self.mk_ty(start.to(expr.span), TyKind::Err(guar)), + )); } else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg() { // Avoid the following output by checking that we consumed a full const arg: diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 8050b34956ce9..a0605b8a44c3a 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -591,7 +591,23 @@ impl<'a> Parser<'a> { let ty_second = if self.token == token::DotDot { // We need to report this error after `cfg` expansion for compatibility reasons self.bump(); // `..`, do not add it to expected tokens - Some(self.mk_ty(self.prev_token.span, TyKind::Err)) + + // FIXME(nnethercote): AST validation later detects this + // `TyKind::Err` and emits an errors. So why the unchecked + // ErrorGuaranteed? + // - A `span_delayed_bug` doesn't work here, because rustfmt can + // hit this path but then not hit the follow-up path in the AST + // validator that issues the error, which results in ICEs. + // - `TyKind::Dummy` doesn't work, because it ends up reaching HIR + // lowering, which results in ICEs. Changing `TyKind::Dummy` to + // `TyKind::Err` during AST validation might fix that, but that's + // not possible because AST validation doesn't allow mutability. + // + // #121072 will hopefully remove all this special handling of the + // obsolete `impl Trait for ..` and then this can go away. + #[allow(deprecated)] + let guar = rustc_errors::ErrorGuaranteed::unchecked_error_guaranteed(); + Some(self.mk_ty(self.prev_token.span, TyKind::Err(guar))) } else if has_for || self.token.can_begin_type() { Some(self.parse_ty()?) } else { @@ -2628,13 +2644,13 @@ impl<'a> Parser<'a> { p.recover_diff_marker(); let snapshot = p.create_snapshot_for_diagnostic(); let param = p.parse_param_general(req_name, first_param).or_else(|e| { - e.emit(); + let guar = e.emit(); let lo = p.prev_token.span; p.restore_snapshot(snapshot); // Skip every token until next possible arg or end. p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(Delimiter::Parenthesis)]); // Create a placeholder argument for proper arg count (issue #34264). - Ok(dummy_arg(Ident::new(kw::Empty, lo.to(p.prev_token.span)))) + Ok(dummy_arg(Ident::new(kw::Empty, lo.to(p.prev_token.span)), guar)) }); // ...now that we've parsed the first argument, `self` is no longer allowed. first_param = false; @@ -2671,8 +2687,8 @@ impl<'a> Parser<'a> { return if let Some(ident) = this.parameter_without_type(&mut err, pat, is_name_required, first_param) { - err.emit(); - Ok((dummy_arg(ident), TrailingToken::None)) + let guar = err.emit(); + Ok((dummy_arg(ident, guar), TrailingToken::None)) } else { Err(err) }; diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index e7cad74b4dd14..681039999a652 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -678,8 +678,9 @@ impl<'a> Parser<'a> { c.into() } Some(GenericArg::Lifetime(lt)) => { - self.dcx().emit_err(errors::AssocLifetime { span, lifetime: lt.ident.span }); - self.mk_ty(span, ast::TyKind::Err).into() + let guar = + self.dcx().emit_err(errors::AssocLifetime { span, lifetime: lt.ident.span }); + self.mk_ty(span, ast::TyKind::Err(guar)).into() } None => { let after_eq = eq.shrink_to_hi(); @@ -779,7 +780,7 @@ impl<'a> Parser<'a> { // type to determine if error recovery has occurred and if the input is not a // syntactically valid type after all. if let ast::TyKind::Slice(inner_ty) | ast::TyKind::Array(inner_ty, _) = &ty.kind - && let ast::TyKind::Err = inner_ty.kind + && let ast::TyKind::Err(_) = inner_ty.kind && let Some(snapshot) = snapshot && let Some(expr) = self.recover_unbraced_const_arg_that_can_begin_ty(snapshot) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 157fb9e505af7..f79f2a813b223 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -346,8 +346,10 @@ impl<'a> Parser<'a> { AllowCVariadic::No => { // FIXME(Centril): Should we just allow `...` syntactically // anywhere in a type and use semantic restrictions instead? - self.dcx().emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) }); - TyKind::Err + let guar = self + .dcx() + .emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) }); + TyKind::Err(guar) } } } else { @@ -493,8 +495,8 @@ impl<'a> Parser<'a> { { // Recover from `[LIT; EXPR]` and `[LIT]` self.bump(); - err.emit(); - self.mk_ty(self.prev_token.span, TyKind::Err) + let guar = err.emit(); + self.mk_ty(self.prev_token.span, TyKind::Err(guar)) } Err(err) => return Err(err), }; diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index d02e86dd45697..96429bb778882 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -616,8 +616,9 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Infer, ImplicitSelf, MacCall, - Err, - CVarArgs + CVarArgs, + Dummy, + Err ] ); diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index adc35bd82ae39..0467a8a65709a 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -690,7 +690,7 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool { match (&l.kind, &r.kind) { (Paren(l), _) => eq_ty(l, r), (_, Paren(r)) => eq_ty(l, r), - (Never, Never) | (Infer, Infer) | (ImplicitSelf, ImplicitSelf) | (Err, Err) | (CVarArgs, CVarArgs) => true, + (Never, Never) | (Infer, Infer) | (ImplicitSelf, ImplicitSelf) | (Err(_), Err(_)) | (CVarArgs, CVarArgs) => true, (Slice(l), Slice(r)) => eq_ty(l, r), (Array(le, ls), Array(re, rs)) => eq_ty(le, re) && eq_expr(&ls.value, &rs.value), (Ptr(l), Ptr(r)) => l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty), diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 4cd8e6a703e53..7f220a456a8ee 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -859,7 +859,7 @@ impl Rewrite for ast::Ty { }) } ast::TyKind::CVarArgs => Some("...".to_owned()), - ast::TyKind::Err => Some(context.snippet(self.span).to_owned()), + ast::TyKind::Dummy | ast::TyKind::Err(_) => Some(context.snippet(self.span).to_owned()), ast::TyKind::Typeof(ref anon_const) => rewrite_call( context, "typeof", From bd546fb20a2d299a0a2e9c2062df9227e82bdb65 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 15 Feb 2024 01:06:27 +0800 Subject: [PATCH 05/20] add extra indent spaces for rust-playground link --- src/librustdoc/doctest.rs | 18 ++++++++++++-- src/librustdoc/doctest/tests.rs | 44 ++++++++++++++++++++++++++++++++- src/librustdoc/html/markdown.rs | 7 ++++-- tests/rustdoc/playground-arg.rs | 2 +- tests/rustdoc/playground.rs | 2 +- 5 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index f2e083de0ec74..f9d4d1af1140f 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -40,6 +40,9 @@ use crate::lint::init_lints; pub(crate) struct GlobalTestOptions { /// Whether to disable the default `extern crate my_crate;` when creating doctests. pub(crate) no_crate_inject: bool, + /// Whether inserting extra indent spaces in code block, + /// default is `false`, only `true` for generating code link of Rust playground + pub(crate) insert_indent_space: bool, /// Additional crate-level attributes to add to doctests. pub(crate) attrs: Vec, } @@ -221,7 +224,8 @@ pub(crate) fn run_tests( fn scrape_test_config(attrs: &[ast::Attribute]) -> GlobalTestOptions { use rustc_ast_pretty::pprust; - let mut opts = GlobalTestOptions { no_crate_inject: false, attrs: Vec::new() }; + let mut opts = + GlobalTestOptions { no_crate_inject: false, attrs: Vec::new(), insert_indent_space: false }; let test_attrs: Vec<_> = attrs .iter() @@ -725,7 +729,17 @@ pub(crate) fn make_test( // /// ``` <- end of the inner main line_offset += 1; - prog.extend([&main_pre, everything_else, &main_post].iter().cloned()); + // add extra 4 spaces for each line to offset the code block + let content = if opts.insert_indent_space { + everything_else + .lines() + .map(|line| format!(" {}", line)) + .collect::>() + .join("\n") + } else { + everything_else.to_string() + }; + prog.extend([&main_pre, content.as_str(), &main_post].iter().cloned()); } debug!("final doctest:\n{prog}"); diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs index a30fe28f94f99..9629acb31eb68 100644 --- a/src/librustdoc/doctest/tests.rs +++ b/src/librustdoc/doctest/tests.rs @@ -53,7 +53,8 @@ assert_eq!(2+2, 4); fn make_test_no_crate_inject() { // Even if you do use the crate within the test, setting `opts.no_crate_inject` will skip // adding it anyway. - let opts = GlobalTestOptions { no_crate_inject: true, attrs: vec![] }; + let opts = + GlobalTestOptions { no_crate_inject: true, attrs: vec![], insert_indent_space: false }; let input = "use asdf::qwop; assert_eq!(2+2, 4);"; let expected = "#![allow(unused)] @@ -302,3 +303,44 @@ assert_eq!(2+2, 4); make_test(input, None, false, &opts, DEFAULT_EDITION, Some("_some_unique_name")); assert_eq!((output, len), (expected, 2)); } + +#[test] +fn make_test_insert_extra_space() { + // will insert indent spaces in the code block if `insert_indent_space` is true + let opts = + GlobalTestOptions { no_crate_inject: false, attrs: vec![], insert_indent_space: true }; + let input = "use std::*; +assert_eq!(2+2, 4); +eprintln!(\"hello anan\"); +"; + let expected = "#![allow(unused)] +fn main() { + use std::*; + assert_eq!(2+2, 4); + eprintln!(\"hello anan\"); +}" + .to_string(); + let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); + assert_eq!((output, len), (expected, 2)); +} + +#[test] +fn make_test_insert_extra_space_fn_main() { + // if input already has a fn main, it should insert a space before it + let opts = + GlobalTestOptions { no_crate_inject: false, attrs: vec![], insert_indent_space: true }; + let input = "use std::*; +fn main() { + assert_eq!(2+2, 4); + eprintln!(\"hello anan\"); +}"; + let expected = "#![allow(unused)] +use std::*; +fn main() { + assert_eq!(2+2, 4); + eprintln!(\"hello anan\"); +}" + .to_string(); + let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION, None); + assert_eq!((output, len), (expected, 1)); +} diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index ee5891c12fc5a..21f682d15b97d 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -45,6 +45,7 @@ use std::str::{self, CharIndices}; use crate::clean::RenderedLink; use crate::doctest; +use crate::doctest::GlobalTestOptions; use crate::html::escape::Escape; use crate::html::format::Buffer; use crate::html::highlight; @@ -302,8 +303,10 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { .intersperse("\n".into()) .collect::(); let krate = krate.as_ref().map(|s| s.as_str()); - let (test, _, _) = - doctest::make_test(&test, krate, false, &Default::default(), edition, None); + + let mut opts: GlobalTestOptions = Default::default(); + opts.insert_indent_space = true; + let (test, _, _) = doctest::make_test(&test, krate, false, &opts, edition, None); let channel = if test.contains("#![feature(") { "&version=nightly" } else { "" }; let test_escaped = small_url_encode(test); diff --git a/tests/rustdoc/playground-arg.rs b/tests/rustdoc/playground-arg.rs index 2542ed657c1a7..1d7085064e5ac 100644 --- a/tests/rustdoc/playground-arg.rs +++ b/tests/rustdoc/playground-arg.rs @@ -10,4 +10,4 @@ pub fn dummy() {} // ensure that `extern crate foo;` was inserted into code snips automatically: -// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0A%23%5Ballow(unused_extern_crates)%5D%0Aextern+crate+r%23foo;%0Afn+main()+%7B%0Ause+foo::dummy;%0Adummy();%0A%7D&edition=2015"]' "Run" +// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0A%23%5Ballow(unused_extern_crates)%5D%0Aextern+crate+r%23foo;%0Afn+main()+%7B%0A++++use+foo::dummy;%0A++++dummy();%0A%7D&edition=2015"]' "Run" diff --git a/tests/rustdoc/playground.rs b/tests/rustdoc/playground.rs index 5c7fa33efc5e5..a2fc9eb7387aa 100644 --- a/tests/rustdoc/playground.rs +++ b/tests/rustdoc/playground.rs @@ -22,6 +22,6 @@ //! } //! ``` -// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0Aprintln!(%22Hello,+world!%22);%0A%7D&edition=2015"]' "Run" +// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' "Run" // @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' "Run" // @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' "Run" From b277772451805f35c02500b020eedf49742eae08 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Thu, 15 Feb 2024 14:29:13 +0300 Subject: [PATCH 06/20] Improve wording of static_mut_ref Rename `static_mut_ref` lint to `static_mut_refs`. --- .../example/mini_core_hello_world.rs | 4 +- .../example/mini_core_hello_world.rs | 4 +- .../src/error_codes/E0796.md | 26 +++--- compiler/rustc_hir_analysis/messages.ftl | 31 ++++--- compiler/rustc_hir_analysis/src/check/errs.rs | 28 ++---- compiler/rustc_hir_analysis/src/errors.rs | 28 ++---- compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_lint_defs/src/builtin.rs | 8 +- library/panic_unwind/src/seh.rs | 8 +- library/std/src/panicking.rs | 5 +- .../sys/pal/common/thread_local/fast_local.rs | 5 +- .../pal/common/thread_local/static_local.rs | 4 +- library/std/src/thread/local.rs | 4 +- .../miri/tests/fail/tls/tls_static_dealloc.rs | 4 +- src/tools/miri/tests/pass/static_mut.rs | 4 +- src/tools/miri/tests/pass/tls/tls_static.rs | 4 +- tests/ui/abi/statics/static-mut-foreign.rs | 4 +- .../ui/abi/statics/static-mut-foreign.stderr | 22 ++--- .../borrowck/borrowck-access-permissions.rs | 2 +- .../borrowck-access-permissions.stderr | 12 +-- .../borrowck-unsafe-static-mutable-borrows.rs | 2 +- ...rowck-unsafe-static-mutable-borrows.stderr | 12 +-- tests/ui/borrowck/issue-20801.rs | 2 +- tests/ui/borrowck/issue-20801.stderr | 12 +-- ...ue-55492-borrowck-migrate-scans-parents.rs | 6 +- ...5492-borrowck-migrate-scans-parents.stderr | 32 +++---- tests/ui/consts/const_let_assign2.rs | 2 +- tests/ui/consts/const_let_assign2.stderr | 12 +-- .../const_refs_to_static_fail_invalid.rs | 6 +- .../const_refs_to_static_fail_invalid.stderr | 2 +- .../ui/consts/issue-17718-const-bad-values.rs | 2 +- .../const_refers_to_static_cross_crate.rs | 2 +- .../ui/consts/miri_unleashed/extern-static.rs | 2 +- .../miri_unleashed/mutable_references_err.rs | 2 +- .../static-promoted-to-mutable-static.rs | 2 +- .../consts/static_mut_containing_mut_ref.rs | 2 +- .../consts/static_mut_containing_mut_ref2.rs | 2 +- .../issue-23338-ensure-param-drop-order.rs | 2 +- ...issue-23338-ensure-param-drop-order.stderr | 12 +-- tests/ui/error-codes/E0017.rs | 2 +- tests/ui/error-codes/E0017.stderr | 12 +-- .../issues/issue-23611-enum-swap-in-drop.rs | 2 +- .../issue-23611-enum-swap-in-drop.stderr | 12 +-- tests/ui/issues/issue-54410.rs | 2 +- tests/ui/issues/issue-54410.stderr | 12 +-- ...ead-local-static-mut-borrow-outlives-fn.rs | 2 +- ...local-static-mut-borrow-outlives-fn.stderr | 12 +-- .../reference-of-mut-static-safe.e2021.stderr | 26 ------ .../reference-of-mut-static-safe.e2024.stderr | 15 --- .../reference-of-mut-static-unsafe-fn.rs | 23 ----- .../reference-of-mut-static-unsafe-fn.stderr | 63 ------------- .../reference-of-mut-static.e2021.stderr | 91 ------------------- .../reference-of-mut-static.e2024.stderr | 75 --------------- tests/ui/static/reference-of-mut-static.rs | 50 ---------- .../reference-to-mut-static-safe.e2021.stderr | 26 ++++++ .../reference-to-mut-static-safe.e2024.stderr | 15 +++ ...afe.rs => reference-to-mut-static-safe.rs} | 4 +- .../reference-to-mut-static-unsafe-fn.rs | 26 ++++++ .../reference-to-mut-static-unsafe-fn.stderr | 75 +++++++++++++++ .../reference-to-mut-static.e2021.stderr | 91 +++++++++++++++++++ .../reference-to-mut-static.e2024.stderr | 75 +++++++++++++++ tests/ui/static/reference-to-mut-static.rs | 50 ++++++++++ tests/ui/static/safe-extern-statics-mut.rs | 4 +- .../ui/static/safe-extern-statics-mut.stderr | 22 ++--- tests/ui/statics/issue-15261.rs | 2 +- tests/ui/statics/issue-15261.stderr | 12 +-- tests/ui/statics/static-mut-xc.rs | 4 +- tests/ui/statics/static-mut-xc.stderr | 22 ++--- tests/ui/statics/static-recursive.rs | 2 +- tests/ui/statics/static-recursive.stderr | 12 +-- tests/ui/thread-local/thread-local-static.rs | 2 +- 71 files changed, 586 insertions(+), 581 deletions(-) delete mode 100644 tests/ui/static/reference-of-mut-static-safe.e2021.stderr delete mode 100644 tests/ui/static/reference-of-mut-static-safe.e2024.stderr delete mode 100644 tests/ui/static/reference-of-mut-static-unsafe-fn.rs delete mode 100644 tests/ui/static/reference-of-mut-static-unsafe-fn.stderr delete mode 100644 tests/ui/static/reference-of-mut-static.e2021.stderr delete mode 100644 tests/ui/static/reference-of-mut-static.e2024.stderr delete mode 100644 tests/ui/static/reference-of-mut-static.rs create mode 100644 tests/ui/static/reference-to-mut-static-safe.e2021.stderr create mode 100644 tests/ui/static/reference-to-mut-static-safe.e2024.stderr rename tests/ui/static/{reference-of-mut-static-safe.rs => reference-to-mut-static-safe.rs} (62%) create mode 100644 tests/ui/static/reference-to-mut-static-unsafe-fn.rs create mode 100644 tests/ui/static/reference-to-mut-static-unsafe-fn.stderr create mode 100644 tests/ui/static/reference-to-mut-static.e2021.stderr create mode 100644 tests/ui/static/reference-to-mut-static.e2024.stderr create mode 100644 tests/ui/static/reference-to-mut-static.rs diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index 2a7b1107ffcaa..8b0b9123ac7df 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -112,8 +112,8 @@ fn start( static mut NUM: u8 = 6 * 7; -// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[allow(static_mut_ref)] +// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint +#[allow(static_mut_refs)] static NUM_REF: &'static u8 = unsafe { &NUM }; unsafe fn zeroed() -> T { diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs index 9827e299f2a31..add77880716c8 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs @@ -99,8 +99,8 @@ fn start( static mut NUM: u8 = 6 * 7; -// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[allow(static_mut_ref)] +// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint +#[allow(static_mut_refs)] static NUM_REF: &'static u8 = unsafe { &NUM }; macro_rules! assert { diff --git a/compiler/rustc_error_codes/src/error_codes/E0796.md b/compiler/rustc_error_codes/src/error_codes/E0796.md index cea18f8db851f..7ac429e521581 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0796.md +++ b/compiler/rustc_error_codes/src/error_codes/E0796.md @@ -1,22 +1,26 @@ -Reference of mutable static. +You have created a reference to a mutable static. Erroneous code example: ```compile_fail,edition2024,E0796 static mut X: i32 = 23; -static mut Y: i32 = 24; -unsafe { - let y = &X; - let ref x = X; - let (x, y) = (&X, &Y); - foo(&X); +fn work() { + let _val = unsafe { X }; } -fn foo<'a>(_x: &'a i32) {} +let x_ref = unsafe { &mut X }; +work(); +// The next line has Undefined Behavior! +// `x_ref` is a mutable reference and allows no aliases, +// but `work` has been reading the reference between +// the moment `x_ref` was created and when it was used. +// This violates the uniqueness of `x_ref`. +*x_ref = 42; ``` -Mutable statics can be written to by multiple threads: aliasing violations or -data races will cause undefined behavior. +A reference to a mutable static has lifetime `'static`. This is very dangerous +as it is easy to accidentally overlap the lifetime of that reference with +other, conflicting accesses to the same static. -Reference of mutable static is a hard error from 2024 edition. +References to mutable statics are a hard error in the 2024 edition. diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index a61cfd0e4ce9a..99f7ab2fa4d9c 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -373,19 +373,24 @@ hir_analysis_start_not_target_feature = `#[start]` function is not allowed to ha hir_analysis_start_not_track_caller = `#[start]` function is not allowed to be `#[track_caller]` .label = `#[start]` function is not allowed to be `#[track_caller]` -hir_analysis_static_mut_ref = reference of mutable static is disallowed - .label = reference of mutable static - .note = mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - .suggestion = shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - .suggestion_mut = mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer - -hir_analysis_static_mut_ref_lint = {$shared}reference of mutable static is discouraged - .label = shared reference of mutable static - .label_mut = mutable reference of mutable static - .suggestion = shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - .suggestion_mut = mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer - .note = reference of mutable static is a hard error from 2024 edition - .why_note = mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior +hir_analysis_static_mut_ref = creating a {$shared} reference to a mutable static + .label = {$shared}reference to mutable static + .note = {$shared -> + [shared] this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior + *[mutable] this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior + } + .suggestion = use `addr_of!` instead to create a raw pointer + .suggestion_mut = use `addr_of_mut!` instead to create a raw pointer + +hir_analysis_static_mut_refs_lint = creating a {$shared} reference to mutable static is discouraged + .label = {$shared} reference to mutable static + .suggestion = use `addr_of!` instead to create a raw pointer + .suggestion_mut = use `addr_of_mut!` instead to create a raw pointer + .note = this will be a hard error in the 2024 edition + .why_note = {$shared -> + [shared] this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior + *[mutable] this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior + } hir_analysis_static_specialize = cannot specialize on `'static` lifetime diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs index 87a1f3d342580..4a7ace274c5bb 100644 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ b/compiler/rustc_hir_analysis/src/check/errs.rs @@ -1,6 +1,6 @@ use rustc_hir as hir; use rustc_hir_pretty::qpath_to_string; -use rustc_lint_defs::builtin::STATIC_MUT_REF; +use rustc_lint_defs::builtin::STATIC_MUT_REFS; use rustc_middle::ty::TyCtxt; use rustc_span::Span; use rustc_type_ir::Mutability; @@ -66,32 +66,24 @@ fn handle_static_mut_ref( hir_id: hir::HirId, ) { if e2024 { - let sugg = if mutable { - errors::StaticMutRefSugg::Mut { span, var } + let (sugg, shared) = if mutable { + (errors::StaticMutRefSugg::Mut { span, var }, "mutable") } else { - errors::StaticMutRefSugg::Shared { span, var } + (errors::StaticMutRefSugg::Shared { span, var }, "shared") }; - tcx.sess.parse_sess.dcx.emit_err(errors::StaticMutRef { span, sugg }); + tcx.sess.parse_sess.dcx.emit_err(errors::StaticMutRef { span, sugg, shared }); return; } - let (label, sugg, shared) = if mutable { - ( - errors::RefOfMutStaticLabel::Mut { span }, - errors::RefOfMutStaticSugg::Mut { span, var }, - "mutable ", - ) + let (sugg, shared) = if mutable { + (errors::RefOfMutStaticSugg::Mut { span, var }, "mutable") } else { - ( - errors::RefOfMutStaticLabel::Shared { span }, - errors::RefOfMutStaticSugg::Shared { span, var }, - "shared ", - ) + (errors::RefOfMutStaticSugg::Shared { span, var }, "shared") }; tcx.emit_node_span_lint( - STATIC_MUT_REF, + STATIC_MUT_REFS, hir_id, span, - errors::RefOfMutStatic { shared, why_note: (), label, sugg }, + errors::RefOfMutStatic { span, sugg, shared }, ); } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 6a505b961974f..a8fd311df4321 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1455,12 +1455,13 @@ pub struct OnlyCurrentTraitsPointerSugg<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_static_mut_ref, code = E0796)] #[note] -pub struct StaticMutRef { +pub struct StaticMutRef<'a> { #[primary_span] #[label] pub span: Span, #[subdiagnostic] pub sugg: StaticMutRefSugg, + pub shared: &'a str, } #[derive(Subdiagnostic)] @@ -1491,30 +1492,15 @@ pub enum StaticMutRefSugg { // STATIC_MUT_REF lint #[derive(LintDiagnostic)] -#[diag(hir_analysis_static_mut_ref_lint)] +#[diag(hir_analysis_static_mut_refs_lint)] #[note] +#[note(hir_analysis_why_note)] pub struct RefOfMutStatic<'a> { - pub shared: &'a str, - #[note(hir_analysis_why_note)] - pub why_note: (), - #[subdiagnostic] - pub label: RefOfMutStaticLabel, + #[label] + pub span: Span, #[subdiagnostic] pub sugg: RefOfMutStaticSugg, -} - -#[derive(Subdiagnostic)] -pub enum RefOfMutStaticLabel { - #[label(hir_analysis_label)] - Shared { - #[primary_span] - span: Span, - }, - #[label(hir_analysis_label_mut)] - Mut { - #[primary_span] - span: Span, - }, + pub shared: &'a str, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 5f769e9ad8a5b..0598a5de06342 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -324,6 +324,7 @@ fn register_builtins(store: &mut LintStore) { store.register_renamed("or_patterns_back_compat", "rust_2021_incompatible_or_patterns"); store.register_renamed("non_fmt_panic", "non_fmt_panics"); store.register_renamed("unused_tuple_struct_fields", "dead_code"); + store.register_renamed("static_mut_ref", "static_mut_refs"); // These were moved to tool lints, but rustc still sees them when compiling normally, before // tool lints are registered, so `check_tool_name_for_backwards_compat` doesn't work. Use diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 6a2a2c1e48e2a..3f5d3c2597151 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -89,7 +89,7 @@ declare_lint_pass! { SINGLE_USE_LIFETIMES, SOFT_UNSTABLE, STABLE_FEATURES, - STATIC_MUT_REF, + STATIC_MUT_REFS, SUSPICIOUS_AUTO_TRAIT_IMPLS, TEST_UNSTABLE_LINT, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, @@ -1769,7 +1769,7 @@ declare_lint! { } declare_lint! { - /// The `static_mut_ref` lint checks for shared or mutable references + /// The `static_mut_refs` lint checks for shared or mutable references /// of mutable static inside `unsafe` blocks and `unsafe` functions. /// /// ### Example @@ -1807,9 +1807,9 @@ declare_lint! { /// Shared or mutable references of mutable static are almost always a mistake and /// can lead to undefined behavior and various other problems in your code. /// - /// This lint is "warn" by default on editions up to 2021, from 2024 there is + /// This lint is "warn" by default on editions up to 2021, in 2024 there is /// a hard error instead. - pub STATIC_MUT_REF, + pub STATIC_MUT_REFS, Warn, "shared references or mutable references of mutable static is discouraged", @future_incompatible = FutureIncompatibleInfo { diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index d3ba546d730d4..876954ab87e85 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -261,8 +261,8 @@ cfg_if::cfg_if! { } } -// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[allow(static_mut_ref)] +// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint +#[allow(static_mut_refs)] pub unsafe fn panic(data: Box) -> u32 { use core::intrinsics::atomic_store_seqcst; @@ -324,8 +324,8 @@ pub unsafe fn panic(data: Box) -> u32 { _CxxThrowException(throw_ptr, &mut THROW_INFO as *mut _ as *mut _); } -// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[allow(static_mut_ref)] +// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint +#[allow(static_mut_refs)] pub unsafe fn cleanup(payload: *mut u8) -> Box { // A null payload here means that we got here from the catch (...) of // __rust_try. This happens when a non-Rust foreign exception is caught. diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 8294160b72ca7..c8306c1b597a3 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -337,8 +337,9 @@ pub mod panic_count { #[doc(hidden)] #[cfg(not(feature = "panic_immediate_abort"))] #[unstable(feature = "update_panic_count", issue = "none")] -// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[allow(static_mut_ref)] +// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint +#[cfg_attr(bootstrap, allow(static_mut_ref))] +#[cfg_attr(not(bootstrap), allow(static_mut_refs))] pub mod panic_count { use crate::cell::Cell; use crate::sync::atomic::{AtomicUsize, Ordering}; diff --git a/library/std/src/sys/pal/common/thread_local/fast_local.rs b/library/std/src/sys/pal/common/thread_local/fast_local.rs index 04c0dd6f75090..646dcd7f3a3e8 100644 --- a/library/std/src/sys/pal/common/thread_local/fast_local.rs +++ b/library/std/src/sys/pal/common/thread_local/fast_local.rs @@ -13,8 +13,9 @@ pub macro thread_local_inner { (@key $t:ty, const $init:expr) => {{ #[inline] #[deny(unsafe_op_in_unsafe_fn)] - // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint - #[allow(static_mut_ref)] + // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint + #[cfg_attr(bootstrap, allow(static_mut_ref))] + #[cfg_attr(not(bootstrap), allow(static_mut_refs))] unsafe fn __getit( _init: $crate::option::Option<&mut $crate::option::Option<$t>>, ) -> $crate::option::Option<&'static $t> { diff --git a/library/std/src/sys/pal/common/thread_local/static_local.rs b/library/std/src/sys/pal/common/thread_local/static_local.rs index 0dde78b14dbb8..206e62bb5e2c8 100644 --- a/library/std/src/sys/pal/common/thread_local/static_local.rs +++ b/library/std/src/sys/pal/common/thread_local/static_local.rs @@ -11,8 +11,8 @@ pub macro thread_local_inner { (@key $t:ty, const $init:expr) => {{ #[inline] // see comments below #[deny(unsafe_op_in_unsafe_fn)] - // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint - #[allow(static_mut_ref)] + // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint + #[allow(static_mut_refs)] unsafe fn __getit( _init: $crate::option::Option<&mut $crate::option::Option<$t>>, ) -> $crate::option::Option<&'static $t> { diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 83d5d63556fc3..d1213e2f16686 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -180,8 +180,8 @@ impl fmt::Debug for LocalKey { #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "thread_local_macro")] #[allow_internal_unstable(thread_local_internals)] -// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[allow(static_mut_ref)] +// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint +#[cfg_attr(not(bootstrap), allow(static_mut_refs))] macro_rules! thread_local { // empty (base case for the recursion) () => {}; diff --git a/src/tools/miri/tests/fail/tls/tls_static_dealloc.rs b/src/tools/miri/tests/fail/tls/tls_static_dealloc.rs index 762a8d85314f2..d47a05d8475cf 100644 --- a/src/tools/miri/tests/fail/tls/tls_static_dealloc.rs +++ b/src/tools/miri/tests/fail/tls/tls_static_dealloc.rs @@ -1,8 +1,8 @@ //! Ensure that thread-local statics get deallocated when the thread dies. #![feature(thread_local)] -// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#![allow(static_mut_ref)] +// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint +#![allow(static_mut_refs)] #[thread_local] static mut TLS: u8 = 0; diff --git a/src/tools/miri/tests/pass/static_mut.rs b/src/tools/miri/tests/pass/static_mut.rs index c1e58b70adb0b..6b0c0297726f3 100644 --- a/src/tools/miri/tests/pass/static_mut.rs +++ b/src/tools/miri/tests/pass/static_mut.rs @@ -1,7 +1,7 @@ static mut FOO: i32 = 42; -// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[allow(static_mut_ref)] +// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint +#[allow(static_mut_refs)] static BAR: Foo = Foo(unsafe { &FOO as *const _ }); #[allow(dead_code)] diff --git a/src/tools/miri/tests/pass/tls/tls_static.rs b/src/tools/miri/tests/pass/tls/tls_static.rs index 9be00af47aa35..fea5bb1db5e6b 100644 --- a/src/tools/miri/tests/pass/tls/tls_static.rs +++ b/src/tools/miri/tests/pass/tls/tls_static.rs @@ -8,8 +8,8 @@ //! test, we also check that thread-locals act as per-thread statics. #![feature(thread_local)] -// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#![allow(static_mut_ref)] +// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint +#![allow(static_mut_refs)] use std::thread; diff --git a/tests/ui/abi/statics/static-mut-foreign.rs b/tests/ui/abi/statics/static-mut-foreign.rs index eb732e7c2c31f..5d7cf1477c1c1 100644 --- a/tests/ui/abi/statics/static-mut-foreign.rs +++ b/tests/ui/abi/statics/static-mut-foreign.rs @@ -33,9 +33,9 @@ unsafe fn run() { rust_dbg_static_mut = -3; assert_eq!(rust_dbg_static_mut, -3); static_bound(&rust_dbg_static_mut); - //~^ WARN shared reference of mutable static is discouraged [static_mut_ref] + //~^ WARN shared reference to mutable static is discouraged [static_mut_refs] static_bound_set(&mut rust_dbg_static_mut); - //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref] + //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs] } pub fn main() { diff --git a/tests/ui/abi/statics/static-mut-foreign.stderr b/tests/ui/abi/statics/static-mut-foreign.stderr index 144ac056f87e4..f393088ff9f33 100644 --- a/tests/ui/abi/statics/static-mut-foreign.stderr +++ b/tests/ui/abi/statics/static-mut-foreign.stderr @@ -1,28 +1,28 @@ -warning: shared reference of mutable static is discouraged +warning: creating a shared reference to mutable static is discouraged --> $DIR/static-mut-foreign.rs:35:18 | LL | static_bound(&rust_dbg_static_mut); - | ^^^^^^^^^^^^^^^^^^^^ shared reference of mutable static + | ^^^^^^^^^^^^^^^^^^^^ shared reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of!` instead to create a raw pointer | LL | static_bound(addr_of!(rust_dbg_static_mut)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -warning: mutable reference of mutable static is discouraged +warning: creating a mutable reference to mutable static is discouraged --> $DIR/static-mut-foreign.rs:37:22 | LL | static_bound_set(&mut rust_dbg_static_mut); - | ^^^^^^^^^^^^^^^^^^^^^^^^ mutable reference of mutable static + | ^^^^^^^^^^^^^^^^^^^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior +help: use `addr_of_mut!` instead to create a raw pointer | LL | static_bound_set(addr_of_mut!(rust_dbg_static_mut)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/borrowck/borrowck-access-permissions.rs b/tests/ui/borrowck/borrowck-access-permissions.rs index 1638644103ba4..be11286a523df 100644 --- a/tests/ui/borrowck/borrowck-access-permissions.rs +++ b/tests/ui/borrowck/borrowck-access-permissions.rs @@ -16,7 +16,7 @@ fn main() { let _y1 = &mut static_x; //~ ERROR [E0596] unsafe { let _y2 = &mut static_x_mut; - //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref] + //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs] } } diff --git a/tests/ui/borrowck/borrowck-access-permissions.stderr b/tests/ui/borrowck/borrowck-access-permissions.stderr index 93d92295dd9b6..11e2b63bd6cd7 100644 --- a/tests/ui/borrowck/borrowck-access-permissions.stderr +++ b/tests/ui/borrowck/borrowck-access-permissions.stderr @@ -1,14 +1,14 @@ -warning: mutable reference of mutable static is discouraged +warning: creating a mutable reference to mutable static is discouraged --> $DIR/borrowck-access-permissions.rs:18:23 | LL | let _y2 = &mut static_x_mut; - | ^^^^^^^^^^^^^^^^^ mutable reference of mutable static + | ^^^^^^^^^^^^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of_mut!` instead to create a raw pointer | LL | let _y2 = addr_of_mut!(static_x_mut); | ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs index 1bf079e24cae4..76a28f928e3c0 100644 --- a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs +++ b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs @@ -17,7 +17,7 @@ impl Foo { fn main() { unsafe { let sfoo: *mut Foo = &mut SFOO; - //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref] + //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs] let x = (*sfoo).x(); (*sfoo).x[1] += 1; *x += 1; diff --git a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr index 7a3824f79a4c2..354d70eb1ad49 100644 --- a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr +++ b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr @@ -1,14 +1,14 @@ -warning: mutable reference of mutable static is discouraged +warning: creating a mutable reference to mutable static is discouraged --> $DIR/borrowck-unsafe-static-mutable-borrows.rs:19:30 | LL | let sfoo: *mut Foo = &mut SFOO; - | ^^^^^^^^^ mutable reference of mutable static + | ^^^^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of_mut!` instead to create a raw pointer | LL | let sfoo: *mut Foo = addr_of_mut!(SFOO); | ~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/borrowck/issue-20801.rs b/tests/ui/borrowck/issue-20801.rs index ec83af5d5dfc6..7e3d3703dc765 100644 --- a/tests/ui/borrowck/issue-20801.rs +++ b/tests/ui/borrowck/issue-20801.rs @@ -12,7 +12,7 @@ fn imm_ref() -> &'static T { fn mut_ref() -> &'static mut T { unsafe { &mut GLOBAL_MUT_T } - //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref] + //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs] } fn mut_ptr() -> *mut T { diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr index b2bee2d880394..97294afd3df9e 100644 --- a/tests/ui/borrowck/issue-20801.stderr +++ b/tests/ui/borrowck/issue-20801.stderr @@ -1,14 +1,14 @@ -warning: mutable reference of mutable static is discouraged +warning: creating a mutable reference to mutable static is discouraged --> $DIR/issue-20801.rs:14:14 | LL | unsafe { &mut GLOBAL_MUT_T } - | ^^^^^^^^^^^^^^^^^ mutable reference of mutable static + | ^^^^^^^^^^^^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of_mut!` instead to create a raw pointer | LL | unsafe { addr_of_mut!(GLOBAL_MUT_T) } | ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs index 9b172b4131911..c3909d0596339 100644 --- a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs +++ b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs @@ -10,7 +10,7 @@ mod borrowck_closures_unique { //~^ ERROR is not declared as mutable unsafe { c1(&mut Y); - //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref] + //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs] } } } @@ -25,7 +25,7 @@ mod borrowck_closures_unique_grandparent { }; unsafe { c1(&mut Z); - //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref] + //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs] } } } @@ -62,7 +62,7 @@ fn main() { static mut X: isize = 2; unsafe { borrowck_closures_unique::e(&mut X); - //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref] + //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs] } mutability_errors::capture_assign_whole((1000,)); diff --git a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr index e4e4947fce1c1..098a2964e9fc7 100644 --- a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr +++ b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr @@ -1,42 +1,42 @@ -warning: mutable reference of mutable static is discouraged +warning: creating a mutable reference to mutable static is discouraged --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:12:16 | LL | c1(&mut Y); - | ^^^^^^ mutable reference of mutable static + | ^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of_mut!` instead to create a raw pointer | LL | c1(addr_of_mut!(Y)); | ~~~~~~~~~~~~~~~ -warning: mutable reference of mutable static is discouraged +warning: creating a mutable reference to mutable static is discouraged --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:27:16 | LL | c1(&mut Z); - | ^^^^^^ mutable reference of mutable static + | ^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior +help: use `addr_of_mut!` instead to create a raw pointer | LL | c1(addr_of_mut!(Z)); | ~~~~~~~~~~~~~~~ -warning: mutable reference of mutable static is discouraged +warning: creating a mutable reference to mutable static is discouraged --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:64:37 | LL | borrowck_closures_unique::e(&mut X); - | ^^^^^^ mutable reference of mutable static + | ^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior +help: use `addr_of_mut!` instead to create a raw pointer | LL | borrowck_closures_unique::e(addr_of_mut!(X)); | ~~~~~~~~~~~~~~~ diff --git a/tests/ui/consts/const_let_assign2.rs b/tests/ui/consts/const_let_assign2.rs index 1c7afe0e3d6cb..f375f0f603df5 100644 --- a/tests/ui/consts/const_let_assign2.rs +++ b/tests/ui/consts/const_let_assign2.rs @@ -16,7 +16,7 @@ static mut BB: AA = AA::new(); fn main() { let ptr = unsafe { &mut BB }; - //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref] + //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs] for a in ptr.data.iter() { println!("{}", a); } diff --git a/tests/ui/consts/const_let_assign2.stderr b/tests/ui/consts/const_let_assign2.stderr index 2764153a8a590..5ae8fd353dd78 100644 --- a/tests/ui/consts/const_let_assign2.stderr +++ b/tests/ui/consts/const_let_assign2.stderr @@ -1,14 +1,14 @@ -warning: mutable reference of mutable static is discouraged +warning: creating a mutable reference to mutable static is discouraged --> $DIR/const_let_assign2.rs:18:24 | LL | let ptr = unsafe { &mut BB }; - | ^^^^^^^ mutable reference of mutable static + | ^^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of_mut!` instead to create a raw pointer | LL | let ptr = unsafe { addr_of_mut!(BB) }; | ~~~~~~~~~~~~~~~~ diff --git a/tests/ui/consts/const_refs_to_static_fail_invalid.rs b/tests/ui/consts/const_refs_to_static_fail_invalid.rs index 665b876c43e2c..bd841c175bf81 100644 --- a/tests/ui/consts/const_refs_to_static_fail_invalid.rs +++ b/tests/ui/consts/const_refs_to_static_fail_invalid.rs @@ -1,7 +1,7 @@ // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" // normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" #![feature(const_refs_to_static)] -#![allow(static_mut_ref)] +#![allow(static_mut_refs)] fn invalid() { static S: i8 = 10; @@ -43,8 +43,8 @@ fn mutable() { // This *must not build*, the constant we are matching against // could change its value! match &42 { - C => {}, //~ERROR: could not evaluate constant pattern - _ => {}, + C => {} //~ERROR: could not evaluate constant pattern + _ => {} } } diff --git a/tests/ui/consts/const_refs_to_static_fail_invalid.stderr b/tests/ui/consts/const_refs_to_static_fail_invalid.stderr index 082f8532444ad..4ff15f0c28b8f 100644 --- a/tests/ui/consts/const_refs_to_static_fail_invalid.stderr +++ b/tests/ui/consts/const_refs_to_static_fail_invalid.stderr @@ -46,7 +46,7 @@ LL | const C: &i32 = unsafe { &S_MUT }; error: could not evaluate constant pattern --> $DIR/const_refs_to_static_fail_invalid.rs:46:9 | -LL | C => {}, +LL | C => {} | ^ error: aborting due to 6 previous errors diff --git a/tests/ui/consts/issue-17718-const-bad-values.rs b/tests/ui/consts/issue-17718-const-bad-values.rs index 0299bfef1b49a..52f8c9bf149a6 100644 --- a/tests/ui/consts/issue-17718-const-bad-values.rs +++ b/tests/ui/consts/issue-17718-const-bad-values.rs @@ -1,4 +1,4 @@ -#![allow(static_mut_ref)] +#![allow(static_mut_refs)] const C1: &'static mut [usize] = &mut []; //~^ ERROR: mutable references are not allowed diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs index bcd29f8b03441..bcece4ccb34b5 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs @@ -2,7 +2,7 @@ // aux-build:static_cross_crate.rs // stderr-per-bitwidth #![feature(exclusive_range_pattern, half_open_range_patterns_in_slices)] -#![allow(static_mut_ref)] +#![allow(static_mut_refs)] extern crate static_cross_crate; diff --git a/tests/ui/consts/miri_unleashed/extern-static.rs b/tests/ui/consts/miri_unleashed/extern-static.rs index 81176b3d4e997..686aa90f55e81 100644 --- a/tests/ui/consts/miri_unleashed/extern-static.rs +++ b/tests/ui/consts/miri_unleashed/extern-static.rs @@ -1,6 +1,6 @@ // compile-flags: -Zunleash-the-miri-inside-of-you #![feature(thread_local)] -#![allow(static_mut_ref)] +#![allow(static_mut_refs)] extern "C" { static mut DATA: u8; diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.rs b/tests/ui/consts/miri_unleashed/mutable_references_err.rs index 43b65f459a1eb..aabcf6d7bee3e 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.rs +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.rs @@ -1,6 +1,6 @@ // stderr-per-bitwidth // compile-flags: -Zunleash-the-miri-inside-of-you -#![allow(invalid_reference_casting, static_mut_ref)] +#![allow(invalid_reference_casting, static_mut_refs)] use std::sync::atomic::*; use std::cell::UnsafeCell; diff --git a/tests/ui/consts/static-promoted-to-mutable-static.rs b/tests/ui/consts/static-promoted-to-mutable-static.rs index d49ba478dbc82..9150867d42330 100644 --- a/tests/ui/consts/static-promoted-to-mutable-static.rs +++ b/tests/ui/consts/static-promoted-to-mutable-static.rs @@ -1,5 +1,5 @@ // check-pass -#![allow(non_camel_case_types, non_upper_case_globals, static_mut_ref)] +#![allow(non_camel_case_types, non_upper_case_globals, static_mut_refs)] pub struct wl_interface { pub version: i32 diff --git a/tests/ui/consts/static_mut_containing_mut_ref.rs b/tests/ui/consts/static_mut_containing_mut_ref.rs index 495804649b14b..3f5bd8007adca 100644 --- a/tests/ui/consts/static_mut_containing_mut_ref.rs +++ b/tests/ui/consts/static_mut_containing_mut_ref.rs @@ -1,5 +1,5 @@ // build-pass (FIXME(62277): could be check-pass?) -#![allow(static_mut_ref)] +#![allow(static_mut_refs)] static mut STDERR_BUFFER_SPACE: [u8; 42] = [0u8; 42]; diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.rs b/tests/ui/consts/static_mut_containing_mut_ref2.rs index e60a17922fd0c..c2e75c1ba9f0e 100644 --- a/tests/ui/consts/static_mut_containing_mut_ref2.rs +++ b/tests/ui/consts/static_mut_containing_mut_ref2.rs @@ -1,5 +1,5 @@ // revisions: stock mut_refs -#![allow(static_mut_ref)] +#![allow(static_mut_refs)] #![cfg_attr(mut_refs, feature(const_mut_refs))] static mut STDERR_BUFFER_SPACE: u8 = 0; diff --git a/tests/ui/drop/issue-23338-ensure-param-drop-order.rs b/tests/ui/drop/issue-23338-ensure-param-drop-order.rs index 52603744c45fc..a6796bd17df17 100644 --- a/tests/ui/drop/issue-23338-ensure-param-drop-order.rs +++ b/tests/ui/drop/issue-23338-ensure-param-drop-order.rs @@ -91,7 +91,7 @@ pub mod d { pub fn max_width() -> u32 { unsafe { (mem::size_of_val(&trails) * 8) as u32 - //~^ WARN shared reference of mutable static is discouraged [static_mut_ref] + //~^ WARN shared reference to mutable static is discouraged [static_mut_refs] } } diff --git a/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr b/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr index fd36ccbcbee47..de1194e74b40d 100644 --- a/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr +++ b/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr @@ -1,14 +1,14 @@ -warning: shared reference of mutable static is discouraged +warning: creating a shared reference to mutable static is discouraged --> $DIR/issue-23338-ensure-param-drop-order.rs:93:31 | LL | (mem::size_of_val(&trails) * 8) as u32 - | ^^^^^^^ shared reference of mutable static + | ^^^^^^^ shared reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of!` instead to create a raw pointer | LL | (mem::size_of_val(addr_of!(trails)) * 8) as u32 | ~~~~~~~~~~~~~~~~ diff --git a/tests/ui/error-codes/E0017.rs b/tests/ui/error-codes/E0017.rs index 9d3433fa543fd..4637fc75b48c7 100644 --- a/tests/ui/error-codes/E0017.rs +++ b/tests/ui/error-codes/E0017.rs @@ -13,6 +13,6 @@ static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are no //~| WARN taking a mutable static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR mutable references are not -//~^ WARN mutable reference of mutable static is discouraged [static_mut_ref] +//~^ WARN mutable reference to mutable static is discouraged [static_mut_refs] fn main() {} diff --git a/tests/ui/error-codes/E0017.stderr b/tests/ui/error-codes/E0017.stderr index 2a70f2ee0ae82..f4a51dca207d9 100644 --- a/tests/ui/error-codes/E0017.stderr +++ b/tests/ui/error-codes/E0017.stderr @@ -1,14 +1,14 @@ -warning: mutable reference of mutable static is discouraged +warning: creating a mutable reference to mutable static is discouraged --> $DIR/E0017.rs:15:52 | LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; - | ^^^^^^ mutable reference of mutable static + | ^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of_mut!` instead to create a raw pointer | LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { addr_of_mut!(M) }; | ~~~~~~~~~~~~~~~ diff --git a/tests/ui/issues/issue-23611-enum-swap-in-drop.rs b/tests/ui/issues/issue-23611-enum-swap-in-drop.rs index b967e6aecdd43..0582ff5e80ad9 100644 --- a/tests/ui/issues/issue-23611-enum-swap-in-drop.rs +++ b/tests/ui/issues/issue-23611-enum-swap-in-drop.rs @@ -187,7 +187,7 @@ pub mod d { pub fn max_width() -> u32 { unsafe { (mem::size_of_val(&trails) * 8) as u32 - //~^ WARN shared reference of mutable static is discouraged [static_mut_ref] + //~^ WARN shared reference to mutable static is discouraged [static_mut_refs] } } diff --git a/tests/ui/issues/issue-23611-enum-swap-in-drop.stderr b/tests/ui/issues/issue-23611-enum-swap-in-drop.stderr index 14a986a333264..bdf46abea8a1f 100644 --- a/tests/ui/issues/issue-23611-enum-swap-in-drop.stderr +++ b/tests/ui/issues/issue-23611-enum-swap-in-drop.stderr @@ -1,14 +1,14 @@ -warning: shared reference of mutable static is discouraged +warning: creating a shared reference to mutable static is discouraged --> $DIR/issue-23611-enum-swap-in-drop.rs:189:31 | LL | (mem::size_of_val(&trails) * 8) as u32 - | ^^^^^^^ shared reference of mutable static + | ^^^^^^^ shared reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of!` instead to create a raw pointer | LL | (mem::size_of_val(addr_of!(trails)) * 8) as u32 | ~~~~~~~~~~~~~~~~ diff --git a/tests/ui/issues/issue-54410.rs b/tests/ui/issues/issue-54410.rs index 51eea3ad9ac43..208be6f221c25 100644 --- a/tests/ui/issues/issue-54410.rs +++ b/tests/ui/issues/issue-54410.rs @@ -5,5 +5,5 @@ extern "C" { fn main() { println!("{:p}", unsafe { &symbol }); - //~^ WARN: shared reference of mutable static is discouraged + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] } diff --git a/tests/ui/issues/issue-54410.stderr b/tests/ui/issues/issue-54410.stderr index 941c1be3eab5f..7cc67ab72c396 100644 --- a/tests/ui/issues/issue-54410.stderr +++ b/tests/ui/issues/issue-54410.stderr @@ -6,17 +6,17 @@ LL | pub static mut symbol: [i8]; | = help: the trait `Sized` is not implemented for `[i8]` -warning: shared reference of mutable static is discouraged +warning: creating a shared reference to mutable static is discouraged --> $DIR/issue-54410.rs:7:31 | LL | println!("{:p}", unsafe { &symbol }); - | ^^^^^^^ shared reference of mutable static + | ^^^^^^^ shared reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of!` instead to create a raw pointer | LL | println!("{:p}", unsafe { addr_of!(symbol) }); | ~~~~~~~~~~~~~~~~ diff --git a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs index 8eb544e8ab9d2..39d594b0e3227 100644 --- a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs +++ b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs @@ -15,7 +15,7 @@ struct S1 { impl S1 { fn new(_x: u64) -> S1 { S1 { a: unsafe { &mut X1 } } - //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref] + //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs] } } diff --git a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr index 17217cd5859d0..82065cc06ea1d 100644 --- a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr +++ b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr @@ -1,14 +1,14 @@ -warning: mutable reference of mutable static is discouraged +warning: creating a mutable reference to mutable static is discouraged --> $DIR/borrowck-thread-local-static-mut-borrow-outlives-fn.rs:17:26 | LL | S1 { a: unsafe { &mut X1 } } - | ^^^^^^^ mutable reference of mutable static + | ^^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of_mut!` instead to create a raw pointer | LL | S1 { a: unsafe { addr_of_mut!(X1) } } | ~~~~~~~~~~~~~~~~ diff --git a/tests/ui/static/reference-of-mut-static-safe.e2021.stderr b/tests/ui/static/reference-of-mut-static-safe.e2021.stderr deleted file mode 100644 index 16f47ace3a930..0000000000000 --- a/tests/ui/static/reference-of-mut-static-safe.e2021.stderr +++ /dev/null @@ -1,26 +0,0 @@ -warning: shared reference of mutable static is discouraged - --> $DIR/reference-of-mut-static-safe.rs:9:14 - | -LL | let _x = &X; - | ^^ shared reference of mutable static - | - = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | let _x = addr_of!(X); - | ~~~~~~~~~~~ - -error[E0133]: use of mutable static is unsafe and requires unsafe function or block - --> $DIR/reference-of-mut-static-safe.rs:9:15 - | -LL | let _x = &X; - | ^ use of mutable static - | - = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior - -error: aborting due to 1 previous error; 1 warning emitted - -For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/static/reference-of-mut-static-safe.e2024.stderr b/tests/ui/static/reference-of-mut-static-safe.e2024.stderr deleted file mode 100644 index 53f81179de55a..0000000000000 --- a/tests/ui/static/reference-of-mut-static-safe.e2024.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0796]: reference of mutable static is disallowed - --> $DIR/reference-of-mut-static-safe.rs:9:14 - | -LL | let _x = &X; - | ^^ reference of mutable static - | - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | let _x = addr_of!(X); - | ~~~~~~~~~~~ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0796`. diff --git a/tests/ui/static/reference-of-mut-static-unsafe-fn.rs b/tests/ui/static/reference-of-mut-static-unsafe-fn.rs deleted file mode 100644 index 6b1e77850e50d..0000000000000 --- a/tests/ui/static/reference-of-mut-static-unsafe-fn.rs +++ /dev/null @@ -1,23 +0,0 @@ -// compile-flags: --edition 2024 -Z unstable-options - -fn main() {} - -unsafe fn _foo() { - static mut X: i32 = 1; - static mut Y: i32 = 1; - - let _y = &X; - //~^ ERROR reference of mutable static is disallowed - - let ref _a = X; - //~^ ERROR reference of mutable static is disallowed - - let (_b, _c) = (&X, &Y); - //~^ ERROR reference of mutable static is disallowed - //~^^ ERROR reference of mutable static is disallowed - - foo(&X); - //~^ ERROR reference of mutable static is disallowed -} - -fn foo<'a>(_x: &'a i32) {} diff --git a/tests/ui/static/reference-of-mut-static-unsafe-fn.stderr b/tests/ui/static/reference-of-mut-static-unsafe-fn.stderr deleted file mode 100644 index 5c6fdedfa96f7..0000000000000 --- a/tests/ui/static/reference-of-mut-static-unsafe-fn.stderr +++ /dev/null @@ -1,63 +0,0 @@ -error[E0796]: reference of mutable static is disallowed - --> $DIR/reference-of-mut-static-unsafe-fn.rs:9:14 - | -LL | let _y = &X; - | ^^ reference of mutable static - | - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | let _y = addr_of!(X); - | ~~~~~~~~~~~ - -error[E0796]: reference of mutable static is disallowed - --> $DIR/reference-of-mut-static-unsafe-fn.rs:12:18 - | -LL | let ref _a = X; - | ^ reference of mutable static - | - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | let ref _a = addr_of!(X); - | ~~~~~~~~~~~ - -error[E0796]: reference of mutable static is disallowed - --> $DIR/reference-of-mut-static-unsafe-fn.rs:15:21 - | -LL | let (_b, _c) = (&X, &Y); - | ^^ reference of mutable static - | - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | let (_b, _c) = (addr_of!(X), &Y); - | ~~~~~~~~~~~ - -error[E0796]: reference of mutable static is disallowed - --> $DIR/reference-of-mut-static-unsafe-fn.rs:15:25 - | -LL | let (_b, _c) = (&X, &Y); - | ^^ reference of mutable static - | - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | let (_b, _c) = (&X, addr_of!(Y)); - | ~~~~~~~~~~~ - -error[E0796]: reference of mutable static is disallowed - --> $DIR/reference-of-mut-static-unsafe-fn.rs:19:9 - | -LL | foo(&X); - | ^^ reference of mutable static - | - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | foo(addr_of!(X)); - | ~~~~~~~~~~~ - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0796`. diff --git a/tests/ui/static/reference-of-mut-static.e2021.stderr b/tests/ui/static/reference-of-mut-static.e2021.stderr deleted file mode 100644 index 77a6b3d304bdb..0000000000000 --- a/tests/ui/static/reference-of-mut-static.e2021.stderr +++ /dev/null @@ -1,91 +0,0 @@ -error: shared reference of mutable static is discouraged - --> $DIR/reference-of-mut-static.rs:16:18 - | -LL | let _y = &X; - | ^^ shared reference of mutable static - | - = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -note: the lint level is defined here - --> $DIR/reference-of-mut-static.rs:6:9 - | -LL | #![deny(static_mut_ref)] - | ^^^^^^^^^^^^^^ -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | let _y = addr_of!(X); - | ~~~~~~~~~~~ - -error: mutable reference of mutable static is discouraged - --> $DIR/reference-of-mut-static.rs:20:18 - | -LL | let _y = &mut X; - | ^^^^^^ mutable reference of mutable static - | - = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer - | -LL | let _y = addr_of_mut!(X); - | ~~~~~~~~~~~~~~~ - -error: shared reference of mutable static is discouraged - --> $DIR/reference-of-mut-static.rs:28:22 - | -LL | let ref _a = X; - | ^ shared reference of mutable static - | - = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | let ref _a = addr_of!(X); - | ~~~~~~~~~~~ - -error: shared reference of mutable static is discouraged - --> $DIR/reference-of-mut-static.rs:32:25 - | -LL | let (_b, _c) = (&X, &Y); - | ^^ shared reference of mutable static - | - = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | let (_b, _c) = (addr_of!(X), &Y); - | ~~~~~~~~~~~ - -error: shared reference of mutable static is discouraged - --> $DIR/reference-of-mut-static.rs:32:29 - | -LL | let (_b, _c) = (&X, &Y); - | ^^ shared reference of mutable static - | - = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | let (_b, _c) = (&X, addr_of!(Y)); - | ~~~~~~~~~~~ - -error: shared reference of mutable static is discouraged - --> $DIR/reference-of-mut-static.rs:38:13 - | -LL | foo(&X); - | ^^ shared reference of mutable static - | - = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | foo(addr_of!(X)); - | ~~~~~~~~~~~ - -error: aborting due to 6 previous errors - diff --git a/tests/ui/static/reference-of-mut-static.e2024.stderr b/tests/ui/static/reference-of-mut-static.e2024.stderr deleted file mode 100644 index f445ec65a5d24..0000000000000 --- a/tests/ui/static/reference-of-mut-static.e2024.stderr +++ /dev/null @@ -1,75 +0,0 @@ -error[E0796]: reference of mutable static is disallowed - --> $DIR/reference-of-mut-static.rs:16:18 - | -LL | let _y = &X; - | ^^ reference of mutable static - | - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | let _y = addr_of!(X); - | ~~~~~~~~~~~ - -error[E0796]: reference of mutable static is disallowed - --> $DIR/reference-of-mut-static.rs:20:18 - | -LL | let _y = &mut X; - | ^^^^^^ reference of mutable static - | - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer - | -LL | let _y = addr_of_mut!(X); - | ~~~~~~~~~~~~~~~ - -error[E0796]: reference of mutable static is disallowed - --> $DIR/reference-of-mut-static.rs:28:22 - | -LL | let ref _a = X; - | ^ reference of mutable static - | - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | let ref _a = addr_of!(X); - | ~~~~~~~~~~~ - -error[E0796]: reference of mutable static is disallowed - --> $DIR/reference-of-mut-static.rs:32:25 - | -LL | let (_b, _c) = (&X, &Y); - | ^^ reference of mutable static - | - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | let (_b, _c) = (addr_of!(X), &Y); - | ~~~~~~~~~~~ - -error[E0796]: reference of mutable static is disallowed - --> $DIR/reference-of-mut-static.rs:32:29 - | -LL | let (_b, _c) = (&X, &Y); - | ^^ reference of mutable static - | - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | let (_b, _c) = (&X, addr_of!(Y)); - | ~~~~~~~~~~~ - -error[E0796]: reference of mutable static is disallowed - --> $DIR/reference-of-mut-static.rs:38:13 - | -LL | foo(&X); - | ^^ reference of mutable static - | - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer - | -LL | foo(addr_of!(X)); - | ~~~~~~~~~~~ - -error: aborting due to 6 previous errors - -For more information about this error, try `rustc --explain E0796`. diff --git a/tests/ui/static/reference-of-mut-static.rs b/tests/ui/static/reference-of-mut-static.rs deleted file mode 100644 index 01a3b1fbd9b51..0000000000000 --- a/tests/ui/static/reference-of-mut-static.rs +++ /dev/null @@ -1,50 +0,0 @@ -// revisions: e2021 e2024 - -// [e2021] edition:2021 -// [e2024] compile-flags: --edition 2024 -Z unstable-options - -#![deny(static_mut_ref)] - -use std::ptr::{addr_of, addr_of_mut}; - -fn main() { - static mut X: i32 = 1; - - static mut Y: i32 = 1; - - unsafe { - let _y = &X; - //[e2024]~^ ERROR reference of mutable static is disallowed - //[e2021]~^^ ERROR shared reference of mutable static is discouraged [static_mut_ref] - - let _y = &mut X; - //[e2024]~^ ERROR reference of mutable static is disallowed - //[e2021]~^^ ERROR mutable reference of mutable static is discouraged [static_mut_ref] - - let _z = addr_of_mut!(X); - - let _p = addr_of!(X); - - let ref _a = X; - //[e2024]~^ ERROR reference of mutable static is disallowed - //[e2021]~^^ ERROR shared reference of mutable static is discouraged [static_mut_ref] - - let (_b, _c) = (&X, &Y); - //[e2024]~^ ERROR reference of mutable static is disallowed - //[e2021]~^^ ERROR shared reference of mutable static is discouraged [static_mut_ref] - //[e2024]~^^^ ERROR reference of mutable static is disallowed - //[e2021]~^^^^ ERROR shared reference of mutable static is discouraged [static_mut_ref] - - foo(&X); - //[e2024]~^ ERROR reference of mutable static is disallowed - //[e2021]~^^ ERROR shared reference of mutable static is discouraged [static_mut_ref] - - static mut Z: &[i32; 3] = &[0, 1, 2]; - - let _ = Z.len(); - let _ = Z[0]; - let _ = format!("{:?}", Z); - } -} - -fn foo<'a>(_x: &'a i32) {} diff --git a/tests/ui/static/reference-to-mut-static-safe.e2021.stderr b/tests/ui/static/reference-to-mut-static-safe.e2021.stderr new file mode 100644 index 0000000000000..9ea34290e36d6 --- /dev/null +++ b/tests/ui/static/reference-to-mut-static-safe.e2021.stderr @@ -0,0 +1,26 @@ +warning: creating a shared reference to mutable static is discouraged + --> $DIR/reference-to-mut-static-safe.rs:9:14 + | +LL | let _x = &X; + | ^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of!` instead to create a raw pointer + | +LL | let _x = addr_of!(X); + | ~~~~~~~~~~~ + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/reference-to-mut-static-safe.rs:9:15 + | +LL | let _x = &X; + | ^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/static/reference-to-mut-static-safe.e2024.stderr b/tests/ui/static/reference-to-mut-static-safe.e2024.stderr new file mode 100644 index 0000000000000..39575441422d4 --- /dev/null +++ b/tests/ui/static/reference-to-mut-static-safe.e2024.stderr @@ -0,0 +1,15 @@ +error[E0796]: creating a shared reference to a mutable static + --> $DIR/reference-to-mut-static-safe.rs:9:14 + | +LL | let _x = &X; + | ^^ sharedreference to mutable static + | + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let _x = addr_of!(X); + | ~~~~~~~~~~~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0796`. diff --git a/tests/ui/static/reference-of-mut-static-safe.rs b/tests/ui/static/reference-to-mut-static-safe.rs similarity index 62% rename from tests/ui/static/reference-of-mut-static-safe.rs rename to tests/ui/static/reference-to-mut-static-safe.rs index 5cb1a03bef512..cc3ef63a2ace3 100644 --- a/tests/ui/static/reference-of-mut-static-safe.rs +++ b/tests/ui/static/reference-to-mut-static-safe.rs @@ -7,7 +7,7 @@ fn main() { static mut X: i32 = 1; let _x = &X; - //[e2024]~^ reference of mutable static is disallowed [E0796] + //[e2024]~^ creating a shared reference to a mutable static [E0796] //[e2021]~^^ use of mutable static is unsafe and requires unsafe function or block [E0133] - //[e2021]~^^^ shared reference of mutable static is discouraged [static_mut_ref] + //[e2021]~^^^ shared reference to mutable static is discouraged [static_mut_refs] } diff --git a/tests/ui/static/reference-to-mut-static-unsafe-fn.rs b/tests/ui/static/reference-to-mut-static-unsafe-fn.rs new file mode 100644 index 0000000000000..737fcb996af18 --- /dev/null +++ b/tests/ui/static/reference-to-mut-static-unsafe-fn.rs @@ -0,0 +1,26 @@ +// compile-flags: --edition 2024 -Z unstable-options + +fn main() {} + +unsafe fn _foo() { + static mut X: i32 = 1; + static mut Y: i32 = 1; + + let _y = &X; + //~^ ERROR creating a shared reference to a mutable static [E0796] + + let ref _a = X; + //~^ ERROR creating a shared reference to a mutable static [E0796] + + let ref mut _a = X; + //~^ ERROR creating a mutable reference to a mutable static [E0796] + + let (_b, _c) = (&X, &mut Y); + //~^ ERROR creating a shared reference to a mutable static [E0796] + //~^^ ERROR creating a mutable reference to a mutable static [E0796] + + foo(&X); + //~^ ERROR creating a shared reference to a mutable static [E0796] +} + +fn foo<'a>(_x: &'a i32) {} diff --git a/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr b/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr new file mode 100644 index 0000000000000..439a205a5f415 --- /dev/null +++ b/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr @@ -0,0 +1,75 @@ +error[E0796]: creating a shared reference to a mutable static + --> $DIR/reference-to-mut-static-unsafe-fn.rs:9:14 + | +LL | let _y = &X; + | ^^ sharedreference to mutable static + | + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let _y = addr_of!(X); + | ~~~~~~~~~~~ + +error[E0796]: creating a shared reference to a mutable static + --> $DIR/reference-to-mut-static-unsafe-fn.rs:12:18 + | +LL | let ref _a = X; + | ^ sharedreference to mutable static + | + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let ref _a = addr_of!(X); + | ~~~~~~~~~~~ + +error[E0796]: creating a mutable reference to a mutable static + --> $DIR/reference-to-mut-static-unsafe-fn.rs:15:22 + | +LL | let ref mut _a = X; + | ^ mutablereference to mutable static + | + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior +help: use `addr_of_mut!` instead to create a raw pointer + | +LL | let ref mut _a = addr_of_mut!(X); + | ~~~~~~~~~~~~~~~ + +error[E0796]: creating a shared reference to a mutable static + --> $DIR/reference-to-mut-static-unsafe-fn.rs:18:21 + | +LL | let (_b, _c) = (&X, &mut Y); + | ^^ sharedreference to mutable static + | + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let (_b, _c) = (addr_of!(X), &mut Y); + | ~~~~~~~~~~~ + +error[E0796]: creating a mutable reference to a mutable static + --> $DIR/reference-to-mut-static-unsafe-fn.rs:18:25 + | +LL | let (_b, _c) = (&X, &mut Y); + | ^^^^^^ mutablereference to mutable static + | + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior +help: use `addr_of_mut!` instead to create a raw pointer + | +LL | let (_b, _c) = (&X, addr_of_mut!(Y)); + | ~~~~~~~~~~~~~~~ + +error[E0796]: creating a shared reference to a mutable static + --> $DIR/reference-to-mut-static-unsafe-fn.rs:22:9 + | +LL | foo(&X); + | ^^ sharedreference to mutable static + | + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | foo(addr_of!(X)); + | ~~~~~~~~~~~ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0796`. diff --git a/tests/ui/static/reference-to-mut-static.e2021.stderr b/tests/ui/static/reference-to-mut-static.e2021.stderr new file mode 100644 index 0000000000000..f477e5ac6c5c2 --- /dev/null +++ b/tests/ui/static/reference-to-mut-static.e2021.stderr @@ -0,0 +1,91 @@ +error: creating a shared reference to mutable static is discouraged + --> $DIR/reference-to-mut-static.rs:16:18 + | +LL | let _y = &X; + | ^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +note: the lint level is defined here + --> $DIR/reference-to-mut-static.rs:6:9 + | +LL | #![deny(static_mut_refs)] + | ^^^^^^^^^^^^^^^ +help: use `addr_of!` instead to create a raw pointer + | +LL | let _y = addr_of!(X); + | ~~~~~~~~~~~ + +error: creating a mutable reference to mutable static is discouraged + --> $DIR/reference-to-mut-static.rs:20:18 + | +LL | let _y = &mut X; + | ^^^^^^ mutable reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior +help: use `addr_of_mut!` instead to create a raw pointer + | +LL | let _y = addr_of_mut!(X); + | ~~~~~~~~~~~~~~~ + +error: creating a shared reference to mutable static is discouraged + --> $DIR/reference-to-mut-static.rs:28:22 + | +LL | let ref _a = X; + | ^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let ref _a = addr_of!(X); + | ~~~~~~~~~~~ + +error: creating a shared reference to mutable static is discouraged + --> $DIR/reference-to-mut-static.rs:32:25 + | +LL | let (_b, _c) = (&X, &Y); + | ^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let (_b, _c) = (addr_of!(X), &Y); + | ~~~~~~~~~~~ + +error: creating a shared reference to mutable static is discouraged + --> $DIR/reference-to-mut-static.rs:32:29 + | +LL | let (_b, _c) = (&X, &Y); + | ^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let (_b, _c) = (&X, addr_of!(Y)); + | ~~~~~~~~~~~ + +error: creating a shared reference to mutable static is discouraged + --> $DIR/reference-to-mut-static.rs:38:13 + | +LL | foo(&X); + | ^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | foo(addr_of!(X)); + | ~~~~~~~~~~~ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/static/reference-to-mut-static.e2024.stderr b/tests/ui/static/reference-to-mut-static.e2024.stderr new file mode 100644 index 0000000000000..12af318572d91 --- /dev/null +++ b/tests/ui/static/reference-to-mut-static.e2024.stderr @@ -0,0 +1,75 @@ +error[E0796]: creating a shared reference to a mutable static + --> $DIR/reference-to-mut-static.rs:16:18 + | +LL | let _y = &X; + | ^^ sharedreference to mutable static + | + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let _y = addr_of!(X); + | ~~~~~~~~~~~ + +error[E0796]: creating a mutable reference to a mutable static + --> $DIR/reference-to-mut-static.rs:20:18 + | +LL | let _y = &mut X; + | ^^^^^^ mutablereference to mutable static + | + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior +help: use `addr_of_mut!` instead to create a raw pointer + | +LL | let _y = addr_of_mut!(X); + | ~~~~~~~~~~~~~~~ + +error[E0796]: creating a shared reference to a mutable static + --> $DIR/reference-to-mut-static.rs:28:22 + | +LL | let ref _a = X; + | ^ sharedreference to mutable static + | + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let ref _a = addr_of!(X); + | ~~~~~~~~~~~ + +error[E0796]: creating a shared reference to a mutable static + --> $DIR/reference-to-mut-static.rs:32:25 + | +LL | let (_b, _c) = (&X, &Y); + | ^^ sharedreference to mutable static + | + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let (_b, _c) = (addr_of!(X), &Y); + | ~~~~~~~~~~~ + +error[E0796]: creating a shared reference to a mutable static + --> $DIR/reference-to-mut-static.rs:32:29 + | +LL | let (_b, _c) = (&X, &Y); + | ^^ sharedreference to mutable static + | + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let (_b, _c) = (&X, addr_of!(Y)); + | ~~~~~~~~~~~ + +error[E0796]: creating a shared reference to a mutable static + --> $DIR/reference-to-mut-static.rs:38:13 + | +LL | foo(&X); + | ^^ sharedreference to mutable static + | + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | foo(addr_of!(X)); + | ~~~~~~~~~~~ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0796`. diff --git a/tests/ui/static/reference-to-mut-static.rs b/tests/ui/static/reference-to-mut-static.rs new file mode 100644 index 0000000000000..b9aecd5185a09 --- /dev/null +++ b/tests/ui/static/reference-to-mut-static.rs @@ -0,0 +1,50 @@ +// revisions: e2021 e2024 + +// [e2021] edition:2021 +// [e2024] compile-flags: --edition 2024 -Z unstable-options + +#![deny(static_mut_refs)] + +use std::ptr::{addr_of, addr_of_mut}; + +fn main() { + static mut X: i32 = 1; + + static mut Y: i32 = 1; + + unsafe { + let _y = &X; + //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796] + //[e2021]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs] + + let _y = &mut X; + //[e2024]~^ ERROR creating a mutable reference to a mutable static [E0796] + //[e2021]~^^ ERROR mutable reference to mutable static is discouraged [static_mut_refs] + + let _z = addr_of_mut!(X); + + let _p = addr_of!(X); + + let ref _a = X; + //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796] + //[e2021]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs] + + let (_b, _c) = (&X, &Y); + //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796] + //[e2021]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs] + //[e2024]~^^^ ERROR creating a shared reference to a mutable static [E0796] + //[e2021]~^^^^ ERROR shared reference to mutable static is discouraged [static_mut_refs] + + foo(&X); + //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796] + //[e2021]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs] + + static mut Z: &[i32; 3] = &[0, 1, 2]; + + let _ = Z.len(); + let _ = Z[0]; + let _ = format!("{:?}", Z); + } +} + +fn foo<'a>(_x: &'a i32) {} diff --git a/tests/ui/static/safe-extern-statics-mut.rs b/tests/ui/static/safe-extern-statics-mut.rs index 1c0662e0a6cec..05cc6dd01917c 100644 --- a/tests/ui/static/safe-extern-statics-mut.rs +++ b/tests/ui/static/safe-extern-statics-mut.rs @@ -10,8 +10,8 @@ extern "C" { fn main() { let b = B; //~ ERROR use of mutable static is unsafe let rb = &B; //~ ERROR use of mutable static is unsafe - //~^ WARN shared reference of mutable static is discouraged [static_mut_ref] + //~^ WARN shared reference to mutable static is discouraged [static_mut_refs] let xb = XB; //~ ERROR use of mutable static is unsafe let xrb = &XB; //~ ERROR use of mutable static is unsafe - //~^ WARN shared reference of mutable static is discouraged [static_mut_ref] + //~^ WARN shared reference to mutable static is discouraged [static_mut_refs] } diff --git a/tests/ui/static/safe-extern-statics-mut.stderr b/tests/ui/static/safe-extern-statics-mut.stderr index eda353ce6736f..9a4b651405f23 100644 --- a/tests/ui/static/safe-extern-statics-mut.stderr +++ b/tests/ui/static/safe-extern-statics-mut.stderr @@ -1,28 +1,28 @@ -warning: shared reference of mutable static is discouraged +warning: creating a shared reference to mutable static is discouraged --> $DIR/safe-extern-statics-mut.rs:12:14 | LL | let rb = &B; - | ^^ shared reference of mutable static + | ^^ shared reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of!` instead to create a raw pointer | LL | let rb = addr_of!(B); | ~~~~~~~~~~~ -warning: shared reference of mutable static is discouraged +warning: creating a shared reference to mutable static is discouraged --> $DIR/safe-extern-statics-mut.rs:15:15 | LL | let xrb = &XB; - | ^^^ shared reference of mutable static + | ^^^ shared reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior +help: use `addr_of!` instead to create a raw pointer | LL | let xrb = addr_of!(XB); | ~~~~~~~~~~~~ diff --git a/tests/ui/statics/issue-15261.rs b/tests/ui/statics/issue-15261.rs index 14422329b7dc8..a6f99bd13c605 100644 --- a/tests/ui/statics/issue-15261.rs +++ b/tests/ui/statics/issue-15261.rs @@ -7,6 +7,6 @@ static mut n_mut: usize = 0; static n: &'static usize = unsafe { &n_mut }; -//~^ WARN shared reference of mutable static is discouraged [static_mut_ref] +//~^ WARN shared reference to mutable static is discouraged [static_mut_refs] fn main() {} diff --git a/tests/ui/statics/issue-15261.stderr b/tests/ui/statics/issue-15261.stderr index 72d88ce1b3832..c31793f3d8f15 100644 --- a/tests/ui/statics/issue-15261.stderr +++ b/tests/ui/statics/issue-15261.stderr @@ -1,14 +1,14 @@ -warning: shared reference of mutable static is discouraged +warning: creating a shared reference to mutable static is discouraged --> $DIR/issue-15261.rs:9:37 | LL | static n: &'static usize = unsafe { &n_mut }; - | ^^^^^^ shared reference of mutable static + | ^^^^^^ shared reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of!` instead to create a raw pointer | LL | static n: &'static usize = unsafe { addr_of!(n_mut) }; | ~~~~~~~~~~~~~~~ diff --git a/tests/ui/statics/static-mut-xc.rs b/tests/ui/statics/static-mut-xc.rs index 2fc265e02eaa3..f242836eccfbc 100644 --- a/tests/ui/statics/static-mut-xc.rs +++ b/tests/ui/statics/static-mut-xc.rs @@ -26,9 +26,9 @@ unsafe fn run() { static_mut_xc::a = -3; assert_eq!(static_mut_xc::a, -3); static_bound(&static_mut_xc::a); - //~^ WARN shared reference of mutable static is discouraged [static_mut_ref] + //~^ WARN shared reference to mutable static is discouraged [static_mut_refs] static_bound_set(&mut static_mut_xc::a); - //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref] + //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs] } pub fn main() { diff --git a/tests/ui/statics/static-mut-xc.stderr b/tests/ui/statics/static-mut-xc.stderr index 37aa336bc50f7..d381328c07178 100644 --- a/tests/ui/statics/static-mut-xc.stderr +++ b/tests/ui/statics/static-mut-xc.stderr @@ -1,28 +1,28 @@ -warning: shared reference of mutable static is discouraged +warning: creating a shared reference to mutable static is discouraged --> $DIR/static-mut-xc.rs:28:18 | LL | static_bound(&static_mut_xc::a); - | ^^^^^^^^^^^^^^^^^ shared reference of mutable static + | ^^^^^^^^^^^^^^^^^ shared reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of!` instead to create a raw pointer | LL | static_bound(addr_of!(static_mut_xc::a)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~ -warning: mutable reference of mutable static is discouraged +warning: creating a mutable reference to mutable static is discouraged --> $DIR/static-mut-xc.rs:30:22 | LL | static_bound_set(&mut static_mut_xc::a); - | ^^^^^^^^^^^^^^^^^^^^^ mutable reference of mutable static + | ^^^^^^^^^^^^^^^^^^^^^ mutable reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior -help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior +help: use `addr_of_mut!` instead to create a raw pointer | LL | static_bound_set(addr_of_mut!(static_mut_xc::a)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/statics/static-recursive.rs b/tests/ui/statics/static-recursive.rs index 216beb0206d9c..52660888986da 100644 --- a/tests/ui/statics/static-recursive.rs +++ b/tests/ui/statics/static-recursive.rs @@ -1,7 +1,7 @@ // run-pass static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 }; -//~^ WARN shared reference of mutable static is discouraged [static_mut_ref] +//~^ WARN shared reference to mutable static is discouraged [static_mut_refs] struct StaticDoubleLinked { prev: &'static StaticDoubleLinked, diff --git a/tests/ui/statics/static-recursive.stderr b/tests/ui/statics/static-recursive.stderr index 15888e5c68d84..cd285c6c2a463 100644 --- a/tests/ui/statics/static-recursive.stderr +++ b/tests/ui/statics/static-recursive.stderr @@ -1,14 +1,14 @@ -warning: shared reference of mutable static is discouraged +warning: creating a shared reference to mutable static is discouraged --> $DIR/static-recursive.rs:3:36 | LL | static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 }; - | ^^ shared reference of mutable static + | ^^ shared reference to mutable static | = note: for more information, see issue #114447 - = note: reference of mutable static is a hard error from 2024 edition - = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior - = note: `#[warn(static_mut_ref)]` on by default -help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer + = note: this will be a hard error in the 2024 edition + = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of!` instead to create a raw pointer | LL | static mut S: *const u8 = unsafe { addr_of!(S) as *const *const u8 as *const u8 }; | ~~~~~~~~~~~ diff --git a/tests/ui/thread-local/thread-local-static.rs b/tests/ui/thread-local/thread-local-static.rs index a2c1954881f89..3da1b80a5dd5b 100644 --- a/tests/ui/thread-local/thread-local-static.rs +++ b/tests/ui/thread-local/thread-local-static.rs @@ -2,7 +2,7 @@ #![feature(thread_local)] #![feature(const_swap)] -#![allow(static_mut_ref)] +#![allow(static_mut_refs)] #[thread_local] static mut STATIC_VAR_2: [u32; 8] = [4; 8]; From 3b791a41f99f52d02fc1ebbd5ccd6a95ca52cd5a Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 23 Nov 2023 10:25:25 +0000 Subject: [PATCH 07/20] simplify codegen for trivially droppable types --- library/alloc/src/collections/vec_deque/drain.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index 0be274a3822d3..7d40ce65ad75b 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -96,8 +96,9 @@ impl Drop for Drain<'_, T, A> { struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { + #[inline] fn drop(&mut self) { - if self.0.remaining != 0 { + if mem::needs_drop::() && self.0.remaining != 0 { unsafe { // SAFETY: We just checked that `self.remaining != 0`. let (front, back) = self.0.as_slices(); @@ -158,7 +159,7 @@ impl Drop for Drain<'_, T, A> { } let guard = DropGuard(self); - if guard.0.remaining != 0 { + if mem::needs_drop::() && guard.0.remaining != 0 { unsafe { // SAFETY: We just checked that `self.remaining != 0`. let (front, back) = guard.0.as_slices(); From fe9bc1be27aa6d8feeab8f87e5c56d45e352f496 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 23 Nov 2023 10:41:35 +0000 Subject: [PATCH 08/20] reduce amount of math --- .../alloc/src/collections/vec_deque/drain.rs | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index 7d40ce65ad75b..aa5cc0fb1ce2b 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -27,8 +27,8 @@ pub struct Drain< drain_len: usize, // index into the logical array, not the physical one (always lies in [0..deque.len)) idx: usize, - // number of elements after the drain range - tail_len: usize, + // number of elements remaining after dropping the drain + new_len: usize, remaining: usize, // Needed to make Drain covariant over T _marker: PhantomData<&'a T>, @@ -41,12 +41,12 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { drain_len: usize, ) -> Self { let orig_len = mem::replace(&mut deque.len, drain_start); - let tail_len = orig_len - drain_start - drain_len; + let new_len = orig_len - drain_len; Drain { deque: NonNull::from(deque), drain_len, idx: drain_start, - tail_len, + new_len, remaining: drain_len, _marker: PhantomData, } @@ -79,7 +79,7 @@ impl fmt::Debug for Drain<'_, T, A> { f.debug_tuple("Drain") .field(&self.drain_len) .field(&self.idx) - .field(&self.tail_len) + .field(&self.new_len) .field(&self.remaining) .finish() } @@ -111,18 +111,16 @@ impl Drop for Drain<'_, T, A> { let drain_start = source_deque.len(); let drain_len = self.0.drain_len; - let drain_end = drain_start + drain_len; - - let orig_len = self.0.tail_len + drain_end; + let new_len = self.0.new_len; if T::IS_ZST { // no need to copy around any memory if T is a ZST - source_deque.len = orig_len - drain_len; + source_deque.len = new_len; return; } let head_len = drain_start; - let tail_len = self.0.tail_len; + let tail_len = new_len - head_len; match (head_len, tail_len) { (0, 0) => { @@ -131,10 +129,10 @@ impl Drop for Drain<'_, T, A> { } (0, _) => { source_deque.head = source_deque.to_physical_idx(drain_len); - source_deque.len = orig_len - drain_len; + source_deque.len = new_len; } (_, 0) => { - source_deque.len = orig_len - drain_len; + source_deque.len = new_len; } _ => unsafe { if head_len <= tail_len { @@ -144,14 +142,14 @@ impl Drop for Drain<'_, T, A> { head_len, ); source_deque.head = source_deque.to_physical_idx(drain_len); - source_deque.len = orig_len - drain_len; + source_deque.len = new_len; } else { source_deque.wrap_copy( source_deque.to_physical_idx(head_len + drain_len), source_deque.to_physical_idx(head_len), tail_len, ); - source_deque.len = orig_len - drain_len; + source_deque.len = new_len; } }, } From b13c926ea644bfa7a21353630e6d552836a61b00 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 23 Nov 2023 16:03:21 +0000 Subject: [PATCH 09/20] reduce branchiness --- .../alloc/src/collections/vec_deque/drain.rs | 53 ++++++++----------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index aa5cc0fb1ce2b..7a413ddf971d7 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -109,7 +109,6 @@ impl Drop for Drain<'_, T, A> { let source_deque = unsafe { self.0.deque.as_mut() }; - let drain_start = source_deque.len(); let drain_len = self.0.drain_len; let new_len = self.0.new_len; @@ -119,40 +118,32 @@ impl Drop for Drain<'_, T, A> { return; } - let head_len = drain_start; + let head_len = source_deque.len(); let tail_len = new_len - head_len; - match (head_len, tail_len) { - (0, 0) => { - source_deque.head = 0; - source_deque.len = 0; - } - (0, _) => { - source_deque.head = source_deque.to_physical_idx(drain_len); - source_deque.len = new_len; - } - (_, 0) => { - source_deque.len = new_len; + if head_len != 0 && tail_len != 0 { + let (src, dst, len); + if head_len < tail_len { + src = source_deque.head; + dst = source_deque.to_physical_idx(drain_len); + len = head_len; + } else { + src = source_deque.to_physical_idx(head_len + drain_len); + dst = source_deque.to_physical_idx(head_len); + len = tail_len; + }; + + unsafe { + source_deque.wrap_copy(src, dst, len); } - _ => unsafe { - if head_len <= tail_len { - source_deque.wrap_copy( - source_deque.head, - source_deque.to_physical_idx(drain_len), - head_len, - ); - source_deque.head = source_deque.to_physical_idx(drain_len); - source_deque.len = new_len; - } else { - source_deque.wrap_copy( - source_deque.to_physical_idx(head_len + drain_len), - source_deque.to_physical_idx(head_len), - tail_len, - ); - source_deque.len = new_len; - } - }, } + + if new_len == 0 { + source_deque.head = 0; + } else if head_len < tail_len { + source_deque.head = source_deque.to_physical_idx(drain_len); + } + source_deque.len = new_len; } } From 064f97260cb205bbf6657f9a54b5f4a112ca0ab0 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 23 Nov 2023 23:31:19 +0100 Subject: [PATCH 10/20] outline large copies --- .../alloc/src/collections/vec_deque/drain.rs | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index 7a413ddf971d7..bf8c9b2d47aed 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -121,7 +121,27 @@ impl Drop for Drain<'_, T, A> { let head_len = source_deque.len(); let tail_len = new_len - head_len; + // When draining at the front (`.drain(..n)`) or at the back (`.drain(n..)`), + // we don't need to copy any data. + // Outlining this function helps LLVM to eliminate the copies in these cases. if head_len != 0 && tail_len != 0 { + copy_data(source_deque, drain_len, head_len, tail_len); + } + + if new_len == 0 { + source_deque.head = 0; + } else if head_len < tail_len { + source_deque.head = source_deque.to_physical_idx(drain_len); + } + source_deque.len = new_len; + + #[cold] + fn copy_data( + source_deque: &mut VecDeque, + drain_len: usize, + head_len: usize, + tail_len: usize, + ) { let (src, dst, len); if head_len < tail_len { src = source_deque.head; @@ -137,13 +157,6 @@ impl Drop for Drain<'_, T, A> { source_deque.wrap_copy(src, dst, len); } } - - if new_len == 0 { - source_deque.head = 0; - } else if head_len < tail_len { - source_deque.head = source_deque.to_physical_idx(drain_len); - } - source_deque.len = new_len; } } From a77d6b983d2e96d8405b1fe84128e72384d41df2 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 23 Nov 2023 23:11:22 +0100 Subject: [PATCH 11/20] add codegen test --- tests/codegen/vecdeque-drain.rs | 68 +++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 tests/codegen/vecdeque-drain.rs diff --git a/tests/codegen/vecdeque-drain.rs b/tests/codegen/vecdeque-drain.rs new file mode 100644 index 0000000000000..4a25a1c40f9a7 --- /dev/null +++ b/tests/codegen/vecdeque-drain.rs @@ -0,0 +1,68 @@ +// Check that draining at the front or back doesn't copy memory. + +// compile-flags: -O +// ignore-debug: the debug assertions get in the way + +#![crate_type = "lib"] + +use std::collections::VecDeque; + +// CHECK-LABEL: @clear +// CHECK-NOT: call +// CHECK-NOT: br +// CHECK: getelementptr inbounds +// CHECK-NEXT: call void @llvm.memset +// CHECK-NEXT: ret void +#[no_mangle] +pub fn clear(v: &mut VecDeque) { + v.drain(..); +} + +// CHECK-LABEL: @truncate +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK-NOT: br +// CHECK: ret void +#[no_mangle] +pub fn truncate(v: &mut VecDeque, n: usize) { + if n < v.len() { + v.drain(n..); + } +} + +// CHECK-LABEL: @advance +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK: br +// CHECK-NOT: call +// CHECK-NOT: br +// CHECK: ret void +#[no_mangle] +pub fn advance(v: &mut VecDeque, n: usize) { + if n < v.len() { + v.drain(..n); + } else { + v.clear(); + } +} + +// CHECK-LABEL: @remove +// CHECK: call +#[no_mangle] +pub fn remove(v: &mut VecDeque, a: usize, b: usize) { + v.drain(a..b); +} From da1c7f639d3d443cba4c05e18e7c58daa87fd572 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 11 Feb 2024 17:13:23 +0100 Subject: [PATCH 12/20] address review comments --- .../alloc/src/collections/vec_deque/drain.rs | 143 ++++++++++++------ 1 file changed, 99 insertions(+), 44 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index bf8c9b2d47aed..1373e60149274 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -95,6 +95,22 @@ impl Drop for Drain<'_, T, A> { fn drop(&mut self) { struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); + let guard = DropGuard(self); + + if mem::needs_drop::() && guard.0.remaining != 0 { + unsafe { + // SAFETY: We just checked that `self.remaining != 0`. + let (front, back) = guard.0.as_slices(); + // since idx is a logical index, we don't need to worry about wrapping. + guard.0.idx += front.len(); + guard.0.remaining -= front.len(); + ptr::drop_in_place(front); + guard.0.remaining = 0; + ptr::drop_in_place(back); + } + } + + // Dropping `guard` handles moving the remaining elements into place. impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { #[inline] fn drop(&mut self) { @@ -118,63 +134,102 @@ impl Drop for Drain<'_, T, A> { return; } - let head_len = source_deque.len(); - let tail_len = new_len - head_len; + let head_len = source_deque.len; // #elements in front of the drain + let tail_len = new_len - head_len; // #elements behind the drain + + // Next, we will fill the hole left by the drain with as few writes as possible. + // The code below handles the following control flow and reduces the amount of + // branches under the assumption that `head_len == 0 || tail_len == 0`, i.e. + // draining at the front or at the back of the dequeue is especially common. + // + // H = "head index" = `deque.head` + // h = elements in front of the drain + // d = elements in the drain + // t = elements behind the drain + // + // Note that the buffer may wrap at any point and the wrapping is handled by + // `wrap_copy` and `to_physical_idx`. + // + // Case 1: if `head_len == 0 && tail_len == 0` + // Everything was drained, reset the head index back to 0. + // H + // [ . . . . . d d d d . . . . . ] + // H + // [ . . . . . . . . . . . . . . ] + // + // Case 2: else if `tail_len == 0` + // Don't move data or the head index. + // H + // [ . . . h h h h d d d d . . . ] + // H + // [ . . . h h h h . . . . . . . ] + // + // Case 3: else if `head_len == 0` + // Don't move data, but move the head index. + // H + // [ . . . d d d d t t t t . . . ] + // H + // [ . . . . . . . t t t t . . . ] + // + // Case 4: else if `tail_len <= head_len` + // Move data, but not the head index. + // H + // [ . . h h h h d d d d t t . . ] + // H + // [ . . h h h h t t . . . . . . ] + // + // Case 5: else + // Move data and the head index. + // H + // [ . . h h d d d d t t t t . . ] + // H + // [ . . . . . . h h t t t t . . ] // When draining at the front (`.drain(..n)`) or at the back (`.drain(n..)`), - // we don't need to copy any data. - // Outlining this function helps LLVM to eliminate the copies in these cases. + // we don't need to copy any data. The number of elements copied would be 0. if head_len != 0 && tail_len != 0 { - copy_data(source_deque, drain_len, head_len, tail_len); + join_head_and_tail_wrapping(source_deque, drain_len, head_len, tail_len); + // Marking this function as cold helps LLVM to eliminate it entirely if + // this branch is never taken. + // We use `#[cold]` instead of `#[inline(never)]`, because inlining this + // function into the general case (`.drain(n..m)`) is fine. + // See `tests/codegen/vecdeque-drain.rs` for a test. + #[cold] + fn join_head_and_tail_wrapping( + source_deque: &mut VecDeque, + drain_len: usize, + head_len: usize, + tail_len: usize, + ) { + // Pick whether to move the head or the tail here. + let (src, dst, len); + if head_len < tail_len { + src = source_deque.head; + dst = source_deque.to_physical_idx(drain_len); + len = head_len; + } else { + src = source_deque.to_physical_idx(head_len + drain_len); + dst = source_deque.to_physical_idx(head_len); + len = tail_len; + }; + + unsafe { + source_deque.wrap_copy(src, dst, len); + } + } } if new_len == 0 { + // Special case: If the entire dequeue was drained, reset the head back to 0, + // like `.clear()` does. source_deque.head = 0; } else if head_len < tail_len { + // If we moved the head above, then we need to adjust the head index here. source_deque.head = source_deque.to_physical_idx(drain_len); } source_deque.len = new_len; - - #[cold] - fn copy_data( - source_deque: &mut VecDeque, - drain_len: usize, - head_len: usize, - tail_len: usize, - ) { - let (src, dst, len); - if head_len < tail_len { - src = source_deque.head; - dst = source_deque.to_physical_idx(drain_len); - len = head_len; - } else { - src = source_deque.to_physical_idx(head_len + drain_len); - dst = source_deque.to_physical_idx(head_len); - len = tail_len; - }; - - unsafe { - source_deque.wrap_copy(src, dst, len); - } - } - } - } - - let guard = DropGuard(self); - if mem::needs_drop::() && guard.0.remaining != 0 { - unsafe { - // SAFETY: We just checked that `self.remaining != 0`. - let (front, back) = guard.0.as_slices(); - // since idx is a logical index, we don't need to worry about wrapping. - guard.0.idx += front.len(); - guard.0.remaining -= front.len(); - ptr::drop_in_place(front); - guard.0.remaining = 0; - ptr::drop_in_place(back); } } - - // Dropping `guard` handles moving the remaining elements into place. } } From cc7b4e02beecdb75b3b5ee348840b50d06ad67c1 Mon Sep 17 00:00:00 2001 From: Adam Gemmell Date: Thu, 25 Jan 2024 15:28:23 +0000 Subject: [PATCH 13/20] Update aarch64 target feature docs to match LLVM --- compiler/rustc_target/src/target_features.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 04943fa3879fb..2b7ac68c21dfb 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -86,7 +86,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Stability)] = &[ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-start - // FEAT_AES + // FEAT_AES & FEAT_PMULL ("aes", Stable), // FEAT_BF16 ("bf16", Stable), @@ -124,7 +124,7 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability)] = &[ ("lor", Stable), // FEAT_LSE ("lse", Stable), - // FEAT_MTE + // FEAT_MTE & FEAT_MTE2 ("mte", Stable), // FEAT_AdvSimd & FEAT_FP ("neon", Stable), @@ -138,7 +138,7 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability)] = &[ ("pmuv3", Stable), // FEAT_RAND ("rand", Stable), - // FEAT_RAS + // FEAT_RAS & FEAT_RASv1p1 ("ras", Stable), // FEAT_RCPC ("rcpc", Stable), @@ -156,7 +156,7 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability)] = &[ ("sm4", Stable), // FEAT_SPE ("spe", Stable), - // FEAT_SSBS + // FEAT_SSBS & FEAT_SSBS2 ("ssbs", Stable), // FEAT_SVE ("sve", Stable), From 5d65b1954ef4dc6ea3a1260e1bce31524fc286f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 15 Feb 2024 00:00:00 +0000 Subject: [PATCH 14/20] Avoid debug logging entire MIR body If there is a need to examine the MIR body there is -Zmir-dump. --- compiler/rustc_mir_transform/src/lib.rs | 1 - compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index b4fa7f3bea6a0..fb174192b8492 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -653,7 +653,6 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { debug!("about to call mir_drops_elaborated..."); let body = tcx.mir_drops_elaborated_and_const_checked(did).steal(); let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::NotConst); - debug!("body: {:#?}", body); if body.tainted_by_errors.is_some() { return body; diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 095119e2e3ff8..fb52bfa468a01 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -15,7 +15,8 @@ impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { } fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - debug!("remove_noop_landing_pads({:?})", body); + let def_id = body.source.def_id(); + debug!(?def_id); self.remove_nop_landing_pads(body) } } @@ -81,8 +82,6 @@ impl RemoveNoopLandingPads { } fn remove_nop_landing_pads(&self, body: &mut Body<'_>) { - debug!("body: {:#?}", body); - // Skip the pass if there are no blocks with a resume terminator. let has_resume = body .basic_blocks From c763f833d14d31fbe63e0b26370a23a51b4f11c5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Feb 2024 14:34:42 +0000 Subject: [PATCH 15/20] Only point out non-diverging arms for match suggestions --- compiler/rustc_hir_typeck/src/_match.rs | 14 +++++------ .../src/infer/error_reporting/mod.rs | 13 ++++++---- .../src/infer/error_reporting/suggest.rs | 11 +++++--- compiler/rustc_middle/src/traits/mod.rs | 2 +- .../ui/match/dont-highlight-diverging-arms.rs | 17 +++++++++++++ .../dont-highlight-diverging-arms.stderr | 25 +++++++++++++++++++ .../match/match-arm-resolving-to-never.stderr | 5 +++- 7 files changed, 69 insertions(+), 18 deletions(-) create mode 100644 tests/ui/match/dont-highlight-diverging-arms.rs create mode 100644 tests/ui/match/dont-highlight-diverging-arms.stderr diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 0311aa94cd485..214066814221b 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -79,7 +79,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { CoerceMany::with_coercion_sites(coerce_first, arms) }; - let mut other_arms = vec![]; // Used only for diagnostics. + let mut prior_non_diverging_arms = vec![]; // Used only for diagnostics. let mut prior_arm = None; for arm in arms { if let Some(e) = &arm.guard { @@ -120,7 +120,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { scrut_span: scrut.span, scrut_hir_id: scrut.hir_id, source: match_src, - prior_arms: other_arms.clone(), + prior_non_diverging_arms: prior_non_diverging_arms.clone(), opt_suggest_box_span, })), ), @@ -142,16 +142,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false, ); - other_arms.push(arm_span); - if other_arms.len() > 5 { - other_arms.remove(0); - } - if !arm_ty.is_never() { // When a match arm has type `!`, then it doesn't influence the expected type for // the following arm. If all of the prior arms are `!`, then the influence comes // from elsewhere and we shouldn't point to any previous arm. prior_arm = Some((arm_block_id, arm_ty, arm_span)); + + prior_non_diverging_arms.push(arm_span); + if prior_non_diverging_arms.len() > 5 { + prior_non_diverging_arms.remove(0); + } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index b953b25d6c4cf..aa92f91f24f83 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -777,7 +777,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { prior_arm_span, prior_arm_ty, source, - ref prior_arms, + ref prior_non_diverging_arms, opt_suggest_box_span, scrut_span, scrut_hir_id, @@ -817,12 +817,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }); let source_map = self.tcx.sess.source_map(); let mut any_multiline_arm = source_map.is_multiline(arm_span); - if prior_arms.len() <= 4 { - for sp in prior_arms { + if prior_non_diverging_arms.len() <= 4 { + for sp in prior_non_diverging_arms { any_multiline_arm |= source_map.is_multiline(*sp); err.span_label(*sp, format!("this is found to be of type `{t}`")); } - } else if let Some(sp) = prior_arms.last() { + } else if let Some(sp) = prior_non_diverging_arms.last() { any_multiline_arm |= source_map.is_multiline(*sp); err.span_label( *sp, @@ -865,7 +865,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.suggest_boxing_for_return_impl_trait( err, ret_sp, - prior_arms.iter().chain(std::iter::once(&arm_span)).copied(), + prior_non_diverging_arms + .iter() + .chain(std::iter::once(&arm_span)) + .copied(), ); } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 248e1c0fcc878..c6f6c32fe60c2 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -203,10 +203,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }) } ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { - prior_arms, + prior_non_diverging_arms, .. }) => { - if let [.., arm_span] = &prior_arms[..] { + if let [.., arm_span] = &prior_non_diverging_arms[..] { Some(ConsiderAddingAwait::BothFuturesSugg { first: arm_span.shrink_to_hi(), second: exp_span.shrink_to_hi(), @@ -234,11 +234,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() }) } ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { - ref prior_arms, + ref prior_non_diverging_arms, .. }) => Some({ ConsiderAddingAwait::FutureSuggMultiple { - spans: prior_arms.iter().map(|arm| arm.shrink_to_hi()).collect(), + spans: prior_non_diverging_arms + .iter() + .map(|arm| arm.shrink_to_hi()) + .collect(), } }), _ => None, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 8e5f026b4c27c..683610ba3b6a3 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -571,7 +571,7 @@ pub struct MatchExpressionArmCause<'tcx> { pub scrut_span: Span, pub scrut_hir_id: hir::HirId, pub source: hir::MatchSource, - pub prior_arms: Vec, + pub prior_non_diverging_arms: Vec, pub opt_suggest_box_span: Option, } diff --git a/tests/ui/match/dont-highlight-diverging-arms.rs b/tests/ui/match/dont-highlight-diverging-arms.rs new file mode 100644 index 0000000000000..dc3b4ca9caad6 --- /dev/null +++ b/tests/ui/match/dont-highlight-diverging-arms.rs @@ -0,0 +1,17 @@ +fn main() { + let m = 42u32; + + let value = 'out: { + match m { + 1 => break 'out Some(1u16), + 2 => Some(2u16), + 3 => break 'out Some(3u16), + 4 => break 'out Some(4u16), + 5 => break 'out Some(5u16), + _ => {} + //~^ ERROR `match` arms have incompatible types + } + + None + }; +} \ No newline at end of file diff --git a/tests/ui/match/dont-highlight-diverging-arms.stderr b/tests/ui/match/dont-highlight-diverging-arms.stderr new file mode 100644 index 0000000000000..886c1af13fa37 --- /dev/null +++ b/tests/ui/match/dont-highlight-diverging-arms.stderr @@ -0,0 +1,25 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/dont-highlight-diverging-arms.rs:11:18 + | +LL | / match m { +LL | | 1 => break 'out Some(1u16), +LL | | 2 => Some(2u16), + | | ---------- this is found to be of type `Option` +LL | | 3 => break 'out Some(3u16), +... | +LL | | _ => {} + | | ^^ expected `Option`, found `()` +LL | | +LL | | } + | |_________- `match` arms have incompatible types + | + = note: expected enum `Option` + found unit type `()` +help: consider using a semicolon here, but this will discard any values in the match arms + | +LL | }; + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-arm-resolving-to-never.stderr b/tests/ui/match/match-arm-resolving-to-never.stderr index 6cbdf03d4c27d..fd0c8708b8ca3 100644 --- a/tests/ui/match/match-arm-resolving-to-never.stderr +++ b/tests/ui/match/match-arm-resolving-to-never.stderr @@ -3,11 +3,14 @@ error[E0308]: `match` arms have incompatible types | LL | / match E::F { LL | | E::A => 1, + | | - this is found to be of type `{integer}` LL | | E::B => 2, + | | - this is found to be of type `{integer}` LL | | E::C => 3, + | | - this is found to be of type `{integer}` LL | | E::D => 4, + | | - this is found to be of type `{integer}` LL | | E::E => unimplemented!(""), - | | ------------------ this and all prior arms are found to be of type `{integer}` LL | | E::F => "", | | ^^ expected integer, found `&str` LL | | }; From acb201af54e15b1beebb5b8a6691f6c851afe177 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 14 Feb 2024 23:52:57 +0000 Subject: [PATCH 16/20] make better async fn kind errors --- compiler/rustc_trait_selection/messages.ftl | 12 +- compiler/rustc_trait_selection/src/errors.rs | 10 ++ .../error_reporting/type_err_ctxt_ext.rs | 123 ++++++++++++++---- tests/ui/async-await/async-closures/not-fn.rs | 15 +++ .../async-await/async-closures/not-fn.stderr | 16 +++ .../async-closures/wrong-fn-kind.rs | 3 +- .../async-closures/wrong-fn-kind.stderr | 12 +- 7 files changed, 154 insertions(+), 37 deletions(-) create mode 100644 tests/ui/async-await/async-closures/not-fn.rs create mode 100644 tests/ui/async-await/async-closures/not-fn.stderr diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index 41db8059cbee3..0dcba0e05f76f 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -8,14 +8,16 @@ trait_selection_adjust_signature_remove_borrow = consider adjusting the signatur *[other] arguments } -trait_selection_closure_fn_mut_label = closure is `FnMut` because it mutates the variable `{$place}` here +trait_selection_async_closure_not_fn = async closure does not implement `{$kind}` because it captures state from its environment -trait_selection_closure_fn_once_label = closure is `FnOnce` because it moves the variable `{$place}` out of its environment +trait_selection_closure_fn_mut_label = closure is `{$trait_prefix}FnMut` because it mutates the variable `{$place}` here -trait_selection_closure_kind_mismatch = expected a closure that implements the `{$expected}` trait, but this closure only implements `{$found}` - .label = this closure implements `{$found}`, not `{$expected}` +trait_selection_closure_fn_once_label = closure is `{$trait_prefix}FnOnce` because it moves the variable `{$place}` out of its environment -trait_selection_closure_kind_requirement = the requirement to implement `{$expected}` derives from here +trait_selection_closure_kind_mismatch = expected a closure that implements the `{$trait_prefix}{$expected}` trait, but this closure only implements `{$trait_prefix}{$found}` + .label = this closure implements `{$trait_prefix}{$found}`, not `{$trait_prefix}{$expected}` + +trait_selection_closure_kind_requirement = the requirement to implement `{$trait_prefix}{$expected}` derives from here trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries} diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 20cd573f46e9b..407fff03e1588 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -135,6 +135,8 @@ pub struct ClosureKindMismatch { #[label(trait_selection_closure_kind_requirement)] pub cause_span: Span, + pub trait_prefix: &'static str, + #[subdiagnostic] pub fn_once_label: Option, @@ -157,3 +159,11 @@ pub struct ClosureFnMutLabel { pub span: Span, pub place: String, } + +#[derive(Diagnostic)] +#[diag(trait_selection_async_closure_not_fn)] +pub(crate) struct AsyncClosureNotFn { + #[primary_span] + pub span: Span, + pub kind: &'static str, +} diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 73effb3356065..68b1a0d4e61cd 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2,7 +2,9 @@ use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote, TypeErrCtxtExt as _}; use super::suggestions::{get_explanation_based_on_obligation, TypeErrCtxtExt as _}; -use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch}; +use crate::errors::{ + AsyncClosureNotFn, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch, +}; use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::InferCtxtExt as _; @@ -959,34 +961,102 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn emit_specialized_closure_kind_error( &self, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, + mut trait_ref: ty::PolyTraitRef<'tcx>, ) -> Option { - let self_ty = trait_ref.self_ty().skip_binder(); - if let ty::Closure(closure_def_id, closure_args) = *self_ty.kind() - && let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id()) - && let Some(found_kind) = self.closure_kind(self_ty) + // If `AsyncFnKindHelper` is not implemented, that means that the closure kind + // doesn't extend the goal kind. This is worth reporting, but we can only do so + // if we actually know which closure this goal comes from, so look at the cause + // to see if we can extract that information. + if Some(trait_ref.def_id()) == self.tcx.lang_items().async_fn_kind_helper() + && let Some(found_kind) = trait_ref.skip_binder().args.type_at(0).to_opt_closure_kind() + && let Some(expected_kind) = + trait_ref.skip_binder().args.type_at(1).to_opt_closure_kind() && !found_kind.extends(expected_kind) - && let sig = closure_args.as_closure().sig() - && self.can_sub( - obligation.param_env, - trait_ref, - sig.map_bound(|sig| { - ty::TraitRef::new( - self.tcx, - trait_ref.def_id(), - [trait_ref.self_ty().skip_binder(), sig.inputs()[0]], - ) - }), - ) { - let mut err = - self.report_closure_error(&obligation, closure_def_id, found_kind, expected_kind); - self.note_obligation_cause(&mut err, &obligation); - self.point_at_returns_when_relevant(&mut err, &obligation); - Some(err.emit()) - } else { - None + if let Some((_, Some(parent))) = obligation.cause.code().parent() { + // If we have a derived obligation, then the parent will be a `AsyncFn*` goal. + trait_ref = parent.to_poly_trait_ref(); + } else if let &ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = + obligation.cause.code() + && let Some(typeck_results) = &self.typeck_results + && let ty::Closure(closure_def_id, _) | ty::CoroutineClosure(closure_def_id, _) = + *typeck_results.node_type(arg_hir_id).kind() + { + // Otherwise, extract the closure kind from the obligation. + let mut err = self.report_closure_error( + &obligation, + closure_def_id, + found_kind, + expected_kind, + "async ", + ); + self.note_obligation_cause(&mut err, &obligation); + self.point_at_returns_when_relevant(&mut err, &obligation); + return Some(err.emit()); + } + } + + let self_ty = trait_ref.self_ty().skip_binder(); + + if let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id()) { + let (closure_def_id, found_args, by_ref_captures) = match *self_ty.kind() { + ty::Closure(def_id, args) => { + (def_id, args.as_closure().sig().map_bound(|sig| sig.inputs()[0]), None) + } + ty::CoroutineClosure(def_id, args) => ( + def_id, + args.as_coroutine_closure() + .coroutine_closure_sig() + .map_bound(|sig| sig.tupled_inputs_ty), + Some(args.as_coroutine_closure().coroutine_captures_by_ref_ty()), + ), + _ => return None, + }; + + let expected_args = trait_ref.map_bound(|trait_ref| trait_ref.args.type_at(1)); + + // Verify that the arguments are compatible. If the signature is + // mismatched, then we have a totally different error to report. + if self.enter_forall(found_args, |found_args| { + self.enter_forall(expected_args, |expected_args| { + !self.can_sub(obligation.param_env, expected_args, found_args) + }) + }) { + return None; + } + + if let Some(found_kind) = self.closure_kind(self_ty) + && !found_kind.extends(expected_kind) + { + let mut err = self.report_closure_error( + &obligation, + closure_def_id, + found_kind, + expected_kind, + "", + ); + self.note_obligation_cause(&mut err, &obligation); + self.point_at_returns_when_relevant(&mut err, &obligation); + return Some(err.emit()); + } + + // If the closure has captures, then perhaps the reason that the trait + // is unimplemented is because async closures don't implement `Fn`/`FnMut` + // if they have captures. + if let Some(by_ref_captures) = by_ref_captures + && let ty::FnPtr(sig) = by_ref_captures.kind() + && !sig.skip_binder().output().is_unit() + { + let mut err = self.tcx.dcx().create_err(AsyncClosureNotFn { + span: self.tcx.def_span(closure_def_id), + kind: expected_kind.as_str(), + }); + self.note_obligation_cause(&mut err, &obligation); + self.point_at_returns_when_relevant(&mut err, &obligation); + return Some(err.emit()); + } } + None } fn fn_arg_obligation( @@ -1493,6 +1563,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> { closure_def_id: DefId, found_kind: ty::ClosureKind, kind: ty::ClosureKind, + trait_prefix: &'static str, ) -> DiagnosticBuilder<'tcx>; fn report_cyclic_signature_error( @@ -3376,6 +3447,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { closure_def_id: DefId, found_kind: ty::ClosureKind, kind: ty::ClosureKind, + trait_prefix: &'static str, ) -> DiagnosticBuilder<'tcx> { let closure_span = self.tcx.def_span(closure_def_id); @@ -3384,6 +3456,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { expected: kind, found: found_kind, cause_span: obligation.cause.span, + trait_prefix, fn_once_label: None, fn_mut_label: None, }; diff --git a/tests/ui/async-await/async-closures/not-fn.rs b/tests/ui/async-await/async-closures/not-fn.rs new file mode 100644 index 0000000000000..4505e6243e966 --- /dev/null +++ b/tests/ui/async-await/async-closures/not-fn.rs @@ -0,0 +1,15 @@ +// edition:2021 + +// FIXME(async_closures): This needs a better error message! + +#![feature(async_closure)] + +fn main() { + fn needs_fn(_: impl FnMut() -> T) {} + + let mut x = 1; + needs_fn(async || { + //~^ ERROR async closure does not implement `FnMut` because it captures state from its environment + x += 1; + }); +} diff --git a/tests/ui/async-await/async-closures/not-fn.stderr b/tests/ui/async-await/async-closures/not-fn.stderr new file mode 100644 index 0000000000000..9c40613599a8e --- /dev/null +++ b/tests/ui/async-await/async-closures/not-fn.stderr @@ -0,0 +1,16 @@ +error: async closure does not implement `FnMut` because it captures state from its environment + --> $DIR/not-fn.rs:11:14 + | +LL | needs_fn(async || { + | -------- ^^^^^^^^ + | | + | required by a bound introduced by this call + | +note: required by a bound in `needs_fn` + --> $DIR/not-fn.rs:8:28 + | +LL | fn needs_fn(_: impl FnMut() -> T) {} + | ^^^^^^^^^^^^ required by this bound in `needs_fn` + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.rs b/tests/ui/async-await/async-closures/wrong-fn-kind.rs index f86cee3e0709e..1e372deb984e2 100644 --- a/tests/ui/async-await/async-closures/wrong-fn-kind.rs +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.rs @@ -9,8 +9,7 @@ fn main() { let mut x = 1; needs_async_fn(async || { - //~^ ERROR i16: ops::async_function::internal_implementation_detail::AsyncFnKindHelper - // FIXME: Should say "closure is `async FnMut` but it needs `async Fn`" or sth. + //~^ ERROR expected a closure that implements the `async Fn` trait, but this closure only implements `async FnMut` x += 1; }); } diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr index 4ef8484cc34cd..34a6b3a485a60 100644 --- a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr @@ -1,15 +1,17 @@ -error[E0277]: the trait bound `i16: ops::async_function::internal_implementation_detail::AsyncFnKindHelper` is not satisfied +error[E0525]: expected a closure that implements the `async Fn` trait, but this closure only implements `async FnMut` --> $DIR/wrong-fn-kind.rs:11:20 | LL | needs_async_fn(async || { - | _____--------------_^ + | -------------- -^^^^^^^ + | | | + | _____|______________this closure implements `async FnMut`, not `async Fn` | | | | | required by a bound introduced by this call LL | | -LL | | // FIXME: Should say "closure is `async FnMut` but it needs `async Fn`" or sth. LL | | x += 1; + | | - closure is `async FnMut` because it mutates the variable `x` here LL | | }); - | |_____^ the trait `ops::async_function::internal_implementation_detail::AsyncFnKindHelper` is not implemented for `i16` + | |_____- the requirement to implement `async Fn` derives from here | note: required by a bound in `needs_async_fn` --> $DIR/wrong-fn-kind.rs:8:31 @@ -19,4 +21,4 @@ LL | fn needs_async_fn(_: impl async Fn()) {} error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0525`. From 6018e21d8ad072d28dbd2e991dfd8295e2de321f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Feb 2024 14:38:52 +0000 Subject: [PATCH 17/20] Remove a suggestion that is redundant --- compiler/rustc_hir_typeck/src/_match.rs | 1 - .../rustc_infer/src/infer/error_reporting/mod.rs | 13 ------------- compiler/rustc_middle/src/traits/mod.rs | 1 - tests/ui/match/dont-highlight-diverging-arms.rs | 2 +- .../ui/match/dont-highlight-diverging-arms.stderr | 4 ---- tests/ui/suggestions/issue-81839.stderr | 15 ++++----------- tests/ui/wf/wf-unsafe-trait-obj-match.stderr | 4 ---- 7 files changed, 5 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 214066814221b..b0caf45b40afe 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -118,7 +118,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { prior_arm_ty, prior_arm_span, scrut_span: scrut.span, - scrut_hir_id: scrut.hir_id, source: match_src, prior_non_diverging_arms: prior_non_diverging_arms.clone(), opt_suggest_box_span, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index aa92f91f24f83..104bf4a5be873 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -780,7 +780,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ref prior_non_diverging_arms, opt_suggest_box_span, scrut_span, - scrut_hir_id, .. }) => match source { hir::MatchSource::TryDesugar(scrut_hir_id) => { @@ -848,18 +847,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ) { err.subdiagnostic(subdiag); } - if let hir::Node::Expr(m) = self.tcx.parent_hir_node(scrut_hir_id) - && let hir::Node::Stmt(stmt) = self.tcx.parent_hir_node(m.hir_id) - && let hir::StmtKind::Expr(_) = stmt.kind - { - err.span_suggestion_verbose( - stmt.span.shrink_to_hi(), - "consider using a semicolon here, but this will discard any values \ - in the match arms", - ";", - Applicability::MaybeIncorrect, - ); - } if let Some(ret_sp) = opt_suggest_box_span { // Get return type span and point to it. self.suggest_boxing_for_return_impl_trait( diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 683610ba3b6a3..119e0a49acf1f 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -569,7 +569,6 @@ pub struct MatchExpressionArmCause<'tcx> { pub prior_arm_ty: Ty<'tcx>, pub prior_arm_span: Span, pub scrut_span: Span, - pub scrut_hir_id: hir::HirId, pub source: hir::MatchSource, pub prior_non_diverging_arms: Vec, pub opt_suggest_box_span: Option, diff --git a/tests/ui/match/dont-highlight-diverging-arms.rs b/tests/ui/match/dont-highlight-diverging-arms.rs index dc3b4ca9caad6..0fb614fa18a6f 100644 --- a/tests/ui/match/dont-highlight-diverging-arms.rs +++ b/tests/ui/match/dont-highlight-diverging-arms.rs @@ -14,4 +14,4 @@ fn main() { None }; -} \ No newline at end of file +} diff --git a/tests/ui/match/dont-highlight-diverging-arms.stderr b/tests/ui/match/dont-highlight-diverging-arms.stderr index 886c1af13fa37..f0aaecbb7adb1 100644 --- a/tests/ui/match/dont-highlight-diverging-arms.stderr +++ b/tests/ui/match/dont-highlight-diverging-arms.stderr @@ -15,10 +15,6 @@ LL | | } | = note: expected enum `Option` found unit type `()` -help: consider using a semicolon here, but this will discard any values in the match arms - | -LL | }; - | + error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/issue-81839.stderr b/tests/ui/suggestions/issue-81839.stderr index de1ea98554bee..34ff16c653afa 100644 --- a/tests/ui/suggestions/issue-81839.stderr +++ b/tests/ui/suggestions/issue-81839.stderr @@ -4,22 +4,15 @@ error[E0308]: `match` arms have incompatible types LL | / match num { LL | | 1 => { LL | | cx.answer_str("hi"); - | | -------------------- this is found to be of type `()` + | | -------------------- + | | | | + | | | help: consider removing this semicolon + | | this is found to be of type `()` LL | | } LL | | _ => cx.answer_str("hi"), | | ^^^^^^^^^^^^^^^^^^^ expected `()`, found future LL | | } | |_____- `match` arms have incompatible types - | -help: consider removing this semicolon - | -LL - cx.answer_str("hi"); -LL + cx.answer_str("hi") - | -help: consider using a semicolon here, but this will discard any values in the match arms - | -LL | }; - | + error: aborting due to 1 previous error diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr index 3b53f55ffdc1d..e30cb8ff921a0 100644 --- a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr +++ b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr @@ -11,10 +11,6 @@ LL | | } | = note: expected reference `&S` found reference `&R` -help: consider using a semicolon here, but this will discard any values in the match arms - | -LL | }; - | + error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/wf-unsafe-trait-obj-match.rs:26:21 From fdc56b68860a3e0fc9a9733d746a0f932f9e53cc Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Thu, 15 Feb 2024 18:38:36 +0100 Subject: [PATCH 18/20] doc: add note before panicking examples for strict_overflow_ops --- library/core/src/num/int_macros.rs | 36 +++++++++++++++++++++++++++++ library/core/src/num/uint_macros.rs | 16 +++++++++++++ 2 files changed, 52 insertions(+) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index d052dcc3e6ee6..434bcace616f2 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -472,6 +472,8 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).strict_add(1), ", stringify!($SelfT), "::MAX - 1);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")] @@ -552,6 +554,8 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_add_unsigned(2), 3);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_unsigned(3);")] @@ -606,6 +610,8 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).strict_sub(1), ", stringify!($SelfT), "::MIN + 1);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub(3);")] @@ -686,6 +692,8 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_sub_unsigned(2), -1);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub_unsigned(3);")] @@ -740,6 +748,8 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.strict_mul(1), ", stringify!($SelfT), "::MAX);")] /// ``` /// + /// The following panics because of overflow: + /// /// ``` should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")] @@ -831,11 +841,15 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).strict_div(-1), ", stringify!($Max), ");")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_div(-1);")] /// ``` /// + /// The following panics because of division by zero: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")] @@ -901,11 +915,15 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).strict_div_euclid(-1), ", stringify!($Max), ");")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_div_euclid(-1);")] /// ``` /// + /// The following panics because of division by zero: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")] @@ -970,11 +988,15 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_rem(2), 1);")] /// ``` /// + /// The following panics because of division by zero: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem(0);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem(-1);")] @@ -1039,11 +1061,15 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_rem_euclid(2), 1);")] /// ``` /// + /// The following panics because of division by zero: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem_euclid(0);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem_euclid(-1);")] @@ -1121,6 +1147,8 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_neg(), -5);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_neg();")] @@ -1175,6 +1203,8 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".strict_shl(4), 0x10);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0x1", stringify!($SelfT), ".strict_shl(129);")] @@ -1256,6 +1286,8 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".strict_shr(4), 0x1);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(128);")] @@ -1340,6 +1372,8 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").strict_abs(), 5);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_abs();")] @@ -1414,6 +1448,8 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(8", stringify!($SelfT), ".strict_pow(2), 64);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index a217c2e259d2b..5036a3b0c71cf 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -480,6 +480,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).strict_add(1), ", stringify!($SelfT), "::MAX - 1);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")] @@ -561,6 +563,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_add_signed(2), 3);")] /// ``` /// + /// The following panic because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_add_signed(-2);")] @@ -620,6 +624,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_sub(1), 0);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0", stringify!($SelfT), ".strict_sub(1);")] @@ -700,6 +706,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_mul(1), 5);")] /// ``` /// + /// The following panics because of overflow: + /// /// ``` should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")] @@ -1172,6 +1180,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".strict_neg(), 0);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_neg();")] @@ -1226,6 +1236,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".strict_shl(4), 0x10);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shl(129);")] @@ -1307,6 +1319,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".strict_shr(4), 0x1);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(129);")] @@ -1406,6 +1420,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".strict_pow(5), 32);")] /// ``` /// + /// The following panics because of overflow: + /// /// ```should_panic /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")] From 675d092e3e69e1ca6f0abcad4b18d746e6ed558a Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Thu, 15 Feb 2024 18:41:30 +0100 Subject: [PATCH 19/20] doc: panicking division by zero examples for unsigned strict div ops --- library/core/src/num/uint_macros.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 5036a3b0c71cf..f2f29e4ad8194 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -793,6 +793,13 @@ macro_rules! uint_impl { /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_div(10), 10);")] /// ``` + /// + /// The following panics because of division by zero: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")] + /// ``` #[unstable(feature = "strict_overflow_ops", issue = "118260")] #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] #[must_use = "this returns the result of the operation, \ @@ -848,6 +855,12 @@ macro_rules! uint_impl { /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_div_euclid(10), 10);")] /// ``` + /// The following panics because of division by zero: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")] + /// ``` #[unstable(feature = "strict_overflow_ops", issue = "118260")] #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] #[must_use = "this returns the result of the operation, \ @@ -903,6 +916,13 @@ macro_rules! uint_impl { /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_rem(10), 0);")] /// ``` + /// + /// The following panics because of division by zero: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem(0);")] + /// ``` #[unstable(feature = "strict_overflow_ops", issue = "118260")] #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] #[must_use = "this returns the result of the operation, \ @@ -959,6 +979,13 @@ macro_rules! uint_impl { /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_rem_euclid(10), 0);")] /// ``` + /// + /// The following panics because of division by zero: + /// + /// ```should_panic + /// #![feature(strict_overflow_ops)] + #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem_euclid(0);")] + /// ``` #[unstable(feature = "strict_overflow_ops", issue = "118260")] #[rustc_const_unstable(feature = "const_strict_overflow_ops", issue = "118260")] #[must_use = "this returns the result of the operation, \ From 954d56591cbbc057d53c233f86895658febe407d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Feb 2024 13:20:33 +0000 Subject: [PATCH 20/20] Fix closure kind docs --- compiler/rustc_middle/src/ty/sty.rs | 37 ++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 66086ac87f16b..a581712526752 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2363,28 +2363,42 @@ impl<'tcx> Ty<'tcx> { } /// When we create a closure, we record its kind (i.e., what trait - /// it implements) into its `ClosureArgs` using a type + /// it implements, constrained by how it uses its borrows) into its + /// [`ty::ClosureArgs`] or [`ty::CoroutineClosureArgs`] using a type /// parameter. This is kind of a phantom type, except that the /// most convenient thing for us to are the integral types. This /// function converts such a special type into the closure - /// kind. To go the other way, use `closure_kind.to_ty(tcx)`. + /// kind. To go the other way, use [`Ty::from_closure_kind`]. /// /// Note that during type checking, we use an inference variable /// to represent the closure kind, because it has not yet been /// inferred. Once upvar inference (in `rustc_hir_analysis/src/check/upvar.rs`) - /// is complete, that type variable will be unified. + /// is complete, that type variable will be unified with one of + /// the integral types. /// - /// To be noted that you can use [`ClosureArgs::kind()`] or [`CoroutineClosureArgs::kind()`] - /// to get the same information, which you can get by calling [`GenericArgs::as_closure()`] - /// or [`GenericArgs::as_coroutine_closure()`], depending on the type of the closure. + /// ```rust,ignore (snippet of compiler code) + /// if let TyKind::Closure(def_id, args) = closure_ty.kind() + /// && let Some(closure_kind) = args.as_closure().kind_ty().to_opt_closure_kind() + /// { + /// println!("{closure_kind:?}"); + /// } else if let TyKind::CoroutineClosure(def_id, args) = closure_ty.kind() + /// && let Some(closure_kind) = args.as_coroutine_closure().kind_ty().to_opt_closure_kind() + /// { + /// println!("{closure_kind:?}"); + /// } + /// ``` /// - /// Otherwise, this method can be used as follows: + /// After upvar analysis, you should instead use [`ClosureArgs::kind()`] + /// or [`CoroutineClosureArgs::kind()`] to assert that the `ClosureKind` + /// has been constrained instead of manually calling this method. /// /// ```rust,ignore (snippet of compiler code) - /// let TyKind::Closure(def_id, [closure_fn_kind_ty, ..]) = closure_ty.kind() - /// && let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() + /// if let TyKind::Closure(def_id, args) = closure_ty.kind() + /// { + /// println!("{:?}", args.as_closure().kind()); + /// } else if let TyKind::CoroutineClosure(def_id, args) = closure_ty.kind() /// { - /// // your code + /// println!("{:?}", args.as_coroutine_closure().kind()); /// } /// ``` pub fn to_opt_closure_kind(self) -> Option { @@ -2406,7 +2420,8 @@ impl<'tcx> Ty<'tcx> { } } - /// Inverse of [`Ty::to_opt_closure_kind`]. + /// Inverse of [`Ty::to_opt_closure_kind`]. See docs on that method + /// for explanation of the relationship between `Ty` and [`ty::ClosureKind`]. pub fn from_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Ty<'tcx> { match kind { ty::ClosureKind::Fn => tcx.types.i8,