Skip to content

Commit

Permalink
Auto merge of rust-lang#128088 - tgross35:rollup-5jeeoew, r=tgross35
Browse files Browse the repository at this point in the history
Rollup of 7 pull requests

Successful merges:

 - rust-lang#124895 (Disallow hidden references to mutable static)
 - rust-lang#125834 (treat `&raw (const|mut) UNSAFE_STATIC` implied deref as safe)
 - rust-lang#126898 (Migrate `run-make/link-framework` to `rmake.rs`)
 - rust-lang#127962 (Cleanup compiletest dylib name calculation)
 - rust-lang#127990 (Migrate `lto-linkage-used-attr`, `no-duplicate-libs` and `pgo-gen-no-imp-symbols` `run-make` tests to rmake)
 - rust-lang#128067 (Get rid of `can_eq_shallow`)
 - rust-lang#128076 (Get rid of `InferCtxtExt` from `error_reporting::traits`)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jul 23, 2024
2 parents 49649bf + 131a76e commit a3d7cff
Show file tree
Hide file tree
Showing 130 changed files with 1,812 additions and 885 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_driver_impl/src/signal_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 8 additions & 12 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
145 changes: 104 additions & 41 deletions compiler/rustc_hir_analysis/src/check/errs.rs
Original file line number Diff line number Diff line change
@@ -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<Span> {
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(
Expand All @@ -63,27 +116,37 @@ fn handle_static_mut_ref(
lo: Span,
hi: Span,
e2024: bool,
mutable: Mutability,
hir_id: hir::HirId,
mutable: Option<Mutability>,
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 },
);
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/check/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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);
}

Expand Down
20 changes: 13 additions & 7 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<MutRefSugg>,
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)]
Expand Down Expand Up @@ -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<MutRefSugg>,
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)]
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
12 changes: 0 additions & 12 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>(&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,
Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,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
Expand Down
Loading

0 comments on commit a3d7cff

Please sign in to comment.