Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,21 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcNoMirInlineParser {
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoMirInline;
}

pub(crate) struct RustcNoWritableParser;

impl<S: Stage> NoArgsAttributeParser<S> for RustcNoWritableParser {
const PATH: &[Symbol] = &[sym::rustc_no_writable];
const ON_DUPLICATE: OnDuplicate<S> = 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<S: Stage> NoArgsAttributeParser<S> for RustcLintQueryInstabilityParser {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ attribute_parsers!(
Single<WithoutArgs<RustcNoImplicitAutorefsParser>>,
Single<WithoutArgs<RustcNoImplicitBoundsParser>>,
Single<WithoutArgs<RustcNoMirInlineParser>>,
Single<WithoutArgs<RustcNoWritableParser>>,
Single<WithoutArgs<RustcNonConstTraitMethodParser>>,
Single<WithoutArgs<RustcNonnullOptimizationGuaranteedParser>>,
Single<WithoutArgs<RustcNounwindParser>>,
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_const_eval/src/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Also returns a ptr to `self.extra` so that the caller can use it in parallel with the
/// allocation.
///
/// This triggers UB if the allocation is not mutable!
///
/// You almost certainly want to use `get_ptr_alloc`/`get_ptr_alloc_mut` instead.
pub fn get_alloc_raw_mut(
&mut self,
Expand Down Expand Up @@ -841,6 +843,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {

/// Gives raw, mutable access to the `Allocation` address, without bounds or alignment checks.
/// The caller is responsible for calling the access hooks!
///
/// This triggers UB if the allocation is not mutable!
pub fn get_alloc_bytes_unchecked_raw_mut(
&mut self,
id: AllocId,
Expand Down Expand Up @@ -893,6 +897,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}

/// Return the `extra` field of the given allocation.
///
/// This triggers UB if the allocation is not mutable!
pub fn get_alloc_extra_mut<'a>(
&'a mut self,
id: AllocId,
Expand Down Expand Up @@ -1086,6 +1092,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
interp_ok(ty)
}

/// This triggers UB if the allocation is not mutable!
pub fn alloc_mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> {
self.get_alloc_raw_mut(id)?.0.mutability = Mutability::Not;
interp_ok(())
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::RustcNoImplicitAutorefs
| AttributeKind::RustcNoImplicitBounds
| AttributeKind::RustcNoMirInline
| AttributeKind::RustcNoWritable
| AttributeKind::RustcNonConstTraitMethod
| AttributeKind::RustcNonnullOptimizationGuaranteed
| AttributeKind::RustcNounwind
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<crate::config::Offload> = (Vec::new(), parse_offload, [TRACKED],
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,7 @@ impl<T> [T] {
#[rustc_as_ptr]
#[inline(always)]
#[must_use]
#[rustc_no_writable]
pub const fn as_mut_ptr(&mut self) -> *mut T {
self as *mut [T] as *mut T
}
Expand Down
1 change: 1 addition & 0 deletions library/core/src/str/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ impl str {
#[rustc_as_ptr]
#[must_use]
#[inline(always)]
#[rustc_no_writable]
pub const fn as_mut_ptr(&mut self) -> *mut u8 {
self as *mut str as *mut u8
}
Expand Down
5 changes: 5 additions & 0 deletions src/doc/unstable-book/src/compiler-flags/no-writable.md
Original file line number Diff line number Diff line change
@@ -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](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.
1 change: 1 addition & 0 deletions src/tools/miri/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
11 changes: 11 additions & 0 deletions src/tools/miri/src/bin/miri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/tools/miri/src/borrow_tracker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::*;
#[derive(Clone, Copy, Debug)]
pub enum AccessCause {
Explicit(AccessKind),
Reborrow,
Reborrow(AccessKind),
Dealloc,
FnExit(AccessKind),
}
Expand All @@ -24,7 +24,7 @@ impl fmt::Display for AccessCause {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Explicit(kind) => write!(f, "{kind}"),
Self::Reborrow => write!(f, "reborrow"),
Self::Reborrow(_) => write!(f, "reborrow"),
Self::Dealloc => write!(f, "deallocation"),
// This is dead code, since the protector release access itself can never
// cause UB (while the protector is active, if some other access invalidates
Expand All @@ -40,7 +40,7 @@ impl AccessCause {
let rel = if is_foreign { "foreign" } else { "child" };
match self {
Self::Explicit(kind) => format!("{rel} {kind}"),
Self::Reborrow => format!("reborrow (acting as a {rel} read access)"),
Self::Reborrow(kind) => format!("reborrow (acting as a {rel} {kind})"),
Self::Dealloc => format!("deallocation (acting as a {rel} write access)"),
Self::FnExit(kind) => format!("protector release (acting as a {rel} {kind})"),
}
Expand Down
Loading
Loading