diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index e8b4cb343794c..e021761a59231 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -541,6 +541,21 @@ impl NoArgsAttributeParser for RustcNoMirInlineParser { const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoMirInline; } +pub(crate) struct RustcNoWritableParser; + +impl NoArgsAttributeParser for RustcNoWritableParser { + const PATH: &[Symbol] = &[sym::rustc_no_writable]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Closure), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Trait { body: true })), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoWritable; +} + pub(crate) struct RustcLintQueryInstabilityParser; impl NoArgsAttributeParser for RustcLintQueryInstabilityParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 259a73de59853..4fef40481259e 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -309,6 +309,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index d74450e67cf1d..7fb68b795c96b 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1414,6 +1414,9 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_scalable_vector, Normal, template!(List: &["count"]), WarnFollowing, EncodeCrossCrate::Yes, "`#[rustc_scalable_vector]` defines a scalable vector type" ), + rustc_attr!( + rustc_no_writable, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes, "`#[rustc_no_writable]` stops the compiler from adding the `writable` flag in LLVM, thus under Tree Borrows, mutable retags no longer count as writes" + ), // ========================================================================== // Internal attributes, Testing: diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index a18ddff947099..fa26ac8cfd677 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1489,6 +1489,9 @@ pub enum AttributeKind { /// Represents `#[rustc_no_mir_inline]` RustcNoMirInline, + /// Represents `#[rustc_no_writable]` + RustcNoWritable, + /// Represents `#[rustc_non_const_trait_method]`. RustcNonConstTraitMethod, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index c19fc6976c6e6..c49629a2504a8 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -161,6 +161,7 @@ impl AttributeKind { RustcNoImplicitAutorefs => Yes, RustcNoImplicitBounds => No, RustcNoMirInline => Yes, + RustcNoWritable => Yes, RustcNonConstTraitMethod => No, // should be reported via other queries like `constness` RustcNonnullOptimizationGuaranteed => Yes, RustcNounwind => No, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index f9d583bdf18c7..ba46751e68db8 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -834,6 +834,7 @@ fn test_unstable_options_tracking_hash() { tracked!(no_profiler_runtime, true); tracked!(no_trait_vptr, true); tracked!(no_unique_section_names, true); + tracked!(no_writable, true); tracked!(offload, vec![Offload::Device]); tracked!(on_broken_pipe, OnBrokenPipe::Kill); tracked!(osx_rpath_install_name, true); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9945802d70c14..bc31b281e986b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -357,6 +357,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcNoImplicitAutorefs | AttributeKind::RustcNoImplicitBounds | AttributeKind::RustcNoMirInline + | AttributeKind::RustcNoWritable | AttributeKind::RustcNonConstTraitMethod | AttributeKind::RustcNonnullOptimizationGuaranteed | AttributeKind::RustcNounwind diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index fb1b3c8679481..fb97015560090 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2530,6 +2530,8 @@ options! { "disable generation of trait vptr in vtable for upcasting"), no_unique_section_names: bool = (false, parse_bool, [TRACKED], "do not use unique names for text and data sections when -Z function-sections is used"), + no_writable: bool = (false, parse_bool, [TRACKED], + "do not insert the writable LLVM attribute; mutable retags don't count as writes under Tree Borrows"), normalize_docs: bool = (false, parse_bool, [TRACKED], "normalize associated items in rustdoc when generating documentation"), offload: Vec = (Vec::new(), parse_offload, [TRACKED], diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 738c9b975fd00..d887fdea52b5f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1751,6 +1751,7 @@ symbols! { rustc_no_implicit_autorefs, rustc_no_implicit_bounds, rustc_no_mir_inline, + rustc_no_writable, rustc_non_const_trait_method, rustc_nonnull_optimization_guaranteed, rustc_nounwind, diff --git a/src/doc/unstable-book/src/compiler-flags/no-writable.md b/src/doc/unstable-book/src/compiler-flags/no-writable.md new file mode 100644 index 0000000000000..36f3bf5bb30d0 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/no-writable.md @@ -0,0 +1,5 @@ +# `no-writable` + +--- + +This flag will globally stop the compiler from inserting the [writable](https://llvm.org/docs/LangRef.html#writable) LLVM flag. It also stops [Miri](https://github.com/rust-lang/miri) from testing for undefined behavior when inserting writes. It has the same effect as applying `#[rustc_no_writable]` to every function. diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 4808e53698c68..7c6eb00082063 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -529,6 +529,7 @@ Some native rustc `-Z` flags are also very relevant for Miri: sets this flag per default. * `-Zmir-emit-retag` controls whether `Retag` statements are emitted. Miri enables this per default because it is needed for [Stacked Borrows] and [Tree Borrows]. +* `-Zno-writable` disables the strong mode globally, thus disabling the tracking of spurious writes. This also stops the compiler from adding the `writable` attribute. This only has an effect in Miri if [Tree Borrows] are enabled. Moreover, Miri recognizes some environment variables: diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index e73c870508bd0..3a8dae22f4cbf 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -519,6 +519,7 @@ fn main() -> ExitCode { miri_config.borrow_tracker = Some(BorrowTrackerMethod::TreeBorrows(TreeBorrowsParams { precise_interior_mut: true, + writable: true, })); } else if arg == "-Zmiri-tree-borrows-no-precise-interior-mut" { match &mut miri_config.borrow_tracker { @@ -530,6 +531,16 @@ fn main() -> ExitCode { "`-Zmiri-tree-borrows` is required before `-Zmiri-tree-borrows-no-precise-interior-mut`" ), }; + } else if arg == "-Zno-writable" { + match &mut miri_config.borrow_tracker { + Some(BorrowTrackerMethod::TreeBorrows(params)) => { + params.writable = false; + } + _ => + eprintln!( + "Warning: `-Zno-writable` only has an effect in Miri if `-Zmiri-tree-borrows` is before it. The flag still will have an effect in the compiler." + ), + }; } else if arg == "-Zmiri-disable-data-race-detector" { miri_config.data_race_detector = false; miri_config.weak_memory_emulation = false; diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index 9aa0ce48e09a0..3f392bd6687be 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -224,6 +224,7 @@ pub enum BorrowTrackerMethod { #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct TreeBorrowsParams { pub precise_interior_mut: bool, + pub writable: bool, } impl BorrowTrackerMethod {