From 3855c5441399adf14d8b8b9e7a87f715a0ae3692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Fri, 19 Jul 2024 11:24:52 +0000 Subject: [PATCH 01/12] compiletest: cleanup dylib name calculation --- src/tools/compiletest/src/runtest.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 0122886961737..de62f4dd96a6b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -82,26 +82,22 @@ fn disable_error_reporting R, R>(f: F) -> R { } /// The platform-specific library name -fn get_lib_name(lib: &str, aux_type: AuxType) -> Option { +fn get_lib_name(name: &str, aux_type: AuxType) -> Option { match aux_type { AuxType::Bin => None, // In some cases (e.g. MUSL), we build a static // library, rather than a dynamic library. // In this case, the only path we can pass // with '--extern-meta' is the '.rlib' file - AuxType::Lib => Some(format!("lib{}.rlib", lib)), - AuxType::Dylib => Some(if cfg!(windows) { - format!("{}.dll", lib) - } else if cfg!(target_vendor = "apple") { - format!("lib{}.dylib", lib) - } else if cfg!(target_os = "aix") { - format!("lib{}.a", lib) - } else { - format!("lib{}.so", lib) - }), + AuxType::Lib => Some(format!("lib{name}.rlib")), + AuxType::Dylib => Some(dylib_name(name)), } } +fn dylib_name(name: &str) -> String { + format!("{}{name}.{}", std::env::consts::DLL_PREFIX, std::env::consts::DLL_EXTENSION) +} + pub fn run(config: Arc, testpaths: &TestPaths, revision: Option<&str>) { match &*config.target { "arm-linux-androideabi" From 632f01306b2a5b7f47e554cf1280f5ef8fc9f710 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Fri, 19 Jul 2024 16:23:29 -0400 Subject: [PATCH 02/12] rewrite lto-linkage-used-attr to rmake --- src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/lto-linkage-used-attr/Makefile | 8 -------- tests/run-make/lto-linkage-used-attr/rmake.rs | 14 ++++++++++++++ 3 files changed, 14 insertions(+), 9 deletions(-) delete mode 100644 tests/run-make/lto-linkage-used-attr/Makefile create mode 100644 tests/run-make/lto-linkage-used-attr/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 6b3533c25785f..5cb580e9f799d 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -47,7 +47,6 @@ run-make/link-cfg/Makefile run-make/link-framework/Makefile run-make/long-linker-command-lines-cmd-exe/Makefile run-make/long-linker-command-lines/Makefile -run-make/lto-linkage-used-attr/Makefile run-make/macos-deployment-target/Makefile run-make/min-global-align/Makefile run-make/native-link-modifier-bundle/Makefile diff --git a/tests/run-make/lto-linkage-used-attr/Makefile b/tests/run-make/lto-linkage-used-attr/Makefile deleted file mode 100644 index fed41a00f84b3..0000000000000 --- a/tests/run-make/lto-linkage-used-attr/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -include ../tools.mk - -# Verify that the impl_* symbols are preserved. #108030 -# only-x86_64-unknown-linux-gnu - -all: - $(RUSTC) -Cdebuginfo=0 -Copt-level=3 lib.rs - $(RUSTC) -Clto=fat -Cdebuginfo=0 -Copt-level=3 main.rs diff --git a/tests/run-make/lto-linkage-used-attr/rmake.rs b/tests/run-make/lto-linkage-used-attr/rmake.rs new file mode 100644 index 0000000000000..114c5dcf5212d --- /dev/null +++ b/tests/run-make/lto-linkage-used-attr/rmake.rs @@ -0,0 +1,14 @@ +// Link time optimizations (LTO) used to snip away some important symbols +// when setting optimization level to 3 or higher. +// This is an LLVM, not a rustc bug, fixed here: https://reviews.llvm.org/D145293 +// This test checks that the impl_* symbols are preserved as they should. +// See https://github.com/rust-lang/rust/issues/108030 + +//FIXME(Oneirical): try it on more than only-x86_64-unknown-linux-gnu + +use run_make_support::rustc; + +fn main() { + rustc().arg("-Cdebuginfo=0").opt_level("3").input("lib.rs").run(); + rustc().arg("-Clto=fat").arg("-Cdebuginfo=0").opt_level("3").input("main.rs").run(); +} From f307287659b8492d6baec07bb2a5902a6b487052 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Fri, 19 Jul 2024 16:35:37 -0400 Subject: [PATCH 03/12] rewrite no-duplicate-libs to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/no-duplicate-libs/Makefile | 11 ---------- tests/run-make/no-duplicate-libs/rmake.rs | 21 +++++++++++++++++++ 3 files changed, 21 insertions(+), 12 deletions(-) delete mode 100644 tests/run-make/no-duplicate-libs/Makefile create mode 100644 tests/run-make/no-duplicate-libs/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 5cb580e9f799d..bc3da81fa5224 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -53,7 +53,6 @@ run-make/native-link-modifier-bundle/Makefile run-make/native-link-modifier-whole-archive/Makefile run-make/no-alloc-shim/Makefile run-make/no-builtins-attribute/Makefile -run-make/no-duplicate-libs/Makefile run-make/panic-abort-eh_frame/Makefile run-make/pdb-buildinfo-cl-cmd/Makefile run-make/pgo-gen-lto/Makefile diff --git a/tests/run-make/no-duplicate-libs/Makefile b/tests/run-make/no-duplicate-libs/Makefile deleted file mode 100644 index 4be8c0262941a..0000000000000 --- a/tests/run-make/no-duplicate-libs/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -ifdef IS_MSVC -# FIXME(#27979) -all: -else -all: $(call STATICLIB,foo) $(call STATICLIB,bar) - $(RUSTC) main.rs - $(call RUN,main) -endif diff --git a/tests/run-make/no-duplicate-libs/rmake.rs b/tests/run-make/no-duplicate-libs/rmake.rs new file mode 100644 index 0000000000000..35b1234ef3484 --- /dev/null +++ b/tests/run-make/no-duplicate-libs/rmake.rs @@ -0,0 +1,21 @@ +// The rust compiler used to try to detect duplicated libraries in +// the linking order and remove the duplicates... but certain edge cases, +// such as the one presented in `foo` and `bar` in this test, demand precise +// control over the link order, including duplicates. As the anti-duplication +// filter was removed, this test should now successfully see main be compiled +// and executed. +// See https://github.com/rust-lang/rust/pull/12688 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +// FIXME(Oneirical): try on msvc because of #27979 + +use run_make_support::{build_native_static_lib, run, rustc}; + +fn main() { + build_native_static_lib("foo"); + build_native_static_lib("bar"); + rustc().input("main.rs").run(); + run("main"); +} From 6d9d605fcac79ad8180f2368c69fd2eb3c18988d Mon Sep 17 00:00:00 2001 From: Oneirical Date: Fri, 19 Jul 2024 16:43:06 -0400 Subject: [PATCH 04/12] rewrite pgo-gen-no-imp-symbols to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/lto-linkage-used-attr/rmake.rs | 3 ++- tests/run-make/no-duplicate-libs/rmake.rs | 3 ++- .../run-make/pgo-gen-no-imp-symbols/Makefile | 11 -------- .../run-make/pgo-gen-no-imp-symbols/rmake.rs | 27 +++++++++++++++++++ 5 files changed, 31 insertions(+), 14 deletions(-) delete mode 100644 tests/run-make/pgo-gen-no-imp-symbols/Makefile create mode 100644 tests/run-make/pgo-gen-no-imp-symbols/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index bc3da81fa5224..5f0a953bc2bbd 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -56,7 +56,6 @@ run-make/no-builtins-attribute/Makefile run-make/panic-abort-eh_frame/Makefile run-make/pdb-buildinfo-cl-cmd/Makefile run-make/pgo-gen-lto/Makefile -run-make/pgo-gen-no-imp-symbols/Makefile run-make/pgo-indirect-call-promotion/Makefile run-make/pointer-auth-link-with-c/Makefile run-make/print-calling-conventions/Makefile diff --git a/tests/run-make/lto-linkage-used-attr/rmake.rs b/tests/run-make/lto-linkage-used-attr/rmake.rs index 114c5dcf5212d..12463b79a754b 100644 --- a/tests/run-make/lto-linkage-used-attr/rmake.rs +++ b/tests/run-make/lto-linkage-used-attr/rmake.rs @@ -4,7 +4,8 @@ // This test checks that the impl_* symbols are preserved as they should. // See https://github.com/rust-lang/rust/issues/108030 -//FIXME(Oneirical): try it on more than only-x86_64-unknown-linux-gnu +//@ only-x86_64-unknown-linux-gnu +// Reason: some of the inline assembly directives are architecture-specific. use run_make_support::rustc; diff --git a/tests/run-make/no-duplicate-libs/rmake.rs b/tests/run-make/no-duplicate-libs/rmake.rs index 35b1234ef3484..469348e266cb8 100644 --- a/tests/run-make/no-duplicate-libs/rmake.rs +++ b/tests/run-make/no-duplicate-libs/rmake.rs @@ -9,7 +9,8 @@ //@ ignore-cross-compile // Reason: the compiled binary is executed -// FIXME(Oneirical): try on msvc because of #27979 +//@ ignore-msvc +// Reason: native compilation results in an unresolved external symbol use run_make_support::{build_native_static_lib, run, rustc}; diff --git a/tests/run-make/pgo-gen-no-imp-symbols/Makefile b/tests/run-make/pgo-gen-no-imp-symbols/Makefile deleted file mode 100644 index d2baa145ba506..0000000000000 --- a/tests/run-make/pgo-gen-no-imp-symbols/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -include ../tools.mk - -COMPILE_FLAGS=-O -Ccodegen-units=1 -Cprofile-generate="$(TMPDIR)" -Zno-profiler-runtime - -all: - $(RUSTC) $(COMPILE_FLAGS) --emit=llvm-ir test.rs - # We expect symbols starting with "__llvm_profile_". - $(CGREP) "__llvm_profile_" < $(TMPDIR)/test.ll - # We do NOT expect the "__imp_" version of these symbols. - $(CGREP) -v "__imp___llvm_profile_" < $(TMPDIR)/test.ll # 64 bit - $(CGREP) -v "__imp____llvm_profile_" < $(TMPDIR)/test.ll # 32 bit diff --git a/tests/run-make/pgo-gen-no-imp-symbols/rmake.rs b/tests/run-make/pgo-gen-no-imp-symbols/rmake.rs new file mode 100644 index 0000000000000..85ade7885ce7e --- /dev/null +++ b/tests/run-make/pgo-gen-no-imp-symbols/rmake.rs @@ -0,0 +1,27 @@ +// LLVM's profiling instrumentation adds a few symbols that are used by the profiler runtime. +// Since these show up as globals in the LLVM IR, the compiler generates dllimport-related +// __imp_ stubs for them. This can lead to linker errors because the instrumentation +// symbols have weak linkage or are in a comdat section, but the __imp_ stubs aren't. +// Since profiler-related symbols were excluded from stub-generation in #59812, this has +// been fixed, and this test checks that the llvm profile symbol appear, but without the +// anomalous __imp_ stubs. +// See https://github.com/rust-lang/rust/pull/59812 + +use run_make_support::{cwd, rfs, rustc}; + +fn main() { + rustc() + .input("test.rs") + .emit("llvm-ir") + .opt() + .codegen_units(1) + .profile_generate(cwd()) + .arg("-Zno-profiler-runtime") + .run(); + let out = rfs::read_to_string("test.ll"); + // We expect symbols starting with "__llvm_profile_". + assert!(out.contains("__llvm_profile_")); + // We do NOT expect the "__imp_" version of these symbols. + assert!(!out.contains("__imp___llvm_profile_")); // 64 bit + assert!(!out.contains("__imp____llvm_profile_")); // 32 bit +} From 7bca516b357f5cf596250f99353a08f65cb0456a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 22 Jul 2024 13:54:48 -0400 Subject: [PATCH 05/12] Get rid of can_eq_shallow --- compiler/rustc_infer/src/infer/mod.rs | 12 ------------ .../src/error_reporting/infer/note_and_explain.rs | 5 +++-- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 7fc4e36d75274..3cee0a622f17b 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -755,18 +755,6 @@ impl<'tcx> InferCtxt<'tcx> { .collect() } - // FIXME(-Znext-solver): Get rid of this method, it's never correct. Either that, - // or we need to process the obligations. - pub fn can_eq_shallow(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool - where - T: at::ToTrace<'tcx>, - { - let origin = &ObligationCause::dummy(); - // We're only answering whether the types could be the same, and with - // opaque types, "they can be the same", via registering a hidden type. - self.probe(|_| self.at(origin, param_env).eq(DefineOpaqueTypes::Yes, a, b).is_ok()) - } - #[instrument(skip(self), level = "debug")] pub fn sub_regions( &self, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 1ff2fca83faf2..f9110cfb3b970 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -12,6 +12,7 @@ use rustc_middle::{ use rustc_span::{def_id::DefId, sym, BytePos, Span, Symbol}; use crate::error_reporting::TypeErrCtxt; +use crate::infer::InferCtxtExt; impl<'tcx> TypeErrCtxt<'_, 'tcx> { pub fn note_and_explain_type_err( @@ -821,7 +822,7 @@ fn foo(&self) -> Self::T { String::new() } tcx.defaultness(item.id.owner_id) { let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity(); - if self.infcx.can_eq_shallow(param_env, assoc_ty, found) { + if self.infcx.can_eq(param_env, assoc_ty, found) { diag.span_label( item.span, "associated type defaults can't be assumed inside the \ @@ -844,7 +845,7 @@ fn foo(&self) -> Self::T { String::new() } let assoc_ty = tcx.type_of(item.id.owner_id).instantiate_identity(); if let hir::Defaultness::Default { has_value: true } = tcx.defaultness(item.id.owner_id) - && self.infcx.can_eq_shallow(param_env, assoc_ty, found) + && self.infcx.can_eq(param_env, assoc_ty, found) { diag.span_label( item.span, From 6310e40578909d2747d86b75adf70033065511aa Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 22 Jul 2024 16:11:08 -0400 Subject: [PATCH 06/12] Get rid of infer_ctxt_ext --- compiler/rustc_hir_typeck/src/closure.rs | 4 +- .../traits/fulfillment_errors.rs | 235 ++++++++++++++++- .../error_reporting/traits/infer_ctxt_ext.rs | 244 ------------------ .../src/error_reporting/traits/mod.rs | 2 - .../clippy/clippy_lints/src/eta_reduction.rs | 4 +- 5 files changed, 237 insertions(+), 252 deletions(-) delete mode 100644 compiler/rustc_trait_selection/src/error_reporting/traits/infer_ctxt_ext.rs diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 08de871f6fa94..79854976bdd57 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -18,7 +18,6 @@ use rustc_span::def_id::LocalDefId; use rustc_span::Span; use rustc_target::spec::abi::Abi; use rustc_trait_selection::error_reporting::traits::ArgKind; -use rustc_trait_selection::error_reporting::traits::InferCtxtExt as _; use rustc_trait_selection::traits; use rustc_type_ir::ClosureKind; use std::iter; @@ -734,13 +733,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|ty| ArgKind::from_expected_ty(*ty, None)) .collect(); let (closure_span, closure_arg_span, found_args) = - match self.get_fn_like_arguments(expr_map_node) { + match self.err_ctxt().get_fn_like_arguments(expr_map_node) { Some((sp, arg_sp, args)) => (Some(sp), arg_sp, args), None => (None, None, Vec::new()), }; let expected_span = expected_sig.cause_span.unwrap_or_else(|| self.tcx.def_span(expr_def_id)); let guar = self + .err_ctxt() .report_arg_count_mismatch( expected_span, closure_span, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 85b37ff326090..a7ea308a818b4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1,7 +1,6 @@ use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote}; use super::suggestions::get_explanation_based_on_obligation; use crate::error_reporting::infer::TyCategory; -use crate::error_reporting::traits::infer_ctxt_ext::InferCtxtExt; use crate::error_reporting::traits::report_object_safety_error; use crate::error_reporting::TypeErrCtxt; use crate::errors::{ @@ -2602,7 +2601,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }) .unwrap_or((found_span, None, found)); - self.infcx.report_arg_count_mismatch( + self.report_arg_count_mismatch( span, closure_span, expected, @@ -2614,6 +2613,238 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) } + /// Given some node representing a fn-like thing in the HIR map, + /// returns a span and `ArgKind` information that describes the + /// arguments it expects. This can be supplied to + /// `report_arg_count_mismatch`. + pub fn get_fn_like_arguments( + &self, + node: Node<'_>, + ) -> Option<(Span, Option, Vec)> { + let sm = self.tcx.sess.source_map(); + let hir = self.tcx.hir(); + Some(match node { + Node::Expr(&hir::Expr { + kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, fn_arg_span, .. }), + .. + }) => ( + fn_decl_span, + fn_arg_span, + hir.body(body) + .params + .iter() + .map(|arg| { + if let hir::Pat { kind: hir::PatKind::Tuple(args, _), span, .. } = *arg.pat + { + Some(ArgKind::Tuple( + Some(span), + args.iter() + .map(|pat| { + sm.span_to_snippet(pat.span) + .ok() + .map(|snippet| (snippet, "_".to_owned())) + }) + .collect::>>()?, + )) + } else { + let name = sm.span_to_snippet(arg.pat.span).ok()?; + Some(ArgKind::Arg(name, "_".to_owned())) + } + }) + .collect::>>()?, + ), + Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref sig, ..), .. }) + | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. }) + | Node::TraitItem(&hir::TraitItem { + kind: hir::TraitItemKind::Fn(ref sig, _), .. + }) => ( + sig.span, + None, + sig.decl + .inputs + .iter() + .map(|arg| match arg.kind { + hir::TyKind::Tup(tys) => ArgKind::Tuple( + Some(arg.span), + vec![("_".to_owned(), "_".to_owned()); tys.len()], + ), + _ => ArgKind::empty(), + }) + .collect::>(), + ), + Node::Ctor(variant_data) => { + let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id)); + (span, None, vec![ArgKind::empty(); variant_data.fields().len()]) + } + _ => panic!("non-FnLike node found: {node:?}"), + }) + } + + /// Reports an error when the number of arguments needed by a + /// trait match doesn't match the number that the expression + /// provides. + pub fn report_arg_count_mismatch( + &self, + span: Span, + found_span: Option, + expected_args: Vec, + found_args: Vec, + is_closure: bool, + closure_arg_span: Option, + ) -> Diag<'a> { + let kind = if is_closure { "closure" } else { "function" }; + + let args_str = |arguments: &[ArgKind], other: &[ArgKind]| { + let arg_length = arguments.len(); + let distinct = matches!(other, &[ArgKind::Tuple(..)]); + match (arg_length, arguments.get(0)) { + (1, Some(ArgKind::Tuple(_, fields))) => { + format!("a single {}-tuple as argument", fields.len()) + } + _ => format!( + "{} {}argument{}", + arg_length, + if distinct && arg_length > 1 { "distinct " } else { "" }, + pluralize!(arg_length) + ), + } + }; + + let expected_str = args_str(&expected_args, &found_args); + let found_str = args_str(&found_args, &expected_args); + + let mut err = struct_span_code_err!( + self.dcx(), + span, + E0593, + "{} is expected to take {}, but it takes {}", + kind, + expected_str, + found_str, + ); + + err.span_label(span, format!("expected {kind} that takes {expected_str}")); + + if let Some(found_span) = found_span { + err.span_label(found_span, format!("takes {found_str}")); + + // Suggest to take and ignore the arguments with expected_args_length `_`s if + // found arguments is empty (assume the user just wants to ignore args in this case). + // For example, if `expected_args_length` is 2, suggest `|_, _|`. + if found_args.is_empty() && is_closure { + let underscores = vec!["_"; expected_args.len()].join(", "); + err.span_suggestion_verbose( + closure_arg_span.unwrap_or(found_span), + format!( + "consider changing the closure to take and ignore the expected argument{}", + pluralize!(expected_args.len()) + ), + format!("|{underscores}|"), + Applicability::MachineApplicable, + ); + } + + if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] { + if fields.len() == expected_args.len() { + let sugg = fields + .iter() + .map(|(name, _)| name.to_owned()) + .collect::>() + .join(", "); + err.span_suggestion_verbose( + found_span, + "change the closure to take multiple arguments instead of a single tuple", + format!("|{sugg}|"), + Applicability::MachineApplicable, + ); + } + } + if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] + && fields.len() == found_args.len() + && is_closure + { + let sugg = format!( + "|({}){}|", + found_args + .iter() + .map(|arg| match arg { + ArgKind::Arg(name, _) => name.to_owned(), + _ => "_".to_owned(), + }) + .collect::>() + .join(", "), + // add type annotations if available + if found_args.iter().any(|arg| match arg { + ArgKind::Arg(_, ty) => ty != "_", + _ => false, + }) { + format!( + ": ({})", + fields + .iter() + .map(|(_, ty)| ty.to_owned()) + .collect::>() + .join(", ") + ) + } else { + String::new() + }, + ); + err.span_suggestion_verbose( + found_span, + "change the closure to accept a tuple instead of individual arguments", + sugg, + Applicability::MachineApplicable, + ); + } + } + + err + } + + /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce` + /// in that order, and returns the generic type corresponding to the + /// argument of that trait (corresponding to the closure arguments). + pub fn type_implements_fn_trait( + &self, + param_env: ty::ParamEnv<'tcx>, + ty: ty::Binder<'tcx, Ty<'tcx>>, + polarity: ty::PredicatePolarity, + ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> { + self.commit_if_ok(|_| { + for trait_def_id in [ + self.tcx.lang_items().fn_trait(), + self.tcx.lang_items().fn_mut_trait(), + self.tcx.lang_items().fn_once_trait(), + ] { + let Some(trait_def_id) = trait_def_id else { continue }; + // Make a fresh inference variable so we can determine what the generic parameters + // of the trait are. + let var = self.next_ty_var(DUMMY_SP); + // FIXME(effects) + let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]); + let obligation = Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + ty.rebind(ty::TraitPredicate { trait_ref, polarity }), + ); + let ocx = ObligationCtxt::new(self); + ocx.register_obligation(obligation); + if ocx.select_all_or_error().is_empty() { + return Ok(( + self.tcx + .fn_trait_kind_from_def_id(trait_def_id) + .expect("expected to map DefId to ClosureKind"), + ty.rebind(self.resolve_vars_if_possible(var)), + )); + } + } + + Err(()) + }) + } + fn report_not_const_evaluatable_error( &self, obligation: &PredicateObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/infer_ctxt_ext.rs deleted file mode 100644 index e8d7e80ac562c..0000000000000 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/infer_ctxt_ext.rs +++ /dev/null @@ -1,244 +0,0 @@ -// FIXME(error_reporting): This should be made into private methods on `TypeErrCtxt`. - -use crate::infer::InferCtxt; -use crate::traits::{Obligation, ObligationCause, ObligationCtxt}; -use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, Diag}; -use rustc_hir as hir; -use rustc_hir::Node; -use rustc_macros::extension; -use rustc_middle::ty::{self, Ty}; -use rustc_span::{Span, DUMMY_SP}; - -use super::ArgKind; - -#[extension(pub trait InferCtxtExt<'tcx>)] -impl<'tcx> InferCtxt<'tcx> { - /// Given some node representing a fn-like thing in the HIR map, - /// returns a span and `ArgKind` information that describes the - /// arguments it expects. This can be supplied to - /// `report_arg_count_mismatch`. - fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option, Vec)> { - let sm = self.tcx.sess.source_map(); - let hir = self.tcx.hir(); - Some(match node { - Node::Expr(&hir::Expr { - kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, fn_arg_span, .. }), - .. - }) => ( - fn_decl_span, - fn_arg_span, - hir.body(body) - .params - .iter() - .map(|arg| { - if let hir::Pat { kind: hir::PatKind::Tuple(args, _), span, .. } = *arg.pat - { - Some(ArgKind::Tuple( - Some(span), - args.iter() - .map(|pat| { - sm.span_to_snippet(pat.span) - .ok() - .map(|snippet| (snippet, "_".to_owned())) - }) - .collect::>>()?, - )) - } else { - let name = sm.span_to_snippet(arg.pat.span).ok()?; - Some(ArgKind::Arg(name, "_".to_owned())) - } - }) - .collect::>>()?, - ), - Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref sig, ..), .. }) - | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. }) - | Node::TraitItem(&hir::TraitItem { - kind: hir::TraitItemKind::Fn(ref sig, _), .. - }) => ( - sig.span, - None, - sig.decl - .inputs - .iter() - .map(|arg| match arg.kind { - hir::TyKind::Tup(tys) => ArgKind::Tuple( - Some(arg.span), - vec![("_".to_owned(), "_".to_owned()); tys.len()], - ), - _ => ArgKind::empty(), - }) - .collect::>(), - ), - Node::Ctor(variant_data) => { - let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id)); - (span, None, vec![ArgKind::empty(); variant_data.fields().len()]) - } - _ => panic!("non-FnLike node found: {node:?}"), - }) - } - - /// Reports an error when the number of arguments needed by a - /// trait match doesn't match the number that the expression - /// provides. - fn report_arg_count_mismatch( - &self, - span: Span, - found_span: Option, - expected_args: Vec, - found_args: Vec, - is_closure: bool, - closure_arg_span: Option, - ) -> Diag<'_> { - let kind = if is_closure { "closure" } else { "function" }; - - let args_str = |arguments: &[ArgKind], other: &[ArgKind]| { - let arg_length = arguments.len(); - let distinct = matches!(other, &[ArgKind::Tuple(..)]); - match (arg_length, arguments.get(0)) { - (1, Some(ArgKind::Tuple(_, fields))) => { - format!("a single {}-tuple as argument", fields.len()) - } - _ => format!( - "{} {}argument{}", - arg_length, - if distinct && arg_length > 1 { "distinct " } else { "" }, - pluralize!(arg_length) - ), - } - }; - - let expected_str = args_str(&expected_args, &found_args); - let found_str = args_str(&found_args, &expected_args); - - let mut err = struct_span_code_err!( - self.dcx(), - span, - E0593, - "{} is expected to take {}, but it takes {}", - kind, - expected_str, - found_str, - ); - - err.span_label(span, format!("expected {kind} that takes {expected_str}")); - - if let Some(found_span) = found_span { - err.span_label(found_span, format!("takes {found_str}")); - - // Suggest to take and ignore the arguments with expected_args_length `_`s if - // found arguments is empty (assume the user just wants to ignore args in this case). - // For example, if `expected_args_length` is 2, suggest `|_, _|`. - if found_args.is_empty() && is_closure { - let underscores = vec!["_"; expected_args.len()].join(", "); - err.span_suggestion_verbose( - closure_arg_span.unwrap_or(found_span), - format!( - "consider changing the closure to take and ignore the expected argument{}", - pluralize!(expected_args.len()) - ), - format!("|{underscores}|"), - Applicability::MachineApplicable, - ); - } - - if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] { - if fields.len() == expected_args.len() { - let sugg = fields - .iter() - .map(|(name, _)| name.to_owned()) - .collect::>() - .join(", "); - err.span_suggestion_verbose( - found_span, - "change the closure to take multiple arguments instead of a single tuple", - format!("|{sugg}|"), - Applicability::MachineApplicable, - ); - } - } - if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] - && fields.len() == found_args.len() - && is_closure - { - let sugg = format!( - "|({}){}|", - found_args - .iter() - .map(|arg| match arg { - ArgKind::Arg(name, _) => name.to_owned(), - _ => "_".to_owned(), - }) - .collect::>() - .join(", "), - // add type annotations if available - if found_args.iter().any(|arg| match arg { - ArgKind::Arg(_, ty) => ty != "_", - _ => false, - }) { - format!( - ": ({})", - fields - .iter() - .map(|(_, ty)| ty.to_owned()) - .collect::>() - .join(", ") - ) - } else { - String::new() - }, - ); - err.span_suggestion_verbose( - found_span, - "change the closure to accept a tuple instead of individual arguments", - sugg, - Applicability::MachineApplicable, - ); - } - } - - err - } - - /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce` - /// in that order, and returns the generic type corresponding to the - /// argument of that trait (corresponding to the closure arguments). - fn type_implements_fn_trait( - &self, - param_env: ty::ParamEnv<'tcx>, - ty: ty::Binder<'tcx, Ty<'tcx>>, - polarity: ty::PredicatePolarity, - ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> { - self.commit_if_ok(|_| { - for trait_def_id in [ - self.tcx.lang_items().fn_trait(), - self.tcx.lang_items().fn_mut_trait(), - self.tcx.lang_items().fn_once_trait(), - ] { - let Some(trait_def_id) = trait_def_id else { continue }; - // Make a fresh inference variable so we can determine what the generic parameters - // of the trait are. - let var = self.next_ty_var(DUMMY_SP); - // FIXME(effects) - let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]); - let obligation = Obligation::new( - self.tcx, - ObligationCause::dummy(), - param_env, - ty.rebind(ty::TraitPredicate { trait_ref, polarity }), - ); - let ocx = ObligationCtxt::new(self); - ocx.register_obligation(obligation); - if ocx.select_all_or_error().is_empty() { - return Ok(( - self.tcx - .fn_trait_kind_from_def_id(trait_def_id) - .expect("expected to map DefId to ClosureKind"), - ty.rebind(self.resolve_vars_if_possible(var)), - )); - } - } - - Err(()) - }) - } -} diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index 10624786baeac..87fdc5ddff85c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -1,6 +1,5 @@ pub mod ambiguity; mod fulfillment_errors; -mod infer_ctxt_ext; pub mod on_unimplemented; mod overflow; pub mod suggestions; @@ -23,7 +22,6 @@ use rustc_span::{ErrorGuaranteed, ExpnKind, Span}; use crate::error_reporting::TypeErrCtxt; use crate::traits::{FulfillmentError, FulfillmentErrorCode}; -pub use self::infer_ctxt_ext::*; pub use self::overflow::*; // When outputting impl candidates, prefer showing those that are more similar. diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index d2a34c7558321..0ed7859418bc5 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::{ use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi; -use rustc_trait_selection::error_reporting::traits::InferCtxtExt as _; +use rustc_trait_selection::error_reporting::InferCtxtErrorExt as _; declare_clippy_lint! { /// ### What it does @@ -178,7 +178,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { // 'cuz currently nothing changes after deleting this check. local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr) }) { - match cx.tcx.infer_ctxt().build().type_implements_fn_trait( + match cx.tcx.infer_ctxt().build().err_ctxt().type_implements_fn_trait( cx.param_env, Binder::bind_with_vars(callee_ty_adjusted, List::empty()), ty::PredicatePolarity::Positive, From e8e6111f869e834bf224c9c01fdf430cbd7da924 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 24 Jun 2024 11:57:52 +0200 Subject: [PATCH 07/12] Migrate `run-make/link-framework` to `rmake.rs` --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/link-framework/Makefile | 23 ----------- tests/run-make/link-framework/rmake.rs | 38 +++++++++++++++++++ 3 files changed, 38 insertions(+), 24 deletions(-) delete mode 100644 tests/run-make/link-framework/Makefile create mode 100644 tests/run-make/link-framework/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 1cb52ea91f9c2..acda41a0cdf17 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -46,7 +46,6 @@ run-make/libtest-json/Makefile run-make/libtest-junit/Makefile run-make/libtest-thread-limit/Makefile run-make/link-cfg/Makefile -run-make/link-framework/Makefile run-make/long-linker-command-lines-cmd-exe/Makefile run-make/long-linker-command-lines/Makefile run-make/lto-linkage-used-attr/Makefile diff --git a/tests/run-make/link-framework/Makefile b/tests/run-make/link-framework/Makefile deleted file mode 100644 index 96d832ad4a832..0000000000000 --- a/tests/run-make/link-framework/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# only-apple -# -# Check that linking to a framework actually makes it to the linker. - -include ../tools.mk - -all: - $(RUSTC) dep-link-framework.rs - $(RUSTC) dep-link-weak-framework.rs - - $(RUSTC) empty.rs - otool -L $(TMPDIR)/no-link | $(CGREP) -v CoreFoundation - - $(RUSTC) link-framework.rs - otool -L $(TMPDIR)/link-framework | $(CGREP) CoreFoundation | $(CGREP) -v weak - - $(RUSTC) link-weak-framework.rs - otool -L $(TMPDIR)/link-weak-framework | $(CGREP) CoreFoundation | $(CGREP) weak - -# When linking the framework both normally, and weakly, the weak linking takes preference - - $(RUSTC) link-both.rs - otool -L $(TMPDIR)/link-both | $(CGREP) CoreFoundation | $(CGREP) weak diff --git a/tests/run-make/link-framework/rmake.rs b/tests/run-make/link-framework/rmake.rs new file mode 100644 index 0000000000000..e5df93b181a09 --- /dev/null +++ b/tests/run-make/link-framework/rmake.rs @@ -0,0 +1,38 @@ +// Check that linking to a framework actually makes it to the linker. + +//@ only-apple + +use run_make_support::{cmd, rustc}; + +fn main() { + rustc().input("dep-link-framework.rs").run(); + rustc().input("dep-link-weak-framework.rs").run(); + + rustc().input("empty.rs").run(); + cmd("otool").arg("-L").arg("no-link").run_fail().assert_stdout_not_contains("CoreFoundation"); + + rustc().input("link-framework.rs").run(); + cmd("otool") + .arg("-L") + .arg("link-framework") + .run() + .assert_stdout_contains("CoreFoundation") + .assert_stdout_not_contains("weak"); + + rustc().input("link-weak-framework.rs").run(); + cmd("otool") + .arg("-L") + .arg("link-weak-framework") + .run() + .assert_stdout_contains("CoreFoundation") + .assert_stdout_contains("weak"); + + // When linking the framework both normally, and weakly, the weak linking takes preference. + rustc().input("link-both.rs").run(); + cmd("otool") + .arg("-L") + .arg("link-both") + .run() + .assert_stdout_contains("CoreFoundation") + .assert_stdout_contains("weak"); +} From 3fdd8d5ef3a8b26c3e24d9baf706fc7fb16717f9 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 31 May 2024 18:48:42 -0700 Subject: [PATCH 08/12] compiler: treat `&raw (const|mut) UNSAFE_STATIC` implied deref as safe The implied deref to statics introduced by HIR->THIR lowering is only used to create place expressions, it lacks unsafe semantics. It is also confusing, as there is no visible `*ident` in the source. For both classes of "unsafe static" (extern static and static mut) allow this operation. We lack a clear story around `thread_local! { static mut }`, which is actually its own category of item that reuses the static syntax but has its own rules. It's possible they should be similarly included, but in the absence of a good reason one way or another, we do not bless it. --- .../rustc_mir_build/src/check_unsafety.rs | 18 +++++++++++++ compiler/rustc_mir_build/src/thir/cx/expr.rs | 6 +++-- tests/ui/consts/const_refs_to_static.rs | 2 +- tests/ui/consts/mut-ptr-to-static.rs | 9 +++---- tests/ui/static/raw-ref-deref-with-unsafe.rs | 16 +++++++++++ .../ui/static/raw-ref-deref-without-unsafe.rs | 18 +++++++++++++ .../raw-ref-deref-without-unsafe.stderr | 19 +++++++++++++ tests/ui/static/raw-ref-extern-static.rs | 27 +++++++++++++++++++ tests/ui/static/raw-ref-static-mut.rs | 17 ++++++++++++ 9 files changed, 123 insertions(+), 9 deletions(-) create mode 100644 tests/ui/static/raw-ref-deref-with-unsafe.rs create mode 100644 tests/ui/static/raw-ref-deref-without-unsafe.rs create mode 100644 tests/ui/static/raw-ref-deref-without-unsafe.stderr create mode 100644 tests/ui/static/raw-ref-extern-static.rs create mode 100644 tests/ui/static/raw-ref-static-mut.rs diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 24098282d93b1..b4a69d7d7b7f2 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -449,6 +449,24 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } } } + ExprKind::AddressOf { arg, .. } => { + if let ExprKind::Scope { value: arg, .. } = self.thir[arg].kind + // THIR desugars UNSAFE_STATIC into *UNSAFE_STATIC_REF, where + // UNSAFE_STATIC_REF holds the addr of the UNSAFE_STATIC, so: take two steps + && let ExprKind::Deref { arg } = self.thir[arg].kind + // FIXME(workingjubiee): we lack a clear reason to reject ThreadLocalRef here, + // but we also have no conclusive reason to allow it either! + && let ExprKind::StaticRef { .. } = self.thir[arg].kind + { + // A raw ref to a place expr, even an "unsafe static", is okay! + // We short-circuit to not recursively traverse this expression. + return; + // note: const_mut_refs enables this code, and it currently remains unsafe: + // static mut BYTE: u8 = 0; + // static mut BYTE_PTR: *mut u8 = unsafe { addr_of_mut!(BYTE) }; + // static mut DEREF_BYTE_PTR: *mut u8 = unsafe { addr_of_mut!(*BYTE_PTR) }; + } + } ExprKind::Deref { arg } => { if let ExprKind::StaticRef { def_id, .. } | ExprKind::ThreadLocalRef(def_id) = self.thir[arg].kind diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index bd66257e6b687..0ba31f820b5c3 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -939,9 +939,11 @@ impl<'tcx> Cx<'tcx> { } } - // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is - // a constant reference (or constant raw pointer for `static mut`) in MIR + // A source Rust `path::to::STATIC` is a place expr like *&ident is. + // In THIR, we make them exactly equivalent by inserting the implied *& or *&raw, + // but distinguish between &STATIC and &THREAD_LOCAL as they have different semantics Res::Def(DefKind::Static { .. }, id) => { + // this is &raw for extern static or static mut, and & for other statics let ty = self.tcx.static_ptr_ty(id); let temp_lifetime = self .rvalue_scopes diff --git a/tests/ui/consts/const_refs_to_static.rs b/tests/ui/consts/const_refs_to_static.rs index 1baa8535b2c0a..f41725b786eb3 100644 --- a/tests/ui/consts/const_refs_to_static.rs +++ b/tests/ui/consts/const_refs_to_static.rs @@ -9,7 +9,7 @@ const C1: &i32 = &S; const C1_READ: () = { assert!(*C1 == 0); }; -const C2: *const i32 = unsafe { std::ptr::addr_of!(S_MUT) }; +const C2: *const i32 = std::ptr::addr_of!(S_MUT); fn main() { assert_eq!(*C1, 0); diff --git a/tests/ui/consts/mut-ptr-to-static.rs b/tests/ui/consts/mut-ptr-to-static.rs index d8a788bb37d1b..e921365c7d407 100644 --- a/tests/ui/consts/mut-ptr-to-static.rs +++ b/tests/ui/consts/mut-ptr-to-static.rs @@ -16,12 +16,9 @@ static mut STATIC: u32 = 42; static INTERIOR_MUTABLE_STATIC: SyncUnsafeCell = SyncUnsafeCell::new(42); // A static that mutably points to STATIC. -static PTR: SyncPtr = SyncPtr { - foo: unsafe { ptr::addr_of_mut!(STATIC) }, -}; -static INTERIOR_MUTABLE_PTR: SyncPtr = SyncPtr { - foo: ptr::addr_of!(INTERIOR_MUTABLE_STATIC) as *mut u32, -}; +static PTR: SyncPtr = SyncPtr { foo: ptr::addr_of_mut!(STATIC) }; +static INTERIOR_MUTABLE_PTR: SyncPtr = + SyncPtr { foo: ptr::addr_of!(INTERIOR_MUTABLE_STATIC) as *mut u32 }; fn main() { let ptr = PTR.foo; diff --git a/tests/ui/static/raw-ref-deref-with-unsafe.rs b/tests/ui/static/raw-ref-deref-with-unsafe.rs new file mode 100644 index 0000000000000..4b8f72de5b77d --- /dev/null +++ b/tests/ui/static/raw-ref-deref-with-unsafe.rs @@ -0,0 +1,16 @@ +//@ check-pass +#![feature(const_mut_refs)] +use std::ptr; + +// This code should remain unsafe because of the two unsafe operations here, +// even if in a hypothetical future we deem all &raw (const|mut) *ptr exprs safe. + +static mut BYTE: u8 = 0; +static mut BYTE_PTR: *mut u8 = ptr::addr_of_mut!(BYTE); +// An unsafe static's ident is a place expression in its own right, so despite the above being safe +// (it's fine to create raw refs to places!) the following derefs the ptr before creating its ref +static mut DEREF_BYTE_PTR: *mut u8 = unsafe { ptr::addr_of_mut!(*BYTE_PTR) }; + +fn main() { + let _ = unsafe { DEREF_BYTE_PTR }; +} diff --git a/tests/ui/static/raw-ref-deref-without-unsafe.rs b/tests/ui/static/raw-ref-deref-without-unsafe.rs new file mode 100644 index 0000000000000..f9bce4368c179 --- /dev/null +++ b/tests/ui/static/raw-ref-deref-without-unsafe.rs @@ -0,0 +1,18 @@ +#![feature(const_mut_refs)] + +use std::ptr; + +// This code should remain unsafe because of the two unsafe operations here, +// even if in a hypothetical future we deem all &raw (const|mut) *ptr exprs safe. + +static mut BYTE: u8 = 0; +static mut BYTE_PTR: *mut u8 = ptr::addr_of_mut!(BYTE); +// An unsafe static's ident is a place expression in its own right, so despite the above being safe +// (it's fine to create raw refs to places!) the following derefs the ptr before creating its ref! +static mut DEREF_BYTE_PTR: *mut u8 = ptr::addr_of_mut!(*BYTE_PTR); +//~^ ERROR: use of mutable static +//~| ERROR: dereference of raw pointer + +fn main() { + let _ = unsafe { DEREF_BYTE_PTR }; +} diff --git a/tests/ui/static/raw-ref-deref-without-unsafe.stderr b/tests/ui/static/raw-ref-deref-without-unsafe.stderr new file mode 100644 index 0000000000000..ac4df8b410c0e --- /dev/null +++ b/tests/ui/static/raw-ref-deref-without-unsafe.stderr @@ -0,0 +1,19 @@ +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/raw-ref-deref-without-unsafe.rs:12:56 + | +LL | static mut DEREF_BYTE_PTR: *mut u8 = ptr::addr_of_mut!(*BYTE_PTR); + | ^^^^^^^^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/raw-ref-deref-without-unsafe.rs:12:57 + | +LL | static mut DEREF_BYTE_PTR: *mut u8 = ptr::addr_of_mut!(*BYTE_PTR); + | ^^^^^^^^ 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 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/static/raw-ref-extern-static.rs b/tests/ui/static/raw-ref-extern-static.rs new file mode 100644 index 0000000000000..95a53a8640d37 --- /dev/null +++ b/tests/ui/static/raw-ref-extern-static.rs @@ -0,0 +1,27 @@ +//@ check-pass +#![feature(raw_ref_op)] +use std::ptr; + +// see https://github.com/rust-lang/rust/issues/125833 +// notionally, taking the address of an extern static is a safe operation, +// as we only point at it instead of generating a true reference to it + +// it may potentially induce linker errors, but the safety of that is not about taking addresses! +// any safety obligation of the extern static's correctness in declaration is on the extern itself, +// see RFC 3484 for more on that: https://rust-lang.github.io/rfcs/3484-unsafe-extern-blocks.html + +extern "C" { + static THERE: u8; + static mut SOMEWHERE: u8; +} + +fn main() { + let ptr2there = ptr::addr_of!(THERE); + let ptr2somewhere = ptr::addr_of!(SOMEWHERE); + let ptr2somewhere = ptr::addr_of_mut!(SOMEWHERE); + + // testing both addr_of and the expression it directly expands to + let raw2there = &raw const THERE; + let raw2somewhere = &raw const SOMEWHERE; + let raw2somewhere = &raw mut SOMEWHERE; +} diff --git a/tests/ui/static/raw-ref-static-mut.rs b/tests/ui/static/raw-ref-static-mut.rs new file mode 100644 index 0000000000000..6855cc7b050b5 --- /dev/null +++ b/tests/ui/static/raw-ref-static-mut.rs @@ -0,0 +1,17 @@ +//@ check-pass +#![feature(raw_ref_op)] +use std::ptr; + +// see https://github.com/rust-lang/rust/issues/125833 +// notionally, taking the address of a static mut is a safe operation, +// as we only point at it instead of generating a true reference to it +static mut NOWHERE: usize = 0; + +fn main() { + let p2nowhere = ptr::addr_of!(NOWHERE); + let p2nowhere = ptr::addr_of_mut!(NOWHERE); + + // testing both addr_of and the expression it directly expands to + let raw2nowhere = &raw const NOWHERE; + let raw2nowhere = &raw mut NOWHERE; +} From bf454afcaabb2406dda5e5d880ad061750caf4a8 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 31 May 2024 18:28:03 -0700 Subject: [PATCH 09/12] library: vary unsafety in bootstrapping for SEH --- library/panic_unwind/src/seh.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index 04c3d3bf9c359..82c248c5a7ba1 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -157,7 +157,10 @@ mod imp { // going to be cross-lang LTOed anyway. However, using expose is shorter and // requires less unsafe. let addr: usize = ptr.expose_provenance(); + #[cfg(bootstrap)] let image_base = unsafe { addr_of!(__ImageBase) }.addr(); + #[cfg(not(bootstrap))] + let image_base = addr_of!(__ImageBase).addr(); let offset: usize = addr - image_base; Self(offset as u32) } @@ -250,7 +253,10 @@ extern "C" { // This is fine since the MSVC runtime uses string comparison on the type name // to match TypeDescriptors rather than pointer equality. static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { + #[cfg(bootstrap)] pVFTable: unsafe { addr_of!(TYPE_INFO_VTABLE) } as *const _, + #[cfg(not(bootstrap))] + pVFTable: addr_of!(TYPE_INFO_VTABLE) as *const _, spare: core::ptr::null_mut(), name: TYPE_NAME, }; From b3cd9b5cd3470da7c8f05ed27a8c1db02422b805 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 31 May 2024 23:40:11 -0700 Subject: [PATCH 10/12] miri: fixup for allowing &raw UNSAFE_STATIC --- src/tools/miri/tests/fail/extern_static.rs | 2 +- src/tools/miri/tests/fail/extern_static.stderr | 4 ++-- src/tools/miri/tests/pass/static_mut.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/tests/fail/extern_static.rs b/src/tools/miri/tests/fail/extern_static.rs index f8805db8d1439..0cbf1646be9d8 100644 --- a/src/tools/miri/tests/fail/extern_static.rs +++ b/src/tools/miri/tests/fail/extern_static.rs @@ -5,5 +5,5 @@ extern "C" { } fn main() { - let _val = unsafe { std::ptr::addr_of!(FOO) }; //~ ERROR: is not supported by Miri + let _val = std::ptr::addr_of!(FOO); //~ ERROR: is not supported by Miri } diff --git a/src/tools/miri/tests/fail/extern_static.stderr b/src/tools/miri/tests/fail/extern_static.stderr index 21759f9601904..c7ab128e2fe97 100644 --- a/src/tools/miri/tests/fail/extern_static.stderr +++ b/src/tools/miri/tests/fail/extern_static.stderr @@ -1,8 +1,8 @@ error: unsupported operation: extern static `FOO` is not supported by Miri --> $DIR/extern_static.rs:LL:CC | -LL | let _val = unsafe { std::ptr::addr_of!(FOO) }; - | ^^^ extern static `FOO` is not supported by Miri +LL | let _val = std::ptr::addr_of!(FOO); + | ^^^ extern static `FOO` is not supported by Miri | = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support = note: BACKTRACE: diff --git a/src/tools/miri/tests/pass/static_mut.rs b/src/tools/miri/tests/pass/static_mut.rs index 1b416cc4e9b08..4488b5a09d5ba 100644 --- a/src/tools/miri/tests/pass/static_mut.rs +++ b/src/tools/miri/tests/pass/static_mut.rs @@ -2,7 +2,7 @@ use std::ptr::addr_of; static mut FOO: i32 = 42; -static BAR: Foo = Foo(unsafe { addr_of!(FOO) }); +static BAR: Foo = Foo(addr_of!(FOO)); #[allow(dead_code)] struct Foo(*const i32); From 0c414dddc01f3bf05766f9826832674c64352e60 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Sun, 21 Jul 2024 01:25:59 +0300 Subject: [PATCH 11/12] Disallow hidden references to mutable static --- .../rustc_driver_impl/src/signal_handler.rs | 2 + compiler/rustc_hir_analysis/messages.ftl | 20 +-- compiler/rustc_hir_analysis/src/check/errs.rs | 145 +++++++++++++----- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- .../rustc_hir_analysis/src/check/region.rs | 4 +- compiler/rustc_hir_analysis/src/collect.rs | 2 + compiler/rustc_hir_analysis/src/errors.rs | 20 ++- 7 files changed, 132 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_driver_impl/src/signal_handler.rs b/compiler/rustc_driver_impl/src/signal_handler.rs index 441219eec90dc..1a3ad78cefd04 100644 --- a/compiler/rustc_driver_impl/src/signal_handler.rs +++ b/compiler/rustc_driver_impl/src/signal_handler.rs @@ -34,6 +34,8 @@ macro raw_errln($tokens:tt) { } /// Signal handler installed for SIGSEGV +// FIXME(obeis): Use `SyncUnsafeCell` instead of allowing `static_mut_refs` lint +#[allow(static_mut_refs)] extern "C" fn print_stack_trace(_: libc::c_int) { const MAX_FRAMES: usize = 256; // Reserve data segment so we don't have to malloc in a signal handler, which might fail diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index cc404daa51f59..efb389b6bd95d 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -463,24 +463,20 @@ 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 = 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 - } +hir_analysis_static_mut_ref = creating a {$shared_label}reference to a mutable static + .label = {$shared_label}reference to mutable static + .shared_note = shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + .mut_note = mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's 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 +hir_analysis_static_mut_refs_lint = creating a {$shared_label}reference to mutable static is discouraged + .label = {$shared_label}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 - } + .shared_note = shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + .mut_note = mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's 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 19a0476e63016..d0884debef20b 100644 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ b/compiler/rustc_hir_analysis/src/check/errs.rs @@ -1,60 +1,113 @@ use rustc_hir as hir; use rustc_lint_defs::builtin::STATIC_MUT_REFS; -use rustc_middle::ty::{Mutability, TyCtxt}; +use rustc_middle::ty::{Mutability, TyCtxt, TyKind}; use rustc_span::Span; use crate::errors; /// Check for shared or mutable references of `static mut` inside expression -pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) { - let span = expr.span; - let hir_id = expr.hir_id; - if let hir::ExprKind::AddrOf(borrow_kind, m, expr) = expr.kind - && matches!(borrow_kind, hir::BorrowKind::Ref) - && path_if_static_mut(expr) - { - handle_static_mut_ref( - tcx, - span, - span.with_hi(expr.span.lo()), - span.shrink_to_hi(), - span.edition().at_least_rust_2024(), - m, - hir_id, - ); +pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) { + let err_span = expr.span; + let lint_level_hir_id = expr.hir_id; + match expr.kind { + hir::ExprKind::AddrOf(borrow_kind, m, ex) + if matches!(borrow_kind, hir::BorrowKind::Ref) + && let Some(err_span) = path_is_static_mut(ex, err_span) => + { + handle_static_mut_ref( + tcx, + err_span, + err_span.with_hi(ex.span.lo()), + err_span.shrink_to_hi(), + err_span.edition().at_least_rust_2024(), + Some(m), + lint_level_hir_id, + !expr.span.from_expansion(), + ); + } + hir::ExprKind::Index(expr, _, _) + if let Some(err_span) = path_is_static_mut(expr, err_span) => + { + handle_static_mut_ref( + tcx, + err_span, + err_span.with_hi(expr.span.lo()), + err_span.shrink_to_hi(), + err_span.edition().at_least_rust_2024(), + None, + lint_level_hir_id, + false, + ); + } + _ => {} } } /// Check for shared or mutable references of `static mut` inside statement -pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) { +pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: &hir::Stmt<'_>) { if let hir::StmtKind::Let(loc) = stmt.kind && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind && let hir::ByRef::Yes(rmutbl) = ba.0 && let Some(init) = loc.init - && path_if_static_mut(init) + && let Some(err_span) = path_is_static_mut(init, init.span) { handle_static_mut_ref( tcx, - init.span, - init.span.shrink_to_lo(), - init.span.shrink_to_hi(), + err_span, + err_span.shrink_to_lo(), + err_span.shrink_to_hi(), loc.span.edition().at_least_rust_2024(), - rmutbl, + Some(rmutbl), stmt.hir_id, + false, + ); + } +} + +/// Check if method call takes shared or mutable references of `static mut` +#[allow(rustc::usage_of_ty_tykind)] +pub fn maybe_method_static_mut(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) { + if let hir::ExprKind::MethodCall(_, e, _, _) = expr.kind + && let Some(err_span) = path_is_static_mut(e, expr.span) + && let typeck = tcx.typeck(expr.hir_id.owner) + && let Some(method_def_id) = typeck.type_dependent_def_id(expr.hir_id) + && let inputs = tcx.fn_sig(method_def_id).skip_binder().inputs().skip_binder() + && !inputs.is_empty() + && inputs[0].is_ref() + { + let m = if let TyKind::Ref(_, _, m) = inputs[0].kind() { *m } else { Mutability::Not }; + + handle_static_mut_ref( + tcx, + err_span, + err_span.shrink_to_lo(), + err_span.shrink_to_hi(), + err_span.edition().at_least_rust_2024(), + Some(m), + expr.hir_id, + false, ); } } -fn path_if_static_mut(expr: &hir::Expr<'_>) -> bool { +fn path_is_static_mut(mut expr: &hir::Expr<'_>, mut err_span: Span) -> Option { + if err_span.from_expansion() { + err_span = expr.span; + } + + while let hir::ExprKind::Field(e, _) = expr.kind { + expr = e; + } + if let hir::ExprKind::Path(qpath) = expr.kind && let hir::QPath::Resolved(_, path) = qpath && let hir::def::Res::Def(def_kind, _) = path.res && let hir::def::DefKind::Static { safety: _, mutability: Mutability::Mut, nested: false } = def_kind { - return true; + return Some(err_span); } - false + None } fn handle_static_mut_ref( @@ -63,27 +116,37 @@ fn handle_static_mut_ref( lo: Span, hi: Span, e2024: bool, - mutable: Mutability, - hir_id: hir::HirId, + mutable: Option, + lint_level_hir_id: hir::HirId, + suggest_addr_of: bool, ) { + let (shared_label, shared_note, mut_note, sugg) = match mutable { + Some(Mutability::Mut) => { + let sugg = + if suggest_addr_of { Some(errors::MutRefSugg::Mut { lo, hi }) } else { None }; + ("mutable ", false, true, sugg) + } + Some(Mutability::Not) => { + let sugg = + if suggest_addr_of { Some(errors::MutRefSugg::Shared { lo, hi }) } else { None }; + ("shared ", true, false, sugg) + } + None => ("", true, true, None), + }; if e2024 { - let (sugg, shared) = if mutable == Mutability::Mut { - (errors::MutRefSugg::Mut { lo, hi }, "mutable") - } else { - (errors::MutRefSugg::Shared { lo, hi }, "shared") - }; - tcx.dcx().emit_err(errors::StaticMutRef { span, sugg, shared }); + tcx.dcx().emit_err(errors::StaticMutRef { + span, + sugg, + shared_label, + shared_note, + mut_note, + }); } else { - let (sugg, shared) = if mutable == Mutability::Mut { - (errors::MutRefSugg::Mut { lo, hi }, "mutable") - } else { - (errors::MutRefSugg::Shared { lo, hi }, "shared") - }; tcx.emit_node_span_lint( STATIC_MUT_REFS, - hir_id, + lint_level_hir_id, span, - errors::RefOfMutStatic { span, sugg, shared }, + errors::RefOfMutStatic { span, sugg, shared_label, shared_note, mut_note }, ); } } diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 4c230ad84def6..51290c8d247ef 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -66,7 +66,7 @@ mod check; mod compare_impl_item; pub mod dropck; mod entry; -mod errs; +pub mod errs; pub mod intrinsic; pub mod intrinsicck; mod region; diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 2b5efd3b2f6f9..5d7effa113746 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -228,7 +228,7 @@ fn resolve_stmt<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, stmt: &'tcx h let stmt_id = stmt.hir_id.local_id; debug!("resolve_stmt(stmt.id={:?})", stmt_id); - maybe_stmt_static_mut(visitor.tcx, *stmt); + maybe_stmt_static_mut(visitor.tcx, stmt); // Every statement will clean up the temporaries created during // execution of that statement. Therefore each statement has an @@ -248,7 +248,7 @@ fn resolve_stmt<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, stmt: &'tcx h fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx hir::Expr<'tcx>) { debug!("resolve_expr - pre-increment {} expr = {:?}", visitor.expr_and_pat_count, expr); - maybe_expr_static_mut(visitor.tcx, *expr); + maybe_expr_static_mut(visitor.tcx, expr); let prev_cx = visitor.cx; visitor.enter_node_scope_with_dtor(expr.hir_id.local_id); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 565351268c96b..dc1fedb18e346 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -43,6 +43,7 @@ use std::cell::Cell; use std::iter; use std::ops::Bound; +use crate::check::errs::maybe_method_static_mut; use crate::check::intrinsic::intrinsic_operation_unsafety; use crate::errors; use crate::hir_ty_lowering::{HirTyLowerer, RegionInferReason}; @@ -324,6 +325,7 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { // depends on typecheck and would therefore hide // any further errors in case one typeck fails. } + maybe_method_static_mut(self.tcx, expr); intravisit::walk_expr(self, expr); } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index c83788928a978..e7ab4b9724cff 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1502,14 +1502,17 @@ pub struct OnlyCurrentTraitsPointerSugg<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_static_mut_ref, code = E0796)] -#[note] pub struct StaticMutRef<'a> { #[primary_span] #[label] pub span: Span, #[subdiagnostic] - pub sugg: MutRefSugg, - pub shared: &'a str, + pub sugg: Option, + pub shared_label: &'a str, + #[note(hir_analysis_shared_note)] + pub shared_note: bool, + #[note(hir_analysis_mut_note)] + pub mut_note: bool, } #[derive(Subdiagnostic)] @@ -1538,17 +1541,20 @@ pub enum MutRefSugg { }, } -// STATIC_MUT_REF lint +// `STATIC_MUT_REF` lint #[derive(LintDiagnostic)] #[diag(hir_analysis_static_mut_refs_lint)] #[note] -#[note(hir_analysis_why_note)] pub struct RefOfMutStatic<'a> { #[label] pub span: Span, #[subdiagnostic] - pub sugg: MutRefSugg, - pub shared: &'a str, + pub sugg: Option, + pub shared_label: &'a str, + #[note(hir_analysis_shared_note)] + pub shared_note: bool, + #[note(hir_analysis_mut_note)] + pub mut_note: bool, } #[derive(Diagnostic)] From 58040b7a8d8d2e06dac7c2ba580f1a42b0e65ac1 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Sun, 21 Jul 2024 01:26:36 +0300 Subject: [PATCH 12/12] Update tests for hidden references to mutable static --- library/alloc/tests/vec.rs | 2 + library/core/tests/atomic.rs | 2 + library/panic_unwind/src/seh.rs | 2 + library/std/src/sync/mod.rs | 3 + library/std/src/thread/local/tests.rs | 3 + .../ui/checked_unwrap/simple_conditionals.rs | 1 + .../checked_unwrap/simple_conditionals.stderr | 14 +- .../tests/ui/redundant_static_lifetimes.fixed | 2 + .../tests/ui/redundant_static_lifetimes.rs | 2 + .../ui/redundant_static_lifetimes.stderr | 36 ++-- .../clippy/tests/ui/useless_conversion.fixed | 2 + .../clippy/tests/ui/useless_conversion.rs | 2 + .../clippy/tests/ui/useless_conversion.stderr | 74 ++++---- .../tests/pass-dep/concurrency/linux-futex.rs | 3 + .../concurrency/tls_pthread_drop_order.rs | 3 + .../miri/tests/pass-dep/libc/libc-eventfd.rs | 3 + .../tests/pass-dep/libc/libc-socketpair.rs | 4 + src/tools/miri/tests/pass/atomic.rs | 4 + .../tests/pass/static_memory_modification.rs | 3 + src/tools/miri/tests/pass/static_mut.rs | 3 + src/tools/miri/tests/pass/tls/tls_static.rs | 2 + src/tools/tidy/src/issues.txt | 1 - tests/ui/abi/statics/static-mut-foreign.rs | 5 + .../ui/abi/statics/static-mut-foreign.stderr | 62 ++++++- tests/ui/array-slice-vec/slice-panic-1.rs | 12 +- tests/ui/array-slice-vec/slice-panic-2.rs | 9 +- tests/ui/array-slice-vec/slice.rs | 23 ++- .../issues/issue-67611-static-mut-refs.rs | 2 + .../issues/issue-67611-static-mut-refs.stderr | 25 +++ tests/ui/binding/order-drop-with-match.rs | 4 + tests/ui/binding/order-drop-with-match.stderr | 46 +++++ .../borrowck-access-permissions.stderr | 2 +- ...rowck-unsafe-static-mutable-borrows.stderr | 2 +- tests/ui/borrowck/issue-20801.stderr | 2 +- ...5492-borrowck-migrate-scans-parents.stderr | 6 +- tests/ui/consts/const_let_assign2.stderr | 2 +- tests/ui/consts/static-mut-refs.rs | 2 + tests/ui/consts/static-mut-refs.stderr | 25 +++ .../static-mut-reference-across-yield.rs | 2 +- .../static-mut-reference-across-yield.stderr | 18 ++ tests/ui/drop/drop-struct-as-object.rs | 10 +- tests/ui/drop/drop-struct-as-object.stderr | 2 +- ...issue-23338-ensure-param-drop-order.stderr | 2 +- .../drop/issue-23611-enum-swap-in-drop.stderr | 2 +- tests/ui/drop/issue-48962.rs | 3 + tests/ui/drop/issue-48962.stderr | 35 ++++ tests/ui/drop/repeat-drop.rs | 32 ++-- .../static-issue-17302.rs} | 3 + tests/ui/drop/static-issue-17302.stderr | 36 ++++ .../cleanup-rvalue-during-if-and-while.rs | 10 +- ...nctional-struct-update-respects-privacy.rs | 1 + ...onal-struct-update-respects-privacy.stderr | 15 +- tests/ui/issues/issue-10734.rs | 10 +- tests/ui/issues/issue-15858.rs | 13 +- tests/ui/issues/issue-15858.stderr | 2 +- tests/ui/issues/issue-16151.rs | 1 + tests/ui/issues/issue-16151.stderr | 13 ++ tests/ui/issues/issue-39367.rs | 2 +- tests/ui/issues/issue-54410.stderr | 2 +- tests/ui/issues/issue-8860.rs | 36 ++-- tests/ui/link-section.rs | 1 + tests/ui/link-section.stderr | 13 ++ .../linkage-attr-mutable-static.rs | 1 + .../linkage-attr-mutable-static.stderr | 13 +- tests/ui/lto/lto-still-runs-thread-dtors.rs | 23 ++- tests/ui/methods/method-self-arg-trait.rs | 41 ++++- tests/ui/methods/method-self-arg.rs | 1 + tests/ui/methods/method-self-arg.stderr | 13 ++ tests/ui/mir/mir_early_return_scope.rs | 13 +- ...local-static-mut-borrow-outlives-fn.stderr | 2 +- tests/ui/nll/issue-69114-static-mut-ty.rs | 4 + tests/ui/nll/issue-69114-static-mut-ty.stderr | 47 ++++- tests/ui/self/where-for-self.rs | 17 +- ...rr => ref-to-mut-static-safe.e2021.stderr} | 6 +- ...rr => ref-to-mut-static-safe.e2024.stderr} | 6 +- ...atic-safe.rs => ref-to-mut-static-safe.rs} | 0 .../ui/static/ref-to-mut-static.e2021.stderr | 170 ++++++++++++++++++ .../ui/static/ref-to-mut-static.e2024.stderr | 140 +++++++++++++++ tests/ui/static/ref-to-mut-static.rs | 90 ++++++++++ .../reference-to-mut-static-unsafe-fn.stderr | 20 +-- .../reference-to-mut-static.e2021.stderr | 91 ---------- .../reference-to-mut-static.e2024.stderr | 75 -------- tests/ui/static/reference-to-mut-static.rs | 50 ------ .../ui/static/safe-extern-statics-mut.stderr | 4 +- tests/ui/statics/issue-15261.stderr | 2 +- tests/ui/statics/static-mut-xc.rs | 5 + tests/ui/statics/static-mut-xc.stderr | 62 ++++++- tests/ui/statics/static-recursive.rs | 1 + tests/ui/statics/static-recursive.stderr | 14 +- .../thread-local/thread-local-issue-37508.rs | 1 + .../thread-local-issue-37508.stderr | 17 ++ tests/ui/traits/impl.rs | 16 +- tests/ui/traits/impl.stderr | 2 +- tests/ui/union/union-drop-assign.rs | 18 +- tests/ui/union/union-drop.rs | 44 ++--- 95 files changed, 1198 insertions(+), 475 deletions(-) create mode 100644 tests/ui/async-await/issues/issue-67611-static-mut-refs.stderr create mode 100644 tests/ui/binding/order-drop-with-match.stderr create mode 100644 tests/ui/consts/static-mut-refs.stderr create mode 100644 tests/ui/coroutine/static-mut-reference-across-yield.stderr create mode 100644 tests/ui/drop/issue-48962.stderr rename tests/ui/{issues/issue-17302.rs => drop/static-issue-17302.rs} (60%) create mode 100644 tests/ui/drop/static-issue-17302.stderr create mode 100644 tests/ui/issues/issue-16151.stderr create mode 100644 tests/ui/link-section.stderr create mode 100644 tests/ui/methods/method-self-arg.stderr rename tests/ui/static/{reference-to-mut-static-safe.e2021.stderr => ref-to-mut-static-safe.e2021.stderr} (75%) rename tests/ui/static/{reference-to-mut-static-safe.e2024.stderr => ref-to-mut-static-safe.e2024.stderr} (70%) rename tests/ui/static/{reference-to-mut-static-safe.rs => ref-to-mut-static-safe.rs} (100%) create mode 100644 tests/ui/static/ref-to-mut-static.e2021.stderr create mode 100644 tests/ui/static/ref-to-mut-static.e2024.stderr create mode 100644 tests/ui/static/ref-to-mut-static.rs delete mode 100644 tests/ui/static/reference-to-mut-static.e2021.stderr delete mode 100644 tests/ui/static/reference-to-mut-static.e2024.stderr delete mode 100644 tests/ui/static/reference-to-mut-static.rs create mode 100644 tests/ui/thread-local/thread-local-issue-37508.stderr diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 71d79893e01d7..8a0a95f20e452 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1285,6 +1285,8 @@ fn test_from_iter_specialization_panic_during_iteration_drops() { #[test] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +// FIXME(obeis): Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint +#[cfg_attr(not(bootstrap), allow(static_mut_refs))] fn test_from_iter_specialization_panic_during_drop_doesnt_leak() { static mut DROP_COUNTER_OLD: [usize; 5] = [0; 5]; static mut DROP_COUNTER_NEW: [usize; 2] = [0; 2]; diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs index 0d1c72a689291..d6874fb25e411 100644 --- a/library/core/tests/atomic.rs +++ b/library/core/tests/atomic.rs @@ -228,6 +228,8 @@ fn static_init() { } #[test] +// FIXME(obeis): Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint +#[cfg_attr(not(bootstrap), allow(static_mut_refs))] fn atomic_access_bool() { static mut ATOMIC: AtomicBool = AtomicBool::new(false); diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index 04c3d3bf9c359..e0b3eefea9463 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -291,6 +291,8 @@ cfg_if::cfg_if! { } } +// FIXME(obeis): Do not allow `static_mut_refs` lint +#[allow(static_mut_refs)] pub unsafe fn panic(data: Box) -> u32 { use core::intrinsics::atomic_store_seqcst; diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 9a38c42f43a02..f90382f3c868b 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -9,6 +9,9 @@ //! Consider the following code, operating on some global static variables: //! //! ```rust +//! // FIXME(obeis): Do not allow `static_mut_refs` lint +//! #![allow(static_mut_refs)] +//! //! static mut A: u32 = 0; //! static mut B: u32 = 0; //! static mut C: u32 = 0; diff --git a/library/std/src/thread/local/tests.rs b/library/std/src/thread/local/tests.rs index 25019b554bb6a..12f6e1236727f 100644 --- a/library/std/src/thread/local/tests.rs +++ b/library/std/src/thread/local/tests.rs @@ -103,6 +103,9 @@ fn smoke_dtor() { #[test] fn circular() { + // FIXME(obeis): Do not allow `static_mut_refs` lint + #![allow(static_mut_refs)] + struct S1(&'static LocalKey>>, &'static LocalKey>>); struct S2(&'static LocalKey>>, &'static LocalKey>>); thread_local!(static K1: UnsafeCell> = UnsafeCell::new(None)); diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs index c3c8562edffba..499b8711c883d 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs +++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs @@ -172,6 +172,7 @@ fn issue11371() { static mut X: Option = Some(123); unsafe { if X.is_some() { + //~^ ERROR: creating a shared reference to mutable static is discouraged X = None; X.unwrap(); } diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr index ddd600418afec..65e5dcc6030d5 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -1,3 +1,15 @@ +error: creating a shared reference to mutable static is discouraged + --> tests/ui/checked_unwrap/simple_conditionals.rs:174:12 + | +LL | if X.is_some() { + | ^^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: `-D static-mut-refs` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(static_mut_refs)]` + error: called `unwrap` on `x` after checking its variant with `is_some` --> tests/ui/checked_unwrap/simple_conditionals.rs:46:9 | @@ -236,5 +248,5 @@ LL | if result.is_ok() { LL | result.as_mut().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 25 previous errors +error: aborting due to 26 previous errors diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed b/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed index 9787bb635e709..472a4e19191fd 100644 --- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed +++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed @@ -1,4 +1,6 @@ #![allow(unused)] +// FIXME(obeis): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] #[derive(Debug)] struct Foo; diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs b/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs index b5a4827fa948e..9f24dfa14e285 100644 --- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs +++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs @@ -1,4 +1,6 @@ #![allow(unused)] +// FIXME(obeis): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] #[derive(Debug)] struct Foo; diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr b/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr index 5c5e2f2a57360..48871eba2dc75 100644 --- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr +++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr @@ -1,5 +1,5 @@ error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:6:17 + --> tests/ui/redundant_static_lifetimes.rs:8:17 | LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR: Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` @@ -8,103 +8,103 @@ LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR: Consider removi = help: to override `-D warnings` add `#[allow(clippy::redundant_static_lifetimes)]` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:10:21 + --> tests/ui/redundant_static_lifetimes.rs:12:21 | LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:12:32 + --> tests/ui/redundant_static_lifetimes.rs:14:32 | LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:12:47 + --> tests/ui/redundant_static_lifetimes.rs:14:47 | LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:14:17 + --> tests/ui/redundant_static_lifetimes.rs:16:17 | LL | const VAR_SIX: &'static u8 = &5; | -^^^^^^^--- help: consider removing `'static`: `&u8` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:16:20 + --> tests/ui/redundant_static_lifetimes.rs:18:20 | LL | const VAR_HEIGHT: &'static Foo = &Foo {}; | -^^^^^^^---- help: consider removing `'static`: `&Foo` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:18:19 + --> tests/ui/redundant_static_lifetimes.rs:20:19 | LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR: Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:20:19 + --> tests/ui/redundant_static_lifetimes.rs:22:19 | LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: constants have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:22:19 + --> tests/ui/redundant_static_lifetimes.rs:24:19 | LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:24:25 + --> tests/ui/redundant_static_lifetimes.rs:26:25 | LL | static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR: Consider removing 'static. | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:28:29 + --> tests/ui/redundant_static_lifetimes.rs:30:29 | LL | static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static | -^^^^^^^---- help: consider removing `'static`: `&str` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:30:25 + --> tests/ui/redundant_static_lifetimes.rs:32:25 | LL | static STATIC_VAR_SIX: &'static u8 = &5; | -^^^^^^^--- help: consider removing `'static`: `&u8` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:32:28 + --> tests/ui/redundant_static_lifetimes.rs:34:28 | LL | static STATIC_VAR_HEIGHT: &'static Foo = &Foo {}; | -^^^^^^^---- help: consider removing `'static`: `&Foo` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:34:27 + --> tests/ui/redundant_static_lifetimes.rs:36:27 | LL | static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR: Consider removing 'static. | -^^^^^^^----- help: consider removing `'static`: `&[u8]` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:36:27 + --> tests/ui/redundant_static_lifetimes.rs:38:27 | LL | static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static. | -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:38:27 + --> tests/ui/redundant_static_lifetimes.rs:40:27 | LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static. | -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:40:31 + --> tests/ui/redundant_static_lifetimes.rs:42:31 | LL | static mut STATIC_MUT_SLICE: &'static mut [u32] = &mut [0]; | -^^^^^^^---------- help: consider removing `'static`: `&mut [u32]` error: statics have by default a `'static` lifetime - --> tests/ui/redundant_static_lifetimes.rs:69:16 + --> tests/ui/redundant_static_lifetimes.rs:71:16 | LL | static V: &'static u8 = &17; | -^^^^^^^--- help: consider removing `'static`: `&u8` diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed index ce00fde2f9930..4e1979a83dd86 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.fixed +++ b/src/tools/clippy/tests/ui/useless_conversion.fixed @@ -1,5 +1,7 @@ #![deny(clippy::useless_conversion)] #![allow(clippy::needless_if, clippy::unnecessary_wraps)] +// FIXME(obeis): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] fn test_generic(val: T) -> T { let _ = val; diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs index 399796195868d..24db89af4e346 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.rs +++ b/src/tools/clippy/tests/ui/useless_conversion.rs @@ -1,5 +1,7 @@ #![deny(clippy::useless_conversion)] #![allow(clippy::needless_if, clippy::unnecessary_wraps)] +// FIXME(obeis): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] fn test_generic(val: T) -> T { let _ = T::from(val); diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr index 82f945c5e89f6..b149357bcf4f4 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.stderr +++ b/src/tools/clippy/tests/ui/useless_conversion.stderr @@ -1,5 +1,5 @@ error: useless conversion to the same type: `T` - --> tests/ui/useless_conversion.rs:5:13 + --> tests/ui/useless_conversion.rs:7:13 | LL | let _ = T::from(val); | ^^^^^^^^^^^^ help: consider removing `T::from()`: `val` @@ -11,217 +11,217 @@ LL | #![deny(clippy::useless_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: useless conversion to the same type: `T` - --> tests/ui/useless_conversion.rs:6:5 + --> tests/ui/useless_conversion.rs:8:5 | LL | val.into() | ^^^^^^^^^^ help: consider removing `.into()`: `val` error: useless conversion to the same type: `i32` - --> tests/ui/useless_conversion.rs:18:22 + --> tests/ui/useless_conversion.rs:20:22 | LL | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` error: useless conversion to the same type: `std::str::Lines<'_>` - --> tests/ui/useless_conversion.rs:48:22 + --> tests/ui/useless_conversion.rs:50:22 | LL | if Some("ok") == lines.into_iter().next() {} | ^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `lines` error: useless conversion to the same type: `std::str::Lines<'_>` - --> tests/ui/useless_conversion.rs:53:21 + --> tests/ui/useless_conversion.rs:55:21 | LL | let mut lines = text.lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()` error: useless conversion to the same type: `std::str::Lines<'_>` - --> tests/ui/useless_conversion.rs:59:22 + --> tests/ui/useless_conversion.rs:61:22 | LL | if Some("ok") == text.lines().into_iter().next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()` error: useless conversion to the same type: `std::ops::Range` - --> tests/ui/useless_conversion.rs:65:13 + --> tests/ui/useless_conversion.rs:67:13 | LL | let _ = NUMBERS.into_iter().next(); | ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS` error: useless conversion to the same type: `std::ops::Range` - --> tests/ui/useless_conversion.rs:70:17 + --> tests/ui/useless_conversion.rs:72:17 | LL | let mut n = NUMBERS.into_iter(); | ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:132:21 + --> tests/ui/useless_conversion.rs:134:21 | LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:133:21 + --> tests/ui/useless_conversion.rs:135:21 | LL | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:134:13 + --> tests/ui/useless_conversion.rs:136:13 | LL | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:135:13 + --> tests/ui/useless_conversion.rs:137:13 | LL | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` error: useless conversion to the same type: `std::str::Lines<'_>` - --> tests/ui/useless_conversion.rs:136:13 + --> tests/ui/useless_conversion.rs:138:13 | LL | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` error: useless conversion to the same type: `std::vec::IntoIter` - --> tests/ui/useless_conversion.rs:137:13 + --> tests/ui/useless_conversion.rs:139:13 | LL | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` error: useless conversion to the same type: `std::string::String` - --> tests/ui/useless_conversion.rs:138:21 + --> tests/ui/useless_conversion.rs:140:21 | LL | let _: String = format!("Hello {}", "world").into(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` error: useless conversion to the same type: `i32` - --> tests/ui/useless_conversion.rs:143:13 + --> tests/ui/useless_conversion.rs:145:13 | LL | let _ = i32::from(a + b) * 3; | ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)` error: useless conversion to the same type: `Foo<'a'>` - --> tests/ui/useless_conversion.rs:149:23 + --> tests/ui/useless_conversion.rs:151:23 | LL | let _: Foo<'a'> = s2.into(); | ^^^^^^^^^ help: consider removing `.into()`: `s2` error: useless conversion to the same type: `Foo<'a'>` - --> tests/ui/useless_conversion.rs:151:13 + --> tests/ui/useless_conversion.rs:153:13 | LL | let _ = Foo::<'a'>::from(s3); | ^^^^^^^^^^^^^^^^^^^^ help: consider removing `Foo::<'a'>::from()`: `s3` error: useless conversion to the same type: `std::vec::IntoIter>` - --> tests/ui/useless_conversion.rs:153:13 + --> tests/ui/useless_conversion.rs:155:13 | LL | let _ = vec![s4, s4, s4].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()` error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:185:7 + --> tests/ui/useless_conversion.rs:187:7 | LL | b(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:175:13 + --> tests/ui/useless_conversion.rs:177:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:186:7 + --> tests/ui/useless_conversion.rs:188:7 | LL | c(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:176:18 + --> tests/ui/useless_conversion.rs:178:18 | LL | fn c(_: impl IntoIterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:187:7 + --> tests/ui/useless_conversion.rs:189:7 | LL | d(vec![1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:179:12 + --> tests/ui/useless_conversion.rs:181:12 | LL | T: IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:190:7 + --> tests/ui/useless_conversion.rs:192:7 | LL | b(vec![1, 2].into_iter().into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:175:13 + --> tests/ui/useless_conversion.rs:177:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:191:7 + --> tests/ui/useless_conversion.rs:193:7 | LL | b(vec![1, 2].into_iter().into_iter().into_iter()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:175:13 + --> tests/ui/useless_conversion.rs:177:13 | LL | fn b>(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:237:24 + --> tests/ui/useless_conversion.rs:239:24 | LL | foo2::([1, 2, 3].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2, 3]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:216:12 + --> tests/ui/useless_conversion.rs:218:12 | LL | I: IntoIterator + Helper, | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:245:14 + --> tests/ui/useless_conversion.rs:247:14 | LL | foo3([1, 2, 3].into_iter()); | ^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2, 3]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:225:12 + --> tests/ui/useless_conversion.rs:227:12 | LL | I: IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:254:16 + --> tests/ui/useless_conversion.rs:256:16 | LL | S1.foo([1, 2].into_iter()); | ^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2]` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:251:27 + --> tests/ui/useless_conversion.rs:253:27 | LL | pub fn foo(&self, _: I) {} | ^^^^^^^^^^^^ error: explicit call to `.into_iter()` in function argument accepting `IntoIterator` - --> tests/ui/useless_conversion.rs:273:44 + --> tests/ui/useless_conversion.rs:275:44 | LL | v0.into_iter().interleave_shortest(v1.into_iter()); | ^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `v1` | note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()` - --> tests/ui/useless_conversion.rs:260:20 + --> tests/ui/useless_conversion.rs:262:20 | LL | J: IntoIterator, | ^^^^^^^^^^^^ diff --git a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs index d21f953672dee..638833d51d8a9 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs @@ -1,6 +1,9 @@ //@only-target-linux //@compile-flags: -Zmiri-disable-isolation +// FIXME(obeis): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] + use std::mem::MaybeUninit; use std::ptr::{self, addr_of}; use std::sync::atomic::AtomicI32; diff --git a/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs b/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs index 52348aad33d72..b86da3f49de3e 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs @@ -5,6 +5,9 @@ //! the fallback path in `guard::key::enable`, which uses a *single* pthread_key //! to manage a thread-local list of dtors to call. +// FIXME(obeis): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] + use std::mem; use std::ptr; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs index a3567eeb7cb4a..f7c115ec43df6 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs @@ -2,6 +2,9 @@ // test_race depends on a deterministic schedule. //@compile-flags: -Zmiri-preemption-rate=0 +// FIXME(obeis): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] + use std::thread; fn main() { diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs index 324c0127ee976..ac867d96177b7 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs @@ -1,6 +1,10 @@ //@ignore-target-windows: No libc socketpair on Windows // test_race depends on a deterministic schedule. //@compile-flags: -Zmiri-preemption-rate=0 + +// FIXME(obeis): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] + use std::thread; fn main() { test_socketpair(); diff --git a/src/tools/miri/tests/pass/atomic.rs b/src/tools/miri/tests/pass/atomic.rs index dfdc9b42f81fc..39b3fb267b7b9 100644 --- a/src/tools/miri/tests/pass/atomic.rs +++ b/src/tools/miri/tests/pass/atomic.rs @@ -1,7 +1,11 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows //@compile-flags: -Zmiri-strict-provenance + #![feature(strict_provenance, strict_provenance_atomic_ptr)] +// FIXME(obeis): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] + use std::sync::atomic::{ compiler_fence, fence, AtomicBool, AtomicIsize, AtomicPtr, AtomicU64, Ordering::*, }; diff --git a/src/tools/miri/tests/pass/static_memory_modification.rs b/src/tools/miri/tests/pass/static_memory_modification.rs index 84a524b1ed163..502575dbc9b5d 100644 --- a/src/tools/miri/tests/pass/static_memory_modification.rs +++ b/src/tools/miri/tests/pass/static_memory_modification.rs @@ -1,3 +1,6 @@ +// FIXME(obeis): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] + use std::sync::atomic::{AtomicUsize, Ordering}; static mut X: usize = 5; diff --git a/src/tools/miri/tests/pass/static_mut.rs b/src/tools/miri/tests/pass/static_mut.rs index 1b416cc4e9b08..76590e9ac8146 100644 --- a/src/tools/miri/tests/pass/static_mut.rs +++ b/src/tools/miri/tests/pass/static_mut.rs @@ -1,3 +1,6 @@ +// FIXME(obeis): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] + use std::ptr::addr_of; static mut FOO: i32 = 42; diff --git a/src/tools/miri/tests/pass/tls/tls_static.rs b/src/tools/miri/tests/pass/tls/tls_static.rs index 8d0e5089d404a..c219a32eedd21 100644 --- a/src/tools/miri/tests/pass/tls/tls_static.rs +++ b/src/tools/miri/tests/pass/tls/tls_static.rs @@ -7,6 +7,8 @@ //! dereferencing the pointer on `t2` resolves to `t1`'s thread-local. In this //! test, we also check that thread-locals act as per-thread statics. +// FIXME(obeis): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] #![feature(thread_local)] use std::ptr::addr_of_mut; diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 5731097770481..8ec98bbdd1879 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -1652,7 +1652,6 @@ ui/issues/issue-17068.rs ui/issues/issue-17121.rs ui/issues/issue-17216.rs ui/issues/issue-17252.rs -ui/issues/issue-17302.rs ui/issues/issue-17322.rs ui/issues/issue-17336.rs ui/issues/issue-17337.rs diff --git a/tests/ui/abi/statics/static-mut-foreign.rs b/tests/ui/abi/statics/static-mut-foreign.rs index 167b7a4e36e9e..edab7101e335e 100644 --- a/tests/ui/abi/statics/static-mut-foreign.rs +++ b/tests/ui/abi/statics/static-mut-foreign.rs @@ -19,15 +19,20 @@ fn static_bound_set(a: &'static mut c_int) { unsafe fn run() { assert_eq!(rust_dbg_static_mut, 3); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] rust_dbg_static_mut = 4; assert_eq!(rust_dbg_static_mut, 4); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] rust_dbg_static_mut_check_four(); rust_dbg_static_mut += 1; assert_eq!(rust_dbg_static_mut, 5); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] rust_dbg_static_mut *= 3; assert_eq!(rust_dbg_static_mut, 15); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] rust_dbg_static_mut = -3; assert_eq!(rust_dbg_static_mut, -3); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] static_bound(&rust_dbg_static_mut); //~^ WARN shared reference to mutable static is discouraged [static_mut_refs] static_bound_set(&mut rust_dbg_static_mut); diff --git a/tests/ui/abi/statics/static-mut-foreign.stderr b/tests/ui/abi/statics/static-mut-foreign.stderr index 0c4bd5382a1f0..a6dd0d8c4f258 100644 --- a/tests/ui/abi/statics/static-mut-foreign.stderr +++ b/tests/ui/abi/statics/static-mut-foreign.stderr @@ -1,31 +1,81 @@ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-foreign.rs:31:18 + --> $DIR/static-mut-foreign.rs:21:16 + | +LL | assert_eq!(rust_dbg_static_mut, 3); + | ^^^^^^^^^^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/static-mut-foreign.rs:24:16 + | +LL | assert_eq!(rust_dbg_static_mut, 4); + | ^^^^^^^^^^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/static-mut-foreign.rs:28:16 + | +LL | assert_eq!(rust_dbg_static_mut, 5); + | ^^^^^^^^^^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/static-mut-foreign.rs:31:16 + | +LL | assert_eq!(rust_dbg_static_mut, 15); + | ^^^^^^^^^^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/static-mut-foreign.rs:34:16 + | +LL | assert_eq!(rust_dbg_static_mut, -3); + | ^^^^^^^^^^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/static-mut-foreign.rs:36:18 | LL | static_bound(&rust_dbg_static_mut); | ^^^^^^^^^^^^^^^^^^^^ 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 + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior help: use `addr_of!` instead to create a raw pointer | LL | static_bound(addr_of!(rust_dbg_static_mut)); | ~~~~~~~~~ + warning: creating a mutable reference to mutable static is discouraged - --> $DIR/static-mut-foreign.rs:33:22 + --> $DIR/static-mut-foreign.rs:38:22 | LL | static_bound_set(&mut rust_dbg_static_mut); | ^^^^^^^^^^^^^^^^^^^^^^^^ 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 + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior help: use `addr_of_mut!` instead to create a raw pointer | LL | static_bound_set(addr_of_mut!(rust_dbg_static_mut)); | ~~~~~~~~~~~~~ + -warning: 2 warnings emitted +warning: 7 warnings emitted diff --git a/tests/ui/array-slice-vec/slice-panic-1.rs b/tests/ui/array-slice-vec/slice-panic-1.rs index 4436b63385641..cef645799c190 100644 --- a/tests/ui/array-slice-vec/slice-panic-1.rs +++ b/tests/ui/array-slice-vec/slice-panic-1.rs @@ -5,15 +5,17 @@ // Test that if a slicing expr[..] fails, the correct cleanups happen. - use std::thread; +use std::sync::atomic::{AtomicUsize, Ordering}; struct Foo; -static mut DTOR_COUNT: isize = 0; +static DTOR_COUNT: AtomicUsize = AtomicUsize::new(0); impl Drop for Foo { - fn drop(&mut self) { unsafe { DTOR_COUNT += 1; } } + fn drop(&mut self) { + DTOR_COUNT.fetch_add(1, Ordering::SeqCst); + } } fn foo() { @@ -22,6 +24,6 @@ fn foo() { } fn main() { - let _ = thread::spawn(move|| foo()).join(); - unsafe { assert_eq!(DTOR_COUNT, 2); } + let _ = thread::spawn(move || foo()).join(); + assert_eq!(DTOR_COUNT.load(Ordering::SeqCst), 2); } diff --git a/tests/ui/array-slice-vec/slice-panic-2.rs b/tests/ui/array-slice-vec/slice-panic-2.rs index 4bd139884244e..f5fbf2cfcb39f 100644 --- a/tests/ui/array-slice-vec/slice-panic-2.rs +++ b/tests/ui/array-slice-vec/slice-panic-2.rs @@ -7,13 +7,16 @@ use std::thread; +use std::sync::atomic::{AtomicUsize, Ordering}; struct Foo; -static mut DTOR_COUNT: isize = 0; +static DTOR_COUNT: AtomicUsize = AtomicUsize::new(0); impl Drop for Foo { - fn drop(&mut self) { unsafe { DTOR_COUNT += 1; } } + fn drop(&mut self) { + DTOR_COUNT.fetch_add(1, Ordering::SeqCst); + } } fn bar() -> usize { @@ -27,5 +30,5 @@ fn foo() { fn main() { let _ = thread::spawn(move|| foo()).join(); - unsafe { assert_eq!(DTOR_COUNT, 2); } + assert_eq!(DTOR_COUNT.load(Ordering::SeqCst), 2); } diff --git a/tests/ui/array-slice-vec/slice.rs b/tests/ui/array-slice-vec/slice.rs index 2adcd96f5984a..f02f36c942108 100644 --- a/tests/ui/array-slice-vec/slice.rs +++ b/tests/ui/array-slice-vec/slice.rs @@ -5,61 +5,62 @@ extern crate core; use core::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull}; +use std::sync::atomic::{AtomicUsize, Ordering}; -static mut COUNT: usize = 0; +static COUNT: AtomicUsize = AtomicUsize::new(0); struct Foo; impl Index> for Foo { type Output = Foo; fn index(&self, index: Range) -> &Foo { - unsafe { COUNT += 1; } + COUNT.fetch_add(1, Ordering::SeqCst); self } } impl Index> for Foo { type Output = Foo; fn index(&self, index: RangeTo) -> &Foo { - unsafe { COUNT += 1; } + COUNT.fetch_add(1, Ordering::SeqCst); self } } impl Index> for Foo { type Output = Foo; fn index(&self, index: RangeFrom) -> &Foo { - unsafe { COUNT += 1; } + COUNT.fetch_add(1, Ordering::SeqCst); self } } impl Index for Foo { type Output = Foo; fn index(&self, _index: RangeFull) -> &Foo { - unsafe { COUNT += 1; } + COUNT.fetch_add(1, Ordering::SeqCst); self } } impl IndexMut> for Foo { fn index_mut(&mut self, index: Range) -> &mut Foo { - unsafe { COUNT += 1; } + COUNT.fetch_add(1, Ordering::SeqCst); self } } impl IndexMut> for Foo { fn index_mut(&mut self, index: RangeTo) -> &mut Foo { - unsafe { COUNT += 1; } + COUNT.fetch_add(1, Ordering::SeqCst); self } } impl IndexMut> for Foo { fn index_mut(&mut self, index: RangeFrom) -> &mut Foo { - unsafe { COUNT += 1; } + COUNT.fetch_add(1, Ordering::SeqCst); self } } impl IndexMut for Foo { fn index_mut(&mut self, _index: RangeFull) -> &mut Foo { - unsafe { COUNT += 1; } + COUNT.fetch_add(1, Ordering::SeqCst); self } } @@ -75,7 +76,5 @@ fn main() { let _ = &mut x[Foo..]; let _ = &mut x[..Foo]; let _ = &mut x[Foo..Foo]; - unsafe { - assert_eq!(COUNT, 8); - } + assert_eq!(COUNT.load(Ordering::SeqCst), 8); } diff --git a/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs b/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs index 51e85931dbf20..a760570cfd1aa 100644 --- a/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs +++ b/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs @@ -9,6 +9,7 @@ fn is_send_sync(_: T) {} async fn fun() { let u = unsafe { A[async { 1 }.await] }; + //~^ WARN creating a reference to mutable static is discouraged [static_mut_refs] unsafe { match A { i if async { true }.await => (), @@ -21,6 +22,7 @@ async fn fun() { fn main() { let index_block = async { let u = unsafe { A[async { 1 }.await] }; + //~^ WARN creating a reference to mutable static is discouraged [static_mut_refs] }; let match_block = async { unsafe { diff --git a/tests/ui/async-await/issues/issue-67611-static-mut-refs.stderr b/tests/ui/async-await/issues/issue-67611-static-mut-refs.stderr new file mode 100644 index 0000000000000..33c3c87f447ad --- /dev/null +++ b/tests/ui/async-await/issues/issue-67611-static-mut-refs.stderr @@ -0,0 +1,25 @@ +warning: creating a reference to mutable static is discouraged + --> $DIR/issue-67611-static-mut-refs.rs:11:22 + | +LL | let u = unsafe { A[async { 1 }.await] }; + | ^^^^^^^^^^^^^^^^^^^^ reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default + +warning: creating a reference to mutable static is discouraged + --> $DIR/issue-67611-static-mut-refs.rs:24:26 + | +LL | let u = unsafe { A[async { 1 }.await] }; + | ^^^^^^^^^^^^^^^^^^^^ reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + +warning: 2 warnings emitted + diff --git a/tests/ui/binding/order-drop-with-match.rs b/tests/ui/binding/order-drop-with-match.rs index c12c5e4c62779..07cca5c5f3edd 100644 --- a/tests/ui/binding/order-drop-with-match.rs +++ b/tests/ui/binding/order-drop-with-match.rs @@ -14,6 +14,7 @@ impl Drop for A { fn drop(&mut self) { unsafe { ORDER[INDEX] = 1; + //~^ WARN creating a reference to mutable static is discouraged [static_mut_refs] INDEX = INDEX + 1; } } @@ -24,6 +25,7 @@ impl Drop for B { fn drop(&mut self) { unsafe { ORDER[INDEX] = 2; + //~^ WARN creating a reference to mutable static is discouraged [static_mut_refs] INDEX = INDEX + 1; } } @@ -34,6 +36,7 @@ impl Drop for C { fn drop(&mut self) { unsafe { ORDER[INDEX] = 3; + //~^ WARN creating a reference to mutable static is discouraged [static_mut_refs] INDEX = INDEX + 1; } } @@ -53,5 +56,6 @@ fn main() { unsafe { let expected: &[_] = &[1, 2, 3]; assert_eq!(expected, ORDER); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] } } diff --git a/tests/ui/binding/order-drop-with-match.stderr b/tests/ui/binding/order-drop-with-match.stderr new file mode 100644 index 0000000000000..43d68bbabfe67 --- /dev/null +++ b/tests/ui/binding/order-drop-with-match.stderr @@ -0,0 +1,46 @@ +warning: creating a reference to mutable static is discouraged + --> $DIR/order-drop-with-match.rs:16:13 + | +LL | ORDER[INDEX] = 1; + | ^^^^^^^^^^^^ reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default + +warning: creating a reference to mutable static is discouraged + --> $DIR/order-drop-with-match.rs:27:13 + | +LL | ORDER[INDEX] = 2; + | ^^^^^^^^^^^^ reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + +warning: creating a reference to mutable static is discouraged + --> $DIR/order-drop-with-match.rs:38:13 + | +LL | ORDER[INDEX] = 3; + | ^^^^^^^^^^^^ reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/order-drop-with-match.rs:58:30 + | +LL | assert_eq!(expected, ORDER); + | ^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +warning: 4 warnings emitted + diff --git a/tests/ui/borrowck/borrowck-access-permissions.stderr b/tests/ui/borrowck/borrowck-access-permissions.stderr index 36e259fa6e8ee..5b61e0f637699 100644 --- a/tests/ui/borrowck/borrowck-access-permissions.stderr +++ b/tests/ui/borrowck/borrowck-access-permissions.stderr @@ -6,7 +6,7 @@ LL | let _y2 = &mut static_x_mut; | = 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 + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of_mut!` instead to create a raw pointer | diff --git a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr index a727c9414c556..710e3d32dd254 100644 --- a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr +++ b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr @@ -6,7 +6,7 @@ LL | let sfoo: *mut Foo = &mut SFOO; | = 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 + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of_mut!` instead to create a raw pointer | diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr index 769b34831c120..44b076d37d758 100644 --- a/tests/ui/borrowck/issue-20801.stderr +++ b/tests/ui/borrowck/issue-20801.stderr @@ -6,7 +6,7 @@ LL | unsafe { &mut GLOBAL_MUT_T } | = 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 + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of_mut!` instead to create a raw pointer | 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 72fd0d8ce161e..a53078dce0798 100644 --- a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr +++ b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr @@ -6,7 +6,7 @@ LL | c1(&mut Y); | = 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 + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of_mut!` instead to create a raw pointer | @@ -21,7 +21,7 @@ LL | c1(&mut Z); | = 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 + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior help: use `addr_of_mut!` instead to create a raw pointer | LL | c1(addr_of_mut!(Z)); @@ -35,7 +35,7 @@ LL | borrowck_closures_unique::e(&mut X); | = 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 + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's 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.stderr b/tests/ui/consts/const_let_assign2.stderr index 87b94a7be67e2..873e9ec43c132 100644 --- a/tests/ui/consts/const_let_assign2.stderr +++ b/tests/ui/consts/const_let_assign2.stderr @@ -6,7 +6,7 @@ LL | let ptr = unsafe { &mut BB }; | = 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 + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of_mut!` instead to create a raw pointer | diff --git a/tests/ui/consts/static-mut-refs.rs b/tests/ui/consts/static-mut-refs.rs index d4ebfbbf17a86..9d4e92ff96281 100644 --- a/tests/ui/consts/static-mut-refs.rs +++ b/tests/ui/consts/static-mut-refs.rs @@ -17,7 +17,9 @@ static mut INT_RAW: *mut isize = &mut 1isize as *mut _; pub fn main() { unsafe { TEST[0] += 1; + //~^ WARN creating a reference to mutable static is discouraged [static_mut_refs] assert_eq!(TEST[0], 2); + //~^ WARN creating a reference to mutable static is discouraged [static_mut_refs] *INT_RAW += 1; assert_eq!(*INT_RAW, 2); } diff --git a/tests/ui/consts/static-mut-refs.stderr b/tests/ui/consts/static-mut-refs.stderr new file mode 100644 index 0000000000000..f68530fd7d860 --- /dev/null +++ b/tests/ui/consts/static-mut-refs.stderr @@ -0,0 +1,25 @@ +warning: creating a reference to mutable static is discouraged + --> $DIR/static-mut-refs.rs:19:9 + | +LL | TEST[0] += 1; + | ^^^^^^^ reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default + +warning: creating a reference to mutable static is discouraged + --> $DIR/static-mut-refs.rs:21:20 + | +LL | assert_eq!(TEST[0], 2); + | ^^^^^^^ reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + +warning: 2 warnings emitted + diff --git a/tests/ui/coroutine/static-mut-reference-across-yield.rs b/tests/ui/coroutine/static-mut-reference-across-yield.rs index 40d5fdf2d5736..5a62826bd7184 100644 --- a/tests/ui/coroutine/static-mut-reference-across-yield.rs +++ b/tests/ui/coroutine/static-mut-reference-across-yield.rs @@ -10,7 +10,7 @@ fn main() { unsafe { let gen_index = #[coroutine] static || { - let u = A[{ + let u = A[{ //~ WARN creating a reference to mutable static is discouraged [static_mut_refs] yield; 1 }]; diff --git a/tests/ui/coroutine/static-mut-reference-across-yield.stderr b/tests/ui/coroutine/static-mut-reference-across-yield.stderr new file mode 100644 index 0000000000000..72020acde5c90 --- /dev/null +++ b/tests/ui/coroutine/static-mut-reference-across-yield.stderr @@ -0,0 +1,18 @@ +warning: creating a reference to mutable static is discouraged + --> $DIR/static-mut-reference-across-yield.rs:13:21 + | +LL | let u = A[{ + | _____________________^ +LL | | yield; +LL | | 1 +LL | | }]; + | |______________^ reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/drop/drop-struct-as-object.rs b/tests/ui/drop/drop-struct-as-object.rs index 07c8950f1b2ba..0dcb9e1cebc5e 100644 --- a/tests/ui/drop/drop-struct-as-object.rs +++ b/tests/ui/drop/drop-struct-as-object.rs @@ -5,7 +5,9 @@ // Test that destructor on a struct runs successfully after the struct // is boxed and converted to an object. -static mut value: usize = 0; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static value: AtomicUsize = AtomicUsize::new(0); struct Cat { name : usize, @@ -21,7 +23,7 @@ impl Dummy for Cat { impl Drop for Cat { fn drop(&mut self) { - unsafe { value = self.name; } + value.store(self.name, Ordering::SeqCst); } } @@ -30,7 +32,5 @@ pub fn main() { let x = Box::new(Cat {name: 22}); let nyan: Box = x as Box; } - unsafe { - assert_eq!(value, 22); - } + assert_eq!(value.load(Ordering::SeqCst), 22); } diff --git a/tests/ui/drop/drop-struct-as-object.stderr b/tests/ui/drop/drop-struct-as-object.stderr index 10527c968ed70..b0d997f0a043c 100644 --- a/tests/ui/drop/drop-struct-as-object.stderr +++ b/tests/ui/drop/drop-struct-as-object.stderr @@ -1,5 +1,5 @@ warning: method `get` is never used - --> $DIR/drop-struct-as-object.rs:15:8 + --> $DIR/drop-struct-as-object.rs:17:8 | LL | trait Dummy { | ----- method in this trait 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 9126e6023913d..af405e144b348 100644 --- a/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr +++ b/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr @@ -6,7 +6,7 @@ LL | (mem::size_of_val(&trails) * 8) as u32 | = 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: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of!` instead to create a raw pointer | diff --git a/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr b/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr index 6da8741680274..d6a85780dc997 100644 --- a/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr +++ b/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr @@ -6,7 +6,7 @@ LL | (mem::size_of_val(&trails) * 8) as u32 | = 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: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of!` instead to create a raw pointer | diff --git a/tests/ui/drop/issue-48962.rs b/tests/ui/drop/issue-48962.rs index 428a6ca6cd21b..fe26ad695c74a 100644 --- a/tests/ui/drop/issue-48962.rs +++ b/tests/ui/drop/issue-48962.rs @@ -10,6 +10,7 @@ impl Drop for Dropee { fn drop(&mut self) { unsafe { ORDER[INDEX] = self.0; + //~^ WARN creating a reference to mutable static is discouraged [static_mut_refs] INDEX = INDEX + 1; } } @@ -18,6 +19,7 @@ impl Drop for Dropee { fn add_sentintel() { unsafe { ORDER[INDEX] = 2; + //~^ WARN creating a reference to mutable static is discouraged [static_mut_refs] INDEX = INDEX + 1; } } @@ -30,5 +32,6 @@ fn main() { {x}; // drop value unsafe { assert_eq!(ORDER, [1, 2, 3]); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] } } diff --git a/tests/ui/drop/issue-48962.stderr b/tests/ui/drop/issue-48962.stderr new file mode 100644 index 0000000000000..b610e5139adf1 --- /dev/null +++ b/tests/ui/drop/issue-48962.stderr @@ -0,0 +1,35 @@ +warning: creating a reference to mutable static is discouraged + --> $DIR/issue-48962.rs:12:13 + | +LL | ORDER[INDEX] = self.0; + | ^^^^^^^^^^^^ reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default + +warning: creating a reference to mutable static is discouraged + --> $DIR/issue-48962.rs:21:9 + | +LL | ORDER[INDEX] = 2; + | ^^^^^^^^^^^^ reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/issue-48962.rs:34:20 + | +LL | assert_eq!(ORDER, [1, 2, 3]); + | ^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +warning: 3 warnings emitted + diff --git a/tests/ui/drop/repeat-drop.rs b/tests/ui/drop/repeat-drop.rs index b83bee8c1bf82..29a46b07adc26 100644 --- a/tests/ui/drop/repeat-drop.rs +++ b/tests/ui/drop/repeat-drop.rs @@ -3,24 +3,26 @@ #![allow(dropping_references, dropping_copy_types)] -static mut CHECK: usize = 0; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static CHECK: AtomicUsize = AtomicUsize::new(0); struct DropChecker(usize); impl Drop for DropChecker { fn drop(&mut self) { - unsafe { - if CHECK != self.0 - 1 { - panic!("Found {}, should have found {}", CHECK, self.0 - 1); - } - CHECK = self.0; + if CHECK.load(Ordering::SeqCst) != self.0 - 1 { + panic!("Found {}, should have found {}", CHECK.load(Ordering::SeqCst), self.0 - 1); } + CHECK.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_c| { + Some(self.0) + }).unwrap(); } } macro_rules! check_drops { ($l:literal) => { - unsafe { assert_eq!(CHECK, $l) } + assert_eq!(CHECK.load(Ordering::SeqCst), $l) }; } @@ -33,7 +35,7 @@ impl Drop for DropPanic { } fn value_zero() { - unsafe { CHECK = 0 }; + CHECK.store(0, Ordering::SeqCst); let foo = DropChecker(1); let v: [DropChecker; 0] = [foo; 0]; check_drops!(1); @@ -42,7 +44,7 @@ fn value_zero() { } fn value_one() { - unsafe { CHECK = 0 }; + CHECK.store(0, Ordering::SeqCst); let foo = DropChecker(1); let v: [DropChecker; 1] = [foo; 1]; check_drops!(0); @@ -53,7 +55,7 @@ fn value_one() { const DROP_CHECKER: DropChecker = DropChecker(1); fn const_zero() { - unsafe { CHECK = 0 }; + CHECK.store(0, Ordering::SeqCst); let v: [DropChecker; 0] = [DROP_CHECKER; 0]; check_drops!(0); std::mem::drop(v); @@ -61,7 +63,7 @@ fn const_zero() { } fn const_one() { - unsafe { CHECK = 0 }; + CHECK.store(0, Ordering::SeqCst); let v: [DropChecker; 1] = [DROP_CHECKER; 1]; check_drops!(0); std::mem::drop(v); @@ -69,7 +71,7 @@ fn const_one() { } fn const_generic_zero() { - unsafe { CHECK = 0 }; + CHECK.store(0, Ordering::SeqCst); let v: [DropChecker; N] = [DROP_CHECKER; N]; check_drops!(0); std::mem::drop(v); @@ -77,7 +79,7 @@ fn const_generic_zero() { } fn const_generic_one() { - unsafe { CHECK = 0 }; + CHECK.store(0, Ordering::SeqCst); let v: [DropChecker; N] = [DROP_CHECKER; N]; check_drops!(0); std::mem::drop(v); @@ -87,7 +89,7 @@ fn const_generic_one() { // Make sure that things are allowed to promote as expected fn allow_promote() { - unsafe { CHECK = 0 }; + CHECK.store(0, Ordering::SeqCst); let foo = DropChecker(1); let v: &'static [DropChecker; 0] = &[foo; 0]; check_drops!(1); @@ -97,7 +99,7 @@ fn allow_promote() { // Verify that unwinding in the drop causes the right things to drop in the right order fn on_unwind() { - unsafe { CHECK = 0 }; + CHECK.store(0, Ordering::SeqCst); std::panic::catch_unwind(|| { let panic = DropPanic; let _local = DropChecker(2); diff --git a/tests/ui/issues/issue-17302.rs b/tests/ui/drop/static-issue-17302.rs similarity index 60% rename from tests/ui/issues/issue-17302.rs rename to tests/ui/drop/static-issue-17302.rs index c499cc5281f3a..bb93bfc996a00 100644 --- a/tests/ui/issues/issue-17302.rs +++ b/tests/ui/drop/static-issue-17302.rs @@ -9,6 +9,7 @@ impl Drop for A { fn drop(&mut self) { let A(i) = *self; unsafe { DROPPED[i] = true; } + //~^ WARN creating a reference to mutable static is discouraged [static_mut_refs] } } @@ -21,6 +22,8 @@ fn main() { } unsafe { assert!(DROPPED[0]); + //~^ WARN creating a reference to mutable static is discouraged [static_mut_refs] assert!(DROPPED[1]); + //~^ WARN creating a reference to mutable static is discouraged [static_mut_refs] } } diff --git a/tests/ui/drop/static-issue-17302.stderr b/tests/ui/drop/static-issue-17302.stderr new file mode 100644 index 0000000000000..49d24b3bd3495 --- /dev/null +++ b/tests/ui/drop/static-issue-17302.stderr @@ -0,0 +1,36 @@ +warning: creating a reference to mutable static is discouraged + --> $DIR/static-issue-17302.rs:11:18 + | +LL | unsafe { DROPPED[i] = true; } + | ^^^^^^^^^^ reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default + +warning: creating a reference to mutable static is discouraged + --> $DIR/static-issue-17302.rs:24:17 + | +LL | assert!(DROPPED[0]); + | ^^^^^^^^^^ reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + +warning: creating a reference to mutable static is discouraged + --> $DIR/static-issue-17302.rs:26:17 + | +LL | assert!(DROPPED[1]); + | ^^^^^^^^^^ reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + +warning: 3 warnings emitted + diff --git a/tests/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs b/tests/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs index fef9f24d462d8..74ec47be0ffc4 100644 --- a/tests/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs +++ b/tests/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs @@ -2,13 +2,15 @@ // This test verifies that temporaries created for `while`'s and `if` // conditions are dropped after the condition is evaluated. +use std::sync::atomic::{AtomicUsize, Ordering}; + struct Temporary; -static mut DROPPED: isize = 0; +static DROPPED: AtomicUsize = AtomicUsize::new(0); impl Drop for Temporary { fn drop(&mut self) { - unsafe { DROPPED += 1; } + DROPPED.fetch_add(1, Ordering::SeqCst); } } @@ -27,7 +29,7 @@ pub fn main() { // `drop` 6 times. while borrow().do_stuff() { i += 1; - unsafe { assert_eq!(DROPPED, i) } + assert_eq!(DROPPED.load(Ordering::SeqCst), i); if i > 5 { break; } @@ -36,6 +38,6 @@ pub fn main() { // This if condition should // call it 1 time if borrow().do_stuff() { - unsafe { assert_eq!(DROPPED, i + 1) } + assert_eq!(DROPPED.load(Ordering::SeqCst), i + 1); } } diff --git a/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.rs b/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.rs index 500633edf12de..16d467ccdcea0 100644 --- a/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.rs +++ b/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.rs @@ -12,6 +12,7 @@ mod foo { pub fn make_secrets(a: u8, b: String) -> S { let val = unsafe { let p = COUNT.get(); let val = *p; *p = val + 1; val }; + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] println!("creating {}, uid {}", b, val); S { a: a, b: b, secret_uid: val } } diff --git a/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr b/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr index 692d98bc53c82..72432b3ae6188 100644 --- a/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr +++ b/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr @@ -1,9 +1,20 @@ +warning: creating a shared reference to mutable static is discouraged + --> $DIR/functional-struct-update-respects-privacy.rs:14:36 + | +LL | let val = unsafe { let p = COUNT.get(); let val = *p; *p = val + 1; val }; + | ^^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default + error[E0451]: field `secret_uid` of struct `S` is private - --> $DIR/functional-struct-update-respects-privacy.rs:28:49 + --> $DIR/functional-struct-update-respects-privacy.rs:29:49 | LL | let s_2 = foo::S { b: format!("ess two"), ..s_1 }; // FRU ... | ^^^ field `secret_uid` is private -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/issues/issue-10734.rs b/tests/ui/issues/issue-10734.rs index 8daa401748c7c..54681aa1c692f 100644 --- a/tests/ui/issues/issue-10734.rs +++ b/tests/ui/issues/issue-10734.rs @@ -1,7 +1,9 @@ //@ run-pass #![allow(non_upper_case_globals)] -static mut drop_count: usize = 0; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static drop_count: AtomicUsize = AtomicUsize::new(0); struct Foo { dropped: bool @@ -13,7 +15,7 @@ impl Drop for Foo { assert!(!self.dropped); self.dropped = true; // And record the fact that we dropped for verification later - unsafe { drop_count += 1; } + drop_count.fetch_add(1, Ordering::SeqCst); } } @@ -23,7 +25,7 @@ pub fn main() { let _a = Foo{ dropped: false }; } // Check that we dropped already (as expected from a `{ expr }`). - unsafe { assert_eq!(drop_count, 1); } + assert_eq!(drop_count.load(Ordering::SeqCst), 1); // An `if false {} else { expr }` statement should compile the same as `{ expr }`. if false { @@ -32,5 +34,5 @@ pub fn main() { let _a = Foo{ dropped: false }; } // Check that we dropped already (as expected from a `{ expr }`). - unsafe { assert_eq!(drop_count, 2); } + assert_eq!(drop_count.load(Ordering::SeqCst), 2); } diff --git a/tests/ui/issues/issue-15858.rs b/tests/ui/issues/issue-15858.rs index 2d4aac01fbe8e..3ac400d2fcb97 100644 --- a/tests/ui/issues/issue-15858.rs +++ b/tests/ui/issues/issue-15858.rs @@ -1,5 +1,8 @@ //@ run-pass -static mut DROP_RAN: bool = false; + +use std::sync::atomic::{AtomicBool, Ordering}; + +static DROP_RAN: AtomicBool = AtomicBool::new(false); trait Bar { fn do_something(&mut self); //~ WARN method `do_something` is never used @@ -16,9 +19,7 @@ struct Foo(#[allow(dead_code)] B); impl Drop for Foo { fn drop(&mut self) { - unsafe { - DROP_RAN = true; - } + DROP_RAN.store(true, Ordering::SeqCst); } } @@ -27,7 +28,5 @@ fn main() { { let _x: Foo = Foo(BarImpl); } - unsafe { - assert_eq!(DROP_RAN, true); - } + assert_eq!(DROP_RAN.load(Ordering::SeqCst), true); } diff --git a/tests/ui/issues/issue-15858.stderr b/tests/ui/issues/issue-15858.stderr index f36bcc21bd7fb..96bede23098c1 100644 --- a/tests/ui/issues/issue-15858.stderr +++ b/tests/ui/issues/issue-15858.stderr @@ -1,5 +1,5 @@ warning: method `do_something` is never used - --> $DIR/issue-15858.rs:5:8 + --> $DIR/issue-15858.rs:8:8 | LL | trait Bar { | --- method in this trait diff --git a/tests/ui/issues/issue-16151.rs b/tests/ui/issues/issue-16151.rs index 20a3b5a04da23..7e09370b8a3de 100644 --- a/tests/ui/issues/issue-16151.rs +++ b/tests/ui/issues/issue-16151.rs @@ -25,5 +25,6 @@ fn main() { } unsafe { assert_eq!(DROP_COUNT, 3); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] } } diff --git a/tests/ui/issues/issue-16151.stderr b/tests/ui/issues/issue-16151.stderr new file mode 100644 index 0000000000000..b5f95a3a8c9c0 --- /dev/null +++ b/tests/ui/issues/issue-16151.stderr @@ -0,0 +1,13 @@ +warning: creating a shared reference to mutable static is discouraged + --> $DIR/issue-16151.rs:27:20 + | +LL | assert_eq!(DROP_COUNT, 3); + | ^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-39367.rs b/tests/ui/issues/issue-39367.rs index dd16d4da1bdd2..90c3fb4a5b760 100644 --- a/tests/ui/issues/issue-39367.rs +++ b/tests/ui/issues/issue-39367.rs @@ -18,7 +18,7 @@ fn arena() -> &'static ArenaSet> { use std::mem::transmute; static mut DATA: *const ArenaSet> = std::ptr::null_mut(); - static mut ONCE: Once = Once::new(); + static ONCE: Once = Once::new(); ONCE.call_once(|| { DATA = transmute ::>>, *const ArenaSet>> diff --git a/tests/ui/issues/issue-54410.stderr b/tests/ui/issues/issue-54410.stderr index 6cc5cd95e2f7d..77dff1e310ced 100644 --- a/tests/ui/issues/issue-54410.stderr +++ b/tests/ui/issues/issue-54410.stderr @@ -14,7 +14,7 @@ LL | println!("{:p}", unsafe { &symbol }); | = 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: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of!` instead to create a raw pointer | diff --git a/tests/ui/issues/issue-8860.rs b/tests/ui/issues/issue-8860.rs index 67e9a276ae487..8cd7d0d9c749e 100644 --- a/tests/ui/issues/issue-8860.rs +++ b/tests/ui/issues/issue-8860.rs @@ -1,17 +1,17 @@ //@ run-pass #![allow(dead_code)] -static mut DROP: isize = 0; -static mut DROP_S: isize = 0; -static mut DROP_T: isize = 0; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static DROP: AtomicUsize = AtomicUsize::new(0); +static DROP_S: AtomicUsize = AtomicUsize::new(0); +static DROP_T: AtomicUsize = AtomicUsize::new(0); struct S; impl Drop for S { fn drop(&mut self) { - unsafe { - DROP_S += 1; - DROP += 1; - } + DROP_S.fetch_add(1, Ordering::SeqCst); + DROP.fetch_add(1, Ordering::SeqCst); } } fn f(ref _s: S) {} @@ -19,10 +19,8 @@ fn f(ref _s: S) {} struct T { i: isize } impl Drop for T { fn drop(&mut self) { - unsafe { - DROP_T += 1; - DROP += 1; - } + DROP_T.fetch_add(1, Ordering::SeqCst); + DROP.fetch_add(1, Ordering::SeqCst); } } fn g(ref _t: T) {} @@ -30,20 +28,16 @@ fn g(ref _t: T) {} fn do_test() { let s = S; f(s); - unsafe { - assert_eq!(1, DROP); - assert_eq!(1, DROP_S); - } + assert_eq!(1, DROP.load(Ordering::SeqCst)); + assert_eq!(1, DROP_S.load(Ordering::SeqCst)); let t = T { i: 1 }; g(t); - unsafe { assert_eq!(1, DROP_T); } + assert_eq!(1, DROP_T.load(Ordering::SeqCst)); } fn main() { do_test(); - unsafe { - assert_eq!(2, DROP); - assert_eq!(1, DROP_S); - assert_eq!(1, DROP_T); - } + assert_eq!(2, DROP.load(Ordering::SeqCst)); + assert_eq!(1, DROP_S.load(Ordering::SeqCst)); + assert_eq!(1, DROP_T.load(Ordering::SeqCst)); } diff --git a/tests/ui/link-section.rs b/tests/ui/link-section.rs index 1a791b88ef957..7d8219a5d88dd 100644 --- a/tests/ui/link-section.rs +++ b/tests/ui/link-section.rs @@ -33,5 +33,6 @@ pub fn main() { unsafe { frobulator = 0x12345678; println!("{} {} {}", i_live_in_more_text(), magic, frobulator); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] } } diff --git a/tests/ui/link-section.stderr b/tests/ui/link-section.stderr new file mode 100644 index 0000000000000..7abc7c2378ddc --- /dev/null +++ b/tests/ui/link-section.stderr @@ -0,0 +1,13 @@ +warning: creating a shared reference to mutable static is discouraged + --> $DIR/link-section.rs:35:60 + | +LL | println!("{} {} {}", i_live_in_more_text(), magic, frobulator); + | ^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/linkage-attr/linkage-attr-mutable-static.rs b/tests/ui/linkage-attr/linkage-attr-mutable-static.rs index ed11947f59e74..8d9997c818290 100644 --- a/tests/ui/linkage-attr/linkage-attr-mutable-static.rs +++ b/tests/ui/linkage-attr/linkage-attr-mutable-static.rs @@ -20,5 +20,6 @@ fn main() { unsafe { assert_eq!(WEAK_DEF, 0); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] } } diff --git a/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr b/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr index ad9997690475b..3a2768f7bbeee 100644 --- a/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr +++ b/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr @@ -6,5 +6,16 @@ LL | #[linkage = "extern_weak"] | = note: marking the extern static mutable would allow changing which symbol the static references rather than make the target of the symbol mutable -error: aborting due to 1 previous error +warning: creating a shared reference to mutable static is discouraged + --> $DIR/linkage-attr-mutable-static.rs:22:20 + | +LL | assert_eq!(WEAK_DEF, 0); + | ^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/lto/lto-still-runs-thread-dtors.rs b/tests/ui/lto/lto-still-runs-thread-dtors.rs index 504923a93c279..b8a797852385b 100644 --- a/tests/ui/lto/lto-still-runs-thread-dtors.rs +++ b/tests/ui/lto/lto-still-runs-thread-dtors.rs @@ -4,8 +4,9 @@ //@ needs-threads use std::thread; +use std::sync::atomic::{AtomicUsize, Ordering}; -static mut HIT: usize = 0; +static HIT: AtomicUsize = AtomicUsize::new(0); thread_local!(static A: Foo = Foo); @@ -13,20 +14,16 @@ struct Foo; impl Drop for Foo { fn drop(&mut self) { - unsafe { - HIT += 1; - } + HIT.fetch_add(1, Ordering::SeqCst); } } fn main() { - unsafe { - assert_eq!(HIT, 0); - thread::spawn(|| { - assert_eq!(HIT, 0); - A.with(|_| ()); - assert_eq!(HIT, 0); - }).join().unwrap(); - assert_eq!(HIT, 1); - } + assert_eq!(HIT.load(Ordering::SeqCst), 0); + thread::spawn(|| { + assert_eq!(HIT.load(Ordering::SeqCst), 0); + A.with(|_| ()); + assert_eq!(HIT.load(Ordering::SeqCst), 0); + }).join().unwrap(); + assert_eq!(HIT.load(Ordering::SeqCst), 1); } diff --git a/tests/ui/methods/method-self-arg-trait.rs b/tests/ui/methods/method-self-arg-trait.rs index 63594380753ea..c1d2624528f53 100644 --- a/tests/ui/methods/method-self-arg-trait.rs +++ b/tests/ui/methods/method-self-arg-trait.rs @@ -1,7 +1,9 @@ //@ run-pass // Test method calls with self as an argument -static mut COUNT: u64 = 1; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static COUNT: AtomicUsize = AtomicUsize::new(1); #[derive(Copy, Clone)] struct Foo; @@ -12,33 +14,54 @@ trait Bar : Sized { fn foo3(self: Box); fn bar1(&self) { - unsafe { COUNT *= 7; } + COUNT.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut c| { + c *= 7; + Some(c) + }).unwrap(); } fn bar2(self) { - unsafe { COUNT *= 11; } + COUNT.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut c| { + c *= 11; + Some(c) + }).unwrap(); } fn bar3(self: Box) { - unsafe { COUNT *= 13; } + COUNT.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut c| { + c *= 13; + Some(c) + }).unwrap(); } } impl Bar for Foo { fn foo1(&self) { - unsafe { COUNT *= 2; } + COUNT.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut c| { + c *= 2; + Some(c) + }).unwrap(); } fn foo2(self) { - unsafe { COUNT *= 3; } + COUNT.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut c| { + c *= 3; + Some(c) + }).unwrap(); } fn foo3(self: Box) { - unsafe { COUNT *= 5; } + COUNT.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut c| { + c *= 5; + Some(c) + }).unwrap(); } } impl Foo { fn baz(self) { - unsafe { COUNT *= 17; } + COUNT.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut c| { + c *= 17; + Some(c) + }).unwrap(); // Test internal call. Bar::foo1(&self); Bar::foo2(self); @@ -63,5 +86,5 @@ fn main() { x.baz(); - unsafe { assert_eq!(COUNT, 2*2*3*3*5*5*7*7*11*11*13*13*17); } + assert_eq!(COUNT.load(Ordering::SeqCst), 2*2*3*3*5*5*7*7*11*11*13*13*17); } diff --git a/tests/ui/methods/method-self-arg.rs b/tests/ui/methods/method-self-arg.rs index d26b9663fd027..71ab69535cd85 100644 --- a/tests/ui/methods/method-self-arg.rs +++ b/tests/ui/methods/method-self-arg.rs @@ -43,4 +43,5 @@ fn main() { x.foo(&x); unsafe { assert_eq!(COUNT, 2*3*3*3*5*5*5*7*7*7); } + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] } diff --git a/tests/ui/methods/method-self-arg.stderr b/tests/ui/methods/method-self-arg.stderr new file mode 100644 index 0000000000000..9d8b54783b67d --- /dev/null +++ b/tests/ui/methods/method-self-arg.stderr @@ -0,0 +1,13 @@ +warning: creating a shared reference to mutable static is discouraged + --> $DIR/method-self-arg.rs:45:25 + | +LL | unsafe { assert_eq!(COUNT, 2*3*3*3*5*5*5*7*7*7); } + | ^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/mir/mir_early_return_scope.rs b/tests/ui/mir/mir_early_return_scope.rs index 6dc3f8bc39bbe..4899b2507c3e8 100644 --- a/tests/ui/mir/mir_early_return_scope.rs +++ b/tests/ui/mir/mir_early_return_scope.rs @@ -1,6 +1,9 @@ //@ run-pass #![allow(unused_variables)] -static mut DROP: bool = false; + +use std::sync::atomic::{AtomicBool, Ordering}; + +static DROP: AtomicBool = AtomicBool::new(false); struct ConnWrap(Conn); impl ::std::ops::Deref for ConnWrap { @@ -10,7 +13,9 @@ impl ::std::ops::Deref for ConnWrap { struct Conn; impl Drop for Conn { - fn drop(&mut self) { unsafe { DROP = true; } } + fn drop(&mut self) { + DROP.store(true, Ordering::SeqCst); + } } fn inner() { @@ -23,7 +28,5 @@ fn inner() { fn main() { inner(); - unsafe { - assert_eq!(DROP, true); - } + assert_eq!(DROP.load(Ordering::SeqCst), true); } 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 a6d4f9a2a5cb1..05346465b8fbd 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 @@ -6,7 +6,7 @@ LL | S1 { a: unsafe { &mut X1 } } | = 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 + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of_mut!` instead to create a raw pointer | diff --git a/tests/ui/nll/issue-69114-static-mut-ty.rs b/tests/ui/nll/issue-69114-static-mut-ty.rs index ce37da053e371..e020b4c2601c7 100644 --- a/tests/ui/nll/issue-69114-static-mut-ty.rs +++ b/tests/ui/nll/issue-69114-static-mut-ty.rs @@ -7,9 +7,13 @@ static mut BAR_ELIDED: &u8 = &FOO; fn main() { unsafe { println!("{} {}", BAR, BAR_ELIDED); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] + //~^^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] set_bar(); set_bar_elided(); println!("{} {}", BAR, BAR_ELIDED); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] + //~^^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] } } diff --git a/tests/ui/nll/issue-69114-static-mut-ty.stderr b/tests/ui/nll/issue-69114-static-mut-ty.stderr index 1b41230d7ba39..90be23df89d6e 100644 --- a/tests/ui/nll/issue-69114-static-mut-ty.stderr +++ b/tests/ui/nll/issue-69114-static-mut-ty.stderr @@ -1,5 +1,46 @@ +warning: creating a shared reference to mutable static is discouraged + --> $DIR/issue-69114-static-mut-ty.rs:9:27 + | +LL | println!("{} {}", BAR, BAR_ELIDED); + | ^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/issue-69114-static-mut-ty.rs:9:32 + | +LL | println!("{} {}", BAR, BAR_ELIDED); + | ^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/issue-69114-static-mut-ty.rs:14:27 + | +LL | println!("{} {}", BAR, BAR_ELIDED); + | ^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/issue-69114-static-mut-ty.rs:14:32 + | +LL | println!("{} {}", BAR, BAR_ELIDED); + | ^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + error[E0597]: `n` does not live long enough - --> $DIR/issue-69114-static-mut-ty.rs:19:15 + --> $DIR/issue-69114-static-mut-ty.rs:23:15 | LL | let n = 42; | - binding `n` declared here @@ -14,7 +55,7 @@ LL | } | - `n` dropped here while still borrowed error[E0597]: `n` does not live long enough - --> $DIR/issue-69114-static-mut-ty.rs:27:22 + --> $DIR/issue-69114-static-mut-ty.rs:31:22 | LL | let n = 42; | - binding `n` declared here @@ -28,6 +69,6 @@ LL | BAR_ELIDED = &n; LL | } | - `n` dropped here while still borrowed -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 4 warnings emitted For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/self/where-for-self.rs b/tests/ui/self/where-for-self.rs index 9b4e83256645d..dca72d3c4dc04 100644 --- a/tests/ui/self/where-for-self.rs +++ b/tests/ui/self/where-for-self.rs @@ -2,8 +2,9 @@ // Test that we can quantify lifetimes outside a constraint (i.e., including // the self type) in a where clause. +use std::sync::atomic::{AtomicUsize, Ordering}; -static mut COUNT: u32 = 1; +static COUNT: AtomicUsize = AtomicUsize::new(1); trait Bar<'a> { fn bar(&self); @@ -16,13 +17,19 @@ trait Baz<'a> impl<'a, 'b> Bar<'b> for &'a u32 { fn bar(&self) { - unsafe { COUNT *= 2; } + COUNT.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut c| { + c *= 2; + Some(c) + }).unwrap(); } } impl<'a, 'b> Baz<'b> for &'a u32 { fn baz(&self) { - unsafe { COUNT *= 3; } + COUNT.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut c| { + c *= 3; + Some(c) + }).unwrap(); } } @@ -45,7 +52,5 @@ fn main() { let x = 42; foo1(&x); foo2(&x); - unsafe { - assert_eq!(COUNT, 12); - } + assert_eq!(COUNT.load(Ordering::SeqCst), 12); } diff --git a/tests/ui/static/reference-to-mut-static-safe.e2021.stderr b/tests/ui/static/ref-to-mut-static-safe.e2021.stderr similarity index 75% rename from tests/ui/static/reference-to-mut-static-safe.e2021.stderr rename to tests/ui/static/ref-to-mut-static-safe.e2021.stderr index 9fdfc00dfcd91..3c996a5f1129f 100644 --- a/tests/ui/static/reference-to-mut-static-safe.e2021.stderr +++ b/tests/ui/static/ref-to-mut-static-safe.e2021.stderr @@ -1,12 +1,12 @@ warning: creating a shared reference to mutable static is discouraged - --> $DIR/reference-to-mut-static-safe.rs:9:14 + --> $DIR/ref-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: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of!` instead to create a raw pointer | @@ -14,7 +14,7 @@ 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 + --> $DIR/ref-to-mut-static-safe.rs:9:15 | LL | let _x = &X; | ^ use of mutable static diff --git a/tests/ui/static/reference-to-mut-static-safe.e2024.stderr b/tests/ui/static/ref-to-mut-static-safe.e2024.stderr similarity index 70% rename from tests/ui/static/reference-to-mut-static-safe.e2024.stderr rename to tests/ui/static/ref-to-mut-static-safe.e2024.stderr index b3e0c84d1d89d..794ef874df336 100644 --- a/tests/ui/static/reference-to-mut-static-safe.e2024.stderr +++ b/tests/ui/static/ref-to-mut-static-safe.e2024.stderr @@ -1,17 +1,17 @@ error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-to-mut-static-safe.rs:9:14 + --> $DIR/ref-to-mut-static-safe.rs:9:14 | LL | let _x = &X; | ^^ shared reference 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 + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior 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 block - --> $DIR/reference-to-mut-static-safe.rs:9:15 + --> $DIR/ref-to-mut-static-safe.rs:9:15 | LL | let _x = &X; | ^ use of mutable static diff --git a/tests/ui/static/reference-to-mut-static-safe.rs b/tests/ui/static/ref-to-mut-static-safe.rs similarity index 100% rename from tests/ui/static/reference-to-mut-static-safe.rs rename to tests/ui/static/ref-to-mut-static-safe.rs diff --git a/tests/ui/static/ref-to-mut-static.e2021.stderr b/tests/ui/static/ref-to-mut-static.e2021.stderr new file mode 100644 index 0000000000000..3af7e2e689864 --- /dev/null +++ b/tests/ui/static/ref-to-mut-static.e2021.stderr @@ -0,0 +1,170 @@ +error: creating a shared reference to mutable static is discouraged + --> $DIR/ref-to-mut-static.rs:36: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: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior +note: the lint level is defined here + --> $DIR/ref-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/ref-to-mut-static.rs:40: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: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's 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/ref-to-mut-static.rs:48: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: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +error: creating a shared reference to mutable static is discouraged + --> $DIR/ref-to-mut-static.rs:52: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: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's 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/ref-to-mut-static.rs:52: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: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's 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/ref-to-mut-static.rs:58: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: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | foo(addr_of!(X)); + | ~~~~~~~~~ + + +error: creating a reference to mutable static is discouraged + --> $DIR/ref-to-mut-static.rs:67:17 + | +LL | let _ = Z[0]; + | ^^^^ reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + +error: creating a shared reference to mutable static is discouraged + --> $DIR/ref-to-mut-static.rs:70:33 + | +LL | let _ = format!("{:?}", Z); + | ^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +error: creating a shared reference to mutable static is discouraged + --> $DIR/ref-to-mut-static.rs:74:18 + | +LL | let _v = &A.value; + | ^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let _v = addr_of!(A.value); + | ~~~~~~~~~ + + +error: creating a shared reference to mutable static is discouraged + --> $DIR/ref-to-mut-static.rs:78:18 + | +LL | let _s = &A.s.value; + | ^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let _s = addr_of!(A.s.value); + | ~~~~~~~~~ + + +error: creating a shared reference to mutable static is discouraged + --> $DIR/ref-to-mut-static.rs:82:22 + | +LL | let ref _v = A.value; + | ^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +error: creating a mutable reference to mutable static is discouraged + --> $DIR/ref-to-mut-static.rs:14:14 + | +LL | &mut ($x.0) + | ^^^^^^ mutable reference to mutable static +... +LL | let _x = bar!(FOO); + | --------- in this macro invocation + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: creating a shared reference to mutable static is discouraged + --> $DIR/ref-to-mut-static.rs:64:17 + | +LL | let _ = Z.len(); + | ^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +error: aborting due to 13 previous errors + diff --git a/tests/ui/static/ref-to-mut-static.e2024.stderr b/tests/ui/static/ref-to-mut-static.e2024.stderr new file mode 100644 index 0000000000000..f99cac5c71f76 --- /dev/null +++ b/tests/ui/static/ref-to-mut-static.e2024.stderr @@ -0,0 +1,140 @@ +error[E0796]: creating a shared reference to a mutable static + --> $DIR/ref-to-mut-static.rs:36:18 + | +LL | let _y = &X; + | ^^ shared reference to mutable static + | + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's 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/ref-to-mut-static.rs:40:18 + | +LL | let _y = &mut X; + | ^^^^^^ mutable reference to mutable static + | + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's 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/ref-to-mut-static.rs:48:22 + | +LL | let ref _a = X; + | ^ shared reference to mutable static + | + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +error[E0796]: creating a shared reference to a mutable static + --> $DIR/ref-to-mut-static.rs:52:25 + | +LL | let (_b, _c) = (&X, &Y); + | ^^ shared reference to mutable static + | + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's 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/ref-to-mut-static.rs:52:29 + | +LL | let (_b, _c) = (&X, &Y); + | ^^ shared reference to mutable static + | + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's 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/ref-to-mut-static.rs:58:13 + | +LL | foo(&X); + | ^^ shared reference to mutable static + | + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | foo(addr_of!(X)); + | ~~~~~~~~~ + + +error[E0796]: creating a reference to a mutable static + --> $DIR/ref-to-mut-static.rs:67:17 + | +LL | let _ = Z[0]; + | ^^^^ reference to mutable static + | + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + +error[E0796]: creating a shared reference to a mutable static + --> $DIR/ref-to-mut-static.rs:70:33 + | +LL | let _ = format!("{:?}", Z); + | ^ shared reference to mutable static + | + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +error[E0796]: creating a shared reference to a mutable static + --> $DIR/ref-to-mut-static.rs:74:18 + | +LL | let _v = &A.value; + | ^^^^^^^^ shared reference to mutable static + | + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let _v = addr_of!(A.value); + | ~~~~~~~~~ + + +error[E0796]: creating a shared reference to a mutable static + --> $DIR/ref-to-mut-static.rs:78:18 + | +LL | let _s = &A.s.value; + | ^^^^^^^^^^ shared reference to mutable static + | + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior +help: use `addr_of!` instead to create a raw pointer + | +LL | let _s = addr_of!(A.s.value); + | ~~~~~~~~~ + + +error[E0796]: creating a shared reference to a mutable static + --> $DIR/ref-to-mut-static.rs:82:22 + | +LL | let ref _v = A.value; + | ^^^^^^^ shared reference to mutable static + | + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +error[E0796]: creating a mutable reference to a mutable static + --> $DIR/ref-to-mut-static.rs:14:14 + | +LL | &mut ($x.0) + | ^^^^^^ mutable reference to mutable static +... +LL | let _x = bar!(FOO); + | --------- in this macro invocation + | + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior + = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0796]: creating a shared reference to a mutable static + --> $DIR/ref-to-mut-static.rs:64:17 + | +LL | let _ = Z.len(); + | ^^^^^^^ shared reference to mutable static + | + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0796`. diff --git a/tests/ui/static/ref-to-mut-static.rs b/tests/ui/static/ref-to-mut-static.rs new file mode 100644 index 0000000000000..8f5770b5c9f36 --- /dev/null +++ b/tests/ui/static/ref-to-mut-static.rs @@ -0,0 +1,90 @@ +//@ 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}; + +static mut FOO: (u32, u32) = (1, 2); + +macro_rules! bar { + ($x:expr) => { + &mut ($x.0) + //[e2024]~^ ERROR creating a mutable reference to a mutable static [E0796] + //[e2021]~^^ ERROR creating a mutable reference to mutable static is discouraged [static_mut_refs] + }; +} + +fn main() { + static mut X: i32 = 1; + + static mut Y: i32 = 1; + + struct TheStruct { + pub value: i32, + } + struct MyStruct { + pub value: i32, + pub s: TheStruct, + } + + static mut A: MyStruct = MyStruct { value: 1, s: TheStruct { value: 2 } }; + + 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(); + //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796] + //[e2021]~^^ ERROR creating a shared reference to mutable static is discouraged [static_mut_refs] + let _ = Z[0]; + //[e2024]~^ ERROR creating a reference to a mutable static [E0796] + //[e2021]~^^ ERROR creating a reference to mutable static is discouraged [static_mut_refs] + let _ = format!("{:?}", Z); + //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796] + //[e2021]~^^ ERROR creating a shared reference to mutable static is discouraged [static_mut_refs] + + let _v = &A.value; + //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796] + //[e2021]~^^ ERROR creating a shared reference to mutable static is discouraged [static_mut_refs] + + let _s = &A.s.value; + //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796] + //[e2021]~^^ ERROR creating a shared reference to mutable static is discouraged [static_mut_refs] + + let ref _v = A.value; + //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796] + //[e2021]~^^ ERROR creating a shared reference to mutable static is discouraged [static_mut_refs] + + let _x = bar!(FOO); + } +} + +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 index ca9cfbf7ac787..e27d4af399dd2 100644 --- a/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr +++ b/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr @@ -4,7 +4,7 @@ error[E0796]: creating a shared reference to a mutable static LL | let _y = &X; | ^^ shared reference 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 + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior help: use `addr_of!` instead to create a raw pointer | LL | let _y = addr_of!(X); @@ -16,11 +16,7 @@ error[E0796]: creating a shared reference to a mutable static LL | let ref _a = X; | ^ shared reference 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); - | +++++++++ + + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior error[E0796]: creating a mutable reference to a mutable static --> $DIR/reference-to-mut-static-unsafe-fn.rs:16:26 @@ -28,11 +24,7 @@ error[E0796]: creating a mutable reference to a mutable static LL | let ref mut _a = X; | ^ mutable reference 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); - | +++++++++++++ + + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior error[E0796]: creating a shared reference to a mutable static --> $DIR/reference-to-mut-static-unsafe-fn.rs:19:25 @@ -40,7 +32,7 @@ error[E0796]: creating a shared reference to a mutable static LL | let (_b, _c) = (&X, &mut Y); | ^^ shared reference 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 + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior help: use `addr_of!` instead to create a raw pointer | LL | let (_b, _c) = (addr_of!(X), &mut Y); @@ -52,7 +44,7 @@ error[E0796]: creating a mutable reference to a mutable static LL | let (_b, _c) = (&X, &mut Y); | ^^^^^^ mutable reference 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 + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior help: use `addr_of_mut!` instead to create a raw pointer | LL | let (_b, _c) = (&X, addr_of_mut!(Y)); @@ -64,7 +56,7 @@ error[E0796]: creating a shared reference to a mutable static LL | foo(&X); | ^^ shared reference 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 + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior help: use `addr_of!` instead to create a raw pointer | LL | foo(addr_of!(X)); diff --git a/tests/ui/static/reference-to-mut-static.e2021.stderr b/tests/ui/static/reference-to-mut-static.e2021.stderr deleted file mode 100644 index 667d7602f34a5..0000000000000 --- a/tests/ui/static/reference-to-mut-static.e2021.stderr +++ /dev/null @@ -1,91 +0,0 @@ -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 deleted file mode 100644 index e77f43554666c..0000000000000 --- a/tests/ui/static/reference-to-mut-static.e2024.stderr +++ /dev/null @@ -1,75 +0,0 @@ -error[E0796]: creating a shared reference to a mutable static - --> $DIR/reference-to-mut-static.rs:16:18 - | -LL | let _y = &X; - | ^^ shared reference 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; - | ^^^^^^ mutable reference 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; - | ^ shared reference 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); - | ^^ shared reference 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); - | ^^ shared reference 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); - | ^^ shared reference 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 deleted file mode 100644 index af2cab7dd8723..0000000000000 --- a/tests/ui/static/reference-to-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_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.stderr b/tests/ui/static/safe-extern-statics-mut.stderr index 7705a897e2717..60778a15649a4 100644 --- a/tests/ui/static/safe-extern-statics-mut.stderr +++ b/tests/ui/static/safe-extern-statics-mut.stderr @@ -6,7 +6,7 @@ LL | let rb = &B; | = 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: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of!` instead to create a raw pointer | @@ -21,7 +21,7 @@ LL | let xrb = &XB; | = 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: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's 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.stderr b/tests/ui/statics/issue-15261.stderr index 6035eef5b7140..c7834f5932c08 100644 --- a/tests/ui/statics/issue-15261.stderr +++ b/tests/ui/statics/issue-15261.stderr @@ -6,7 +6,7 @@ LL | static n: &'static usize = unsafe { &n_mut }; | = 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: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior = note: `#[warn(static_mut_refs)]` on by default help: use `addr_of!` instead to create a raw pointer | diff --git a/tests/ui/statics/static-mut-xc.rs b/tests/ui/statics/static-mut-xc.rs index a772d4151f7cd..c23cc822ce741 100644 --- a/tests/ui/statics/static-mut-xc.rs +++ b/tests/ui/statics/static-mut-xc.rs @@ -17,14 +17,19 @@ fn static_bound_set(a: &'static mut isize) { unsafe fn run() { assert_eq!(static_mut_xc::a, 3); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] static_mut_xc::a = 4; assert_eq!(static_mut_xc::a, 4); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] static_mut_xc::a += 1; assert_eq!(static_mut_xc::a, 5); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] static_mut_xc::a *= 3; assert_eq!(static_mut_xc::a, 15); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] static_mut_xc::a = -3; assert_eq!(static_mut_xc::a, -3); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] static_bound(&static_mut_xc::a); //~^ WARN shared reference to mutable static is discouraged [static_mut_refs] static_bound_set(&mut static_mut_xc::a); diff --git a/tests/ui/statics/static-mut-xc.stderr b/tests/ui/statics/static-mut-xc.stderr index 9751f754332c9..94120884296b7 100644 --- a/tests/ui/statics/static-mut-xc.stderr +++ b/tests/ui/statics/static-mut-xc.stderr @@ -1,31 +1,81 @@ warning: creating a shared reference to mutable static is discouraged - --> $DIR/static-mut-xc.rs:28:18 + --> $DIR/static-mut-xc.rs:19:16 + | +LL | assert_eq!(static_mut_xc::a, 3); + | ^^^^^^^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/static-mut-xc.rs:22:16 + | +LL | assert_eq!(static_mut_xc::a, 4); + | ^^^^^^^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/static-mut-xc.rs:25:16 + | +LL | assert_eq!(static_mut_xc::a, 5); + | ^^^^^^^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/static-mut-xc.rs:28:16 + | +LL | assert_eq!(static_mut_xc::a, 15); + | ^^^^^^^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/static-mut-xc.rs:31:16 + | +LL | assert_eq!(static_mut_xc::a, -3); + | ^^^^^^^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +warning: creating a shared reference to mutable static is discouraged + --> $DIR/static-mut-xc.rs:33:18 | LL | static_bound(&static_mut_xc::a); | ^^^^^^^^^^^^^^^^^ 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 + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior help: use `addr_of!` instead to create a raw pointer | LL | static_bound(addr_of!(static_mut_xc::a)); | ~~~~~~~~~ + warning: creating a mutable reference to mutable static is discouraged - --> $DIR/static-mut-xc.rs:30:22 + --> $DIR/static-mut-xc.rs:35:22 | LL | static_bound_set(&mut static_mut_xc::a); | ^^^^^^^^^^^^^^^^^^^^^ 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 + = note: mutable references to mutable statics are dangerous since if there's any other pointer used or reference created for that static while the reference lives, that's undefined behavior help: use `addr_of_mut!` instead to create a raw pointer | LL | static_bound_set(addr_of_mut!(static_mut_xc::a)); | ~~~~~~~~~~~~~ + -warning: 2 warnings emitted +warning: 7 warnings emitted diff --git a/tests/ui/statics/static-recursive.rs b/tests/ui/statics/static-recursive.rs index 29b80818b7d46..da23b54d1fca0 100644 --- a/tests/ui/statics/static-recursive.rs +++ b/tests/ui/statics/static-recursive.rs @@ -17,6 +17,7 @@ static L3: StaticDoubleLinked = StaticDoubleLinked { prev: &L2, next: &L1, data: pub fn main() { unsafe { assert_eq!(S, *(S as *const *const u8)); + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] } let mut test_vec = Vec::new(); diff --git a/tests/ui/statics/static-recursive.stderr b/tests/ui/statics/static-recursive.stderr index a7a1a1610afbb..105ab05c6c654 100644 --- a/tests/ui/statics/static-recursive.stderr +++ b/tests/ui/statics/static-recursive.stderr @@ -6,12 +6,22 @@ LL | static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 }; | = 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: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's 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 }; | ~~~~~~~~~ + -warning: 1 warning emitted +warning: creating a shared reference to mutable static is discouraged + --> $DIR/static-recursive.rs:19:20 + | +LL | assert_eq!(S, *(S as *const *const u8)); + | ^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + +warning: 2 warnings emitted diff --git a/tests/ui/thread-local/thread-local-issue-37508.rs b/tests/ui/thread-local/thread-local-issue-37508.rs index db430a3229c7b..6fa88f60d5092 100644 --- a/tests/ui/thread-local/thread-local-issue-37508.rs +++ b/tests/ui/thread-local/thread-local-issue-37508.rs @@ -28,6 +28,7 @@ pub unsafe fn set() -> Option<&'static BB> { return None; } Some(&KEY.inner) + //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs] } pub struct Key { diff --git a/tests/ui/thread-local/thread-local-issue-37508.stderr b/tests/ui/thread-local/thread-local-issue-37508.stderr new file mode 100644 index 0000000000000..ee8d232fab6d2 --- /dev/null +++ b/tests/ui/thread-local/thread-local-issue-37508.stderr @@ -0,0 +1,17 @@ +warning: creating a shared reference to mutable static is discouraged + --> $DIR/thread-local-issue-37508.rs:30:10 + | +LL | Some(&KEY.inner) + | ^^^^^^^^^^ shared reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: shared references to mutable statics are dangerous since if there's any kind of mutation of, or mutable reference created for, that static while the reference lives, that's undefined behavior + = note: `#[warn(static_mut_refs)]` on by default +help: use `addr_of!` instead to create a raw pointer + | +LL | Some(addr_of!(KEY.inner)) + | ~~~~~~~~~ + + +warning: 1 warning emitted + diff --git a/tests/ui/traits/impl.rs b/tests/ui/traits/impl.rs index 348096f37f7be..601114e607373 100644 --- a/tests/ui/traits/impl.rs +++ b/tests/ui/traits/impl.rs @@ -3,10 +3,12 @@ //@ aux-build:traitimpl.rs +use std::sync::atomic::{AtomicUsize, Ordering}; + extern crate traitimpl; use traitimpl::Bar; -static mut COUNT: usize = 1; +static COUNT: AtomicUsize = AtomicUsize::new(1); trait T { fn t(&self) {} //~ WARN method `t` is never used @@ -14,10 +16,16 @@ trait T { impl<'a> dyn T+'a { fn foo(&self) { - unsafe { COUNT *= 2; } + COUNT.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut c| { + c *= 2; + Some(c) + }).unwrap(); } fn bar() { - unsafe { COUNT *= 3; } + COUNT.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |mut c| { + c *= 3; + Some(c) + }).unwrap(); } } @@ -33,7 +41,7 @@ fn main() { ::foo(x); ::bar(); - unsafe { assert_eq!(COUNT, 12); } + assert_eq!(COUNT.load(Ordering::SeqCst), 12); // Cross-crait case let x: &dyn Bar = &Foo; diff --git a/tests/ui/traits/impl.stderr b/tests/ui/traits/impl.stderr index 98b6fb03d836f..0697f62da0dc7 100644 --- a/tests/ui/traits/impl.stderr +++ b/tests/ui/traits/impl.stderr @@ -1,5 +1,5 @@ warning: method `t` is never used - --> $DIR/impl.rs:12:8 + --> $DIR/impl.rs:14:8 | LL | trait T { | - method in this trait diff --git a/tests/ui/union/union-drop-assign.rs b/tests/ui/union/union-drop-assign.rs index e9165fddc51e4..1d1809c98c356 100644 --- a/tests/ui/union/union-drop-assign.rs +++ b/tests/ui/union/union-drop-assign.rs @@ -4,6 +4,7 @@ // Drop works for union itself. use std::mem::ManuallyDrop; +use std::sync::atomic::{AtomicUsize, Ordering}; struct S; @@ -13,25 +14,26 @@ union U { impl Drop for S { fn drop(&mut self) { - unsafe { CHECK += 10; } + CHECK.fetch_add(10, Ordering::SeqCst); } } impl Drop for U { fn drop(&mut self) { - unsafe { CHECK += 1; } + CHECK.fetch_add(1, Ordering::SeqCst); } } -static mut CHECK: u8 = 0; +static CHECK: AtomicUsize = AtomicUsize::new(0); fn main() { + let mut u = U { a: ManuallyDrop::new(S) }; + assert_eq!(CHECK.load(Ordering::SeqCst), 0); + u = U { a: ManuallyDrop::new(S) }; + // union itself is assigned, union is dropped, field is not dropped + assert_eq!(CHECK.load(Ordering::SeqCst), 1); unsafe { - let mut u = U { a: ManuallyDrop::new(S) }; - assert_eq!(CHECK, 0); - u = U { a: ManuallyDrop::new(S) }; - assert_eq!(CHECK, 1); // union itself is assigned, union is dropped, field is not dropped *u.a = S; - assert_eq!(CHECK, 11); // union field is assigned, field is dropped } + assert_eq!(CHECK.load(Ordering::SeqCst), 11); // union field is assigned, field is dropped } diff --git a/tests/ui/union/union-drop.rs b/tests/ui/union/union-drop.rs index e467eda293504..28cf4571cd616 100644 --- a/tests/ui/union/union-drop.rs +++ b/tests/ui/union/union-drop.rs @@ -3,6 +3,8 @@ #![allow(dead_code)] #![allow(unused_variables)] +use std::sync::atomic::{AtomicUsize, Ordering}; + // Drop works for union itself. #[derive(Copy, Clone)] @@ -22,37 +24,35 @@ union Y { impl Drop for U { fn drop(&mut self) { - unsafe { CHECK += 1; } + CHECK.fetch_add(1, Ordering::SeqCst); } } impl Drop for W { fn drop(&mut self) { - unsafe { CHECK += 1; } + CHECK.fetch_add(1, Ordering::SeqCst); } } -static mut CHECK: u8 = 0; +static CHECK: AtomicUsize = AtomicUsize::new(0); fn main() { - unsafe { - assert_eq!(CHECK, 0); - { - let u = U { a: 1 }; - } - assert_eq!(CHECK, 1); // 1, dtor of U is called - { - let w = W { a: S }; - } - assert_eq!(CHECK, 2); // 2, dtor of W is called - { - let y = Y { a: S }; - } - assert_eq!(CHECK, 2); // 2, Y has no dtor - { - let u2 = U { a: 1 }; - std::mem::forget(u2); - } - assert_eq!(CHECK, 2); // 2, dtor of U *not* called for u2 + assert_eq!(CHECK.load(Ordering::SeqCst), 0); + { + let u = U { a: 1 }; + } + assert_eq!(CHECK.load(Ordering::SeqCst), 1); // 1, dtor of U is called + { + let w = W { a: S }; + } + assert_eq!(CHECK.load(Ordering::SeqCst), 2); // 2, dtor of W is called + { + let y = Y { a: S }; + } + assert_eq!(CHECK.load(Ordering::SeqCst), 2); // 2, Y has no dtor + { + let u2 = U { a: 1 }; + std::mem::forget(u2); } + assert_eq!(CHECK.load(Ordering::SeqCst), 2); // 2, dtor of U *not* called for u2 }