Skip to content

Commit

Permalink
Auto merge of #128351 - ChayimFriedman2:lint-transmute-unsafe-cell, r…
Browse files Browse the repository at this point in the history
…=<try>

[crater] Lint against &T to &mut T and &T to &UnsafeCell<T> transmutes

Needs a (check-only) crater run as per https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Lint.20against.20.60.26.60-.3E.60.26UnsafeCell.60.20transmutes/near/454868964.

r? ghost
  • Loading branch information
bors committed Jul 29, 2024
2 parents 612a33f + 59c22c3 commit be92fb7
Show file tree
Hide file tree
Showing 35 changed files with 1,105 additions and 75 deletions.
10 changes: 10 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ lint_builtin_missing_doc = missing documentation for {$article} {$desc}
lint_builtin_mutable_transmutes =
transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell
.note = transmute from `{$from}` to `{$to}`
lint_builtin_no_mangle_fn = declaration of a `no_mangle` function
lint_builtin_no_mangle_generic = functions generic over types or consts must be mangled
Expand Down Expand Up @@ -169,6 +170,10 @@ lint_builtin_unreachable_pub = unreachable `pub` {$what}
lint_builtin_unsafe_block = usage of an `unsafe` block
lint_builtin_unsafe_cell_transmutes =
transmuting &T to &UnsafeCell<T> is undefined behavior, even if the reference is unused, consider using UnsafeCell on the original data
.note = transmute from `{$from}` to `{$to}`
lint_builtin_unsafe_extern_block = usage of an `unsafe extern` block
lint_builtin_unsafe_impl = implementation of an `unsafe` trait
Expand Down Expand Up @@ -862,6 +867,11 @@ lint_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe
.label = usage of unsafe attribute
lint_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)`
lint_unsafe_cell_reference_casting =
casting `&T` to `&UnsafeCell<T>` is undefined behavior, even if the reference is unused, consider using an `UnsafeCell` on the original data
.label = casting happend here
.note = cast from `{$from}` to `{$to}`
lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
lint_untranslatable_diag = diagnostics should be created using translatable messages
Expand Down
78 changes: 5 additions & 73 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,11 @@ use crate::lints::{
BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives,
BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures,
BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents,
BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, BuiltinMutablesTransmutes,
BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed,
BuiltinTrivialBounds, BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller,
BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub,
BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub,
BuiltinWhileTrue, InvalidAsmLabel,
BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, BuiltinNoMangleGeneric,
BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds,
BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit,
BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures,
BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel,
};
use crate::nonstandard_style::{method_context, MethodLateContext};
use crate::{
Expand Down Expand Up @@ -1100,72 +1099,6 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
}
}

declare_lint! {
/// The `mutable_transmutes` lint catches transmuting from `&T` to `&mut
/// T` because it is [undefined behavior].
///
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
///
/// ### Example
///
/// ```rust,compile_fail
/// unsafe {
/// let y = std::mem::transmute::<&i32, &mut i32>(&5);
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Certain assumptions are made about aliasing of data, and this transmute
/// violates those assumptions. Consider using [`UnsafeCell`] instead.
///
/// [`UnsafeCell`]: https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html
MUTABLE_TRANSMUTES,
Deny,
"transmuting &T to &mut T is undefined behavior, even if the reference is unused"
}

declare_lint_pass!(MutableTransmutes => [MUTABLE_TRANSMUTES]);

impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
if let Some((&ty::Ref(_, _, from_mutbl), &ty::Ref(_, _, to_mutbl))) =
get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind()))
{
if from_mutbl < to_mutbl {
cx.emit_span_lint(MUTABLE_TRANSMUTES, expr.span, BuiltinMutablesTransmutes);
}
}

fn get_transmute_from_to<'tcx>(
cx: &LateContext<'tcx>,
expr: &hir::Expr<'_>,
) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
let def = if let hir::ExprKind::Path(ref qpath) = expr.kind {
cx.qpath_res(qpath, expr.hir_id)
} else {
return None;
};
if let Res::Def(DefKind::Fn, did) = def {
if !def_id_is_transmute(cx, did) {
return None;
}
let sig = cx.typeck_results().node_type(expr.hir_id).fn_sig(cx.tcx);
let from = sig.inputs().skip_binder()[0];
let to = sig.output().skip_binder();
return Some((from, to));
}
None
}

fn def_id_is_transmute(cx: &LateContext<'_>, def_id: DefId) -> bool {
cx.tcx.is_intrinsic(def_id, sym::transmute)
}
}
}

declare_lint! {
/// The `unstable_features` lint detects uses of `#![feature]`.
///
Expand Down Expand Up @@ -1612,7 +1545,6 @@ declare_lint_pass!(
UNUSED_DOC_COMMENTS,
NO_MANGLE_CONST_ITEMS,
NO_MANGLE_GENERIC_ITEMS,
MUTABLE_TRANSMUTES,
UNSTABLE_FEATURES,
UNREACHABLE_PUB,
TYPE_ALIAS_BOUNDS,
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ mod macro_expr_fragment_specifier_2024_migration;
mod map_unit_fn;
mod methods;
mod multiple_supertrait_upcastable;
mod mutable_transmutes;
mod non_ascii_idents;
mod non_fmt_panic;
mod non_local_def;
Expand Down Expand Up @@ -99,6 +100,7 @@ use macro_expr_fragment_specifier_2024_migration::*;
use map_unit_fn::*;
use methods::*;
use multiple_supertrait_upcastable::*;
use mutable_transmutes::*;
use non_ascii_idents::*;
use non_fmt_panic::NonPanicFmt;
use non_local_def::*;
Expand Down Expand Up @@ -209,6 +211,7 @@ late_lint_methods!(
// Depends on referenced function signatures in expressions
PtrNullChecks: PtrNullChecks,
MutableTransmutes: MutableTransmutes,
UnsafeCellReferenceCasting: UnsafeCellReferenceCasting,
TypeAliasBounds: TypeAliasBounds,
TrivialConstraints: TrivialConstraints,
TypeLimits: TypeLimits::new(),
Expand Down
27 changes: 26 additions & 1 deletion compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,34 @@ pub struct BuiltinConstNoMangle {
pub suggestion: Span,
}

// mutable_transmutes.rs
#[derive(LintDiagnostic)]
#[diag(lint_builtin_mutable_transmutes)]
pub struct BuiltinMutablesTransmutes;
#[note]
pub struct BuiltinMutablesTransmutes {
pub from: String,
pub to: String,
}

// mutable_transmutes.rs
#[derive(LintDiagnostic)]
#[diag(lint_builtin_unsafe_cell_transmutes)]
#[note]
pub struct BuiltinUnsafeCellTransmutes {
pub from: String,
pub to: String,
}

// mutable_transmutes.rs
#[derive(LintDiagnostic)]
#[diag(lint_unsafe_cell_reference_casting)]
#[note]
pub struct UnsafeCellReferenceCastingDiag {
#[label]
pub orig_cast: Option<Span>,
pub from: String,
pub to: String,
}

#[derive(LintDiagnostic)]
#[diag(lint_builtin_unstable_features)]
Expand Down
Loading

0 comments on commit be92fb7

Please sign in to comment.