Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 8 pull requests #136185

Merged
merged 18 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
656d1cc
alloc: add `#![warn(unreachable_pub)]`
Urgau Jan 11, 2025
2fd6296
add missing allocator safety in alloc crate
DiuDiu777 Jan 21, 2025
c06ed54
Implement `AtomicT::update` & `AtomicT::try_update`
GrigorenkoPV Dec 3, 2024
d3cd832
Document purpose of closure in from_fn.rs more clearly
hkBst Jan 22, 2025
5082fd8
Trim extra whitespace in fn ptr suggestion span
tyrone-wu Nov 17, 2024
1f4309c
Fix 2/4 tests skipped by opt-dist
saethlin Jan 24, 2025
1cbb062
Type level consts can show up in MIR type checker
compiler-errors Jan 27, 2025
057313b
Reapply "Auto merge of #133734 - scottmcm:lower-indexing-to-ptrmetada…
compiler-errors Jan 19, 2025
eeecb56
Represent the raw pointer for a array length check as a new kind of f…
compiler-errors Jan 19, 2025
3d6c6fa
Document powf and powi calls that always return 1.0
hkBst Jan 26, 2025
c0005f1
Rollup merge of #133151 - tyrone-wu:trim-fn-ptr-whitespace, r=compile…
matthiaskrgr Jan 28, 2025
da5e22d
Rollup merge of #133829 - GrigorenkoPV:fetch_update_infallible, r=Nor…
matthiaskrgr Jan 28, 2025
e3420f4
Rollup merge of #135367 - Urgau:unreach_pub-std-3, r=Noratrieb
matthiaskrgr Jan 28, 2025
21ddd7a
Rollup merge of #135748 - compiler-errors:len-2, r=RalfJung,oli-obk
matthiaskrgr Jan 28, 2025
32c04fc
Rollup merge of #135805 - DiuDiu777:master, r=Noratrieb
matthiaskrgr Jan 28, 2025
448fa11
Rollup merge of #135886 - hkBst:patch-14, r=workingjubilee
matthiaskrgr Jan 28, 2025
da6d9fd
Rollup merge of #135961 - saethlin:skip-less-in-opt-dist, r=jieyouxu
matthiaskrgr Jan 28, 2025
9a192b2
Rollup merge of #136012 - hkBst:patch-22, r=workingjubilee,tgross35
matthiaskrgr Jan 28, 2025
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
11 changes: 7 additions & 4 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1284,15 +1284,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
);
}

&Rvalue::RawPtr(mutability, place) => {
let access_kind = match mutability {
Mutability::Mut => (
&Rvalue::RawPtr(kind, place) => {
let access_kind = match kind {
RawPtrKind::Mut => (
Deep,
Write(WriteKind::MutableBorrow(BorrowKind::Mut {
kind: MutBorrowKind::Default,
})),
),
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
RawPtrKind::Const => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
RawPtrKind::FakeForPtrMetadata => {
(Shallow(Some(ArtificialField::ArrayLength)), Read(ReadKind::Copy))
}
};

self.access_place(
Expand Down
21 changes: 10 additions & 11 deletions compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ use std::ops::ControlFlow;
use rustc_data_structures::graph::dominators::Dominators;
use rustc_middle::bug;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{
self, BasicBlock, Body, BorrowKind, FakeBorrowKind, InlineAsmOperand, Location, Mutability,
NonDivergingIntrinsic, Operand, Place, Rvalue, Statement, StatementKind, Terminator,
TerminatorKind,
};
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use tracing::debug;

Expand Down Expand Up @@ -60,7 +56,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> {
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => {
self.consume_operand(location, op);
}
StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
src,
dst,
count,
Expand Down Expand Up @@ -273,15 +269,18 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
self.access_place(location, place, access_kind, LocalMutationIsAllowed::No);
}

&Rvalue::RawPtr(mutability, place) => {
let access_kind = match mutability {
Mutability::Mut => (
&Rvalue::RawPtr(kind, place) => {
let access_kind = match kind {
RawPtrKind::Mut => (
Deep,
Write(WriteKind::MutableBorrow(BorrowKind::Mut {
kind: mir::MutBorrowKind::Default,
kind: MutBorrowKind::Default,
})),
),
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
RawPtrKind::Const => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
RawPtrKind::FakeForPtrMetadata => {
(Shallow(Some(ArtificialField::ArrayLength)), Read(ReadKind::Copy))
}
};

self.access_place(location, place, access_kind, LocalMutationIsAllowed::No);
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
let tcx = self.tcx();
let maybe_uneval = match constant.const_ {
Const::Ty(_, ct) => match ct.kind() {
ty::ConstKind::Unevaluated(_) => {
bug!("should not encounter unevaluated Const::Ty here, got {:?}", ct)
ty::ConstKind::Unevaluated(uv) => {
Some(UnevaluatedConst { def: uv.def, args: uv.args, promoted: None })
}
_ => None,
},
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_codegen_ssa/src/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -612,9 +612,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::Rvalue::CopyForDeref(place) => {
self.codegen_operand(bx, &mir::Operand::Copy(place))
}
mir::Rvalue::RawPtr(mutability, place) => {
let mk_ptr =
move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| Ty::new_ptr(tcx, ty, mutability);
mir::Rvalue::RawPtr(kind, place) => {
let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| {
Ty::new_ptr(tcx, ty, kind.to_mutbl_lossy())
};
self.codegen_place_to_pointer(bx, place, mk_ptr)
}

Expand Down
31 changes: 24 additions & 7 deletions compiler/rustc_const_eval/src/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}

Rvalue::Ref(_, BorrowKind::Mut { .. }, place)
| Rvalue::RawPtr(Mutability::Mut, place) => {
| Rvalue::RawPtr(RawPtrKind::Mut, place) => {
// Inside mutable statics, we allow arbitrary mutable references.
// We've allowed `static mut FOO = &mut [elements];` for a long time (the exact
// reasons why are lost to history), and there is no reason to restrict that to
Expand All @@ -536,7 +536,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}

Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Fake(_), place)
| Rvalue::RawPtr(Mutability::Not, place) => {
| Rvalue::RawPtr(RawPtrKind::Const, place) => {
let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
self.ccx,
&mut |local| self.qualifs.has_mut_interior(self.ccx, local, location),
Expand All @@ -548,6 +548,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
}

Rvalue::RawPtr(RawPtrKind::FakeForPtrMetadata, place) => {
// These are only inserted for slice length, so the place must already be indirect.
// This implies we do not have to worry about whether the borrow escapes.
assert!(place.is_indirect(), "fake borrows are always indirect");
}

Rvalue::Cast(
CastKind::PointerCoercion(
PointerCoercion::MutToConstPointer
Expand Down Expand Up @@ -586,12 +592,23 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
) => {}
Rvalue::ShallowInitBox(_, _) => {}

Rvalue::UnaryOp(_, operand) => {
Rvalue::UnaryOp(op, operand) => {
let ty = operand.ty(self.body, self.tcx);
if is_int_bool_float_or_char(ty) {
// Int, bool, float, and char operations are fine.
} else {
span_bug!(self.span, "non-primitive type in `Rvalue::UnaryOp`: {:?}", ty);
match op {
UnOp::Not | UnOp::Neg => {
if is_int_bool_float_or_char(ty) {
// Int, bool, float, and char operations are fine.
} else {
span_bug!(
self.span,
"non-primitive type in `Rvalue::UnaryOp{op:?}`: {ty:?}",
);
}
}
UnOp::PtrMetadata => {
// Getting the metadata from a pointer is always const.
// We already validated the type is valid in the validator.
}
}
}

Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_const_eval/src/interpret/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
self.write_immediate(*val, &dest)?;
}

RawPtr(_, place) => {
RawPtr(kind, place) => {
// Figure out whether this is an addr_of of an already raw place.
let place_base_raw = if place.is_indirect_first_projection() {
let ty = self.frame().body.local_decls[place.local].ty;
Expand All @@ -250,8 +250,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let src = self.eval_place(place)?;
let place = self.force_allocation(&src)?;
let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
if !place_base_raw {
// If this was not already raw, it needs retagging.
if !place_base_raw && !kind.is_fake() {
// If this was not already raw, it needs retagging -- except for "fake"
// raw borrows whose defining property is that they do not get retagged.
val = M::retag_ptr_value(self, mir::RetagKind::Raw, &val)?;
}
self.write_immediate(*val, &dest)?;
Expand Down
55 changes: 54 additions & 1 deletion compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,59 @@ pub enum BorrowKind {
Mut { kind: MutBorrowKind },
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
#[derive(Hash, HashStable)]
pub enum RawPtrKind {
Mut,
Const,
/// Creates a raw pointer to a place that will only be used to access its metadata,
/// not the data behind the pointer. Note that this limitation is *not* enforced
/// by the validator.
///
/// The borrow checker allows overlap of these raw pointers with references to the
/// data. This is sound even if the pointer is "misused" since any such use is anyway
/// unsafe. In terms of the operational semantics (i.e., Miri), this is equivalent
/// to `RawPtrKind::Mut`, but will never incur a retag.
FakeForPtrMetadata,
}

impl From<Mutability> for RawPtrKind {
fn from(other: Mutability) -> Self {
match other {
Mutability::Mut => RawPtrKind::Mut,
Mutability::Not => RawPtrKind::Const,
}
}
}

impl RawPtrKind {
pub fn is_fake(self) -> bool {
match self {
RawPtrKind::Mut | RawPtrKind::Const => false,
RawPtrKind::FakeForPtrMetadata => true,
}
}

pub fn to_mutbl_lossy(self) -> Mutability {
match self {
RawPtrKind::Mut => Mutability::Mut,
RawPtrKind::Const => Mutability::Not,

// We have no type corresponding to a fake borrow, so use
// `*const` as an approximation.
RawPtrKind::FakeForPtrMetadata => Mutability::Not,
}
}

pub fn ptr_str(self) -> &'static str {
match self {
RawPtrKind::Mut => "mut",
RawPtrKind::Const => "const",
RawPtrKind::FakeForPtrMetadata => "const (fake)",
}
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
#[derive(Hash, HashStable)]
pub enum MutBorrowKind {
Expand Down Expand Up @@ -1356,7 +1409,7 @@ pub enum Rvalue<'tcx> {
///
/// Like with references, the semantics of this operation are heavily dependent on the aliasing
/// model.
RawPtr(Mutability, Place<'tcx>),
RawPtr(RawPtrKind, Place<'tcx>),

/// Yields the length of the place, as a `usize`.
///
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/mir/tcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,9 @@ impl<'tcx> Rvalue<'tcx> {
let place_ty = place.ty(local_decls, tcx).ty;
Ty::new_ref(tcx, reg, place_ty, bk.to_mutbl_lossy())
}
Rvalue::RawPtr(mutability, ref place) => {
Rvalue::RawPtr(kind, ref place) => {
let place_ty = place.ty(local_decls, tcx).ty;
Ty::new_ptr(tcx, place_ty, mutability)
Ty::new_ptr(tcx, place_ty, kind.to_mutbl_lossy())
}
Rvalue::Len(..) => tcx.types.usize,
Rvalue::Cast(.., ty) => ty,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/mir/type_foldable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ TrivialTypeTraversalImpls! {
SourceScopeLocalData,
UserTypeAnnotationIndex,
BorrowKind,
RawPtrKind,
CastKind,
BasicBlock,
SwitchTargets,
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_middle/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -685,12 +685,15 @@ macro_rules! make_mir_visitor {

Rvalue::RawPtr(m, path) => {
let ctx = match m {
Mutability::Mut => PlaceContext::MutatingUse(
RawPtrKind::Mut => PlaceContext::MutatingUse(
MutatingUseContext::RawBorrow
),
Mutability::Not => PlaceContext::NonMutatingUse(
RawPtrKind::Const => PlaceContext::NonMutatingUse(
NonMutatingUseContext::RawBorrow
),
RawPtrKind::FakeForPtrMetadata => PlaceContext::NonMutatingUse(
NonMutatingUseContext::Inspect
),
};
self.visit_place(path, ctx, location);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
),
ExprKind::RawBorrow { mutability, arg } => Ok(
Rvalue::RawPtr(*mutability, self.parse_place(*arg)?)
Rvalue::RawPtr((*mutability).into(), self.parse_place(*arg)?)
),
ExprKind::Binary { op, lhs, rhs } => Ok(
Rvalue::BinaryOp(*op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?)))
Expand Down
79 changes: 71 additions & 8 deletions compiler/rustc_mir_build/src/builder/expr/as_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,69 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block.and(base_place.index(idx))
}

/// Given a place that's either an array or a slice, returns an operand
/// with the length of the array/slice.
///
/// For arrays it'll be `Operand::Constant` with the actual length;
/// For slices it'll be `Operand::Move` of a local using `PtrMetadata`.
fn len_of_slice_or_array(
&mut self,
block: BasicBlock,
place: Place<'tcx>,
span: Span,
source_info: SourceInfo,
) -> Operand<'tcx> {
let place_ty = place.ty(&self.local_decls, self.tcx).ty;
match place_ty.kind() {
ty::Array(_elem_ty, len_const) => {
// We know how long an array is, so just use that as a constant
// directly -- no locals needed. We do need one statement so
// that borrow- and initialization-checking consider it used,
// though. FIXME: Do we really *need* to count this as a use?
// Could partial array tracking work off something else instead?
self.cfg.push_fake_read(block, source_info, FakeReadCause::ForIndex, place);
let const_ = Const::Ty(self.tcx.types.usize, *len_const);
Operand::Constant(Box::new(ConstOperand { span, user_ty: None, const_ }))
}
ty::Slice(_elem_ty) => {
let ptr_or_ref = if let [PlaceElem::Deref] = place.projection[..]
&& let local_ty = self.local_decls[place.local].ty
&& local_ty.is_trivially_pure_clone_copy()
{
// It's extremely common that we have something that can be
// directly passed to `PtrMetadata`, so avoid an unnecessary
// temporary and statement in those cases. Note that we can
// only do that for `Copy` types -- not `&mut [_]` -- because
// the MIR we're building here needs to pass NLL later.
Operand::Copy(Place::from(place.local))
} else {
let ptr_ty = Ty::new_imm_ptr(self.tcx, place_ty);
let slice_ptr = self.temp(ptr_ty, span);
self.cfg.push_assign(
block,
source_info,
slice_ptr,
Rvalue::RawPtr(RawPtrKind::FakeForPtrMetadata, place),
);
Operand::Move(slice_ptr)
};

let len = self.temp(self.tcx.types.usize, span);
self.cfg.push_assign(
block,
source_info,
len,
Rvalue::UnaryOp(UnOp::PtrMetadata, ptr_or_ref),
);

Operand::Move(len)
}
_ => {
span_bug!(span, "len called on place of type {place_ty:?}")
}
}
}

fn bounds_check(
&mut self,
block: BasicBlock,
Expand All @@ -638,25 +701,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr_span: Span,
source_info: SourceInfo,
) -> BasicBlock {
let usize_ty = self.tcx.types.usize;
let bool_ty = self.tcx.types.bool;
// bounds check:
let len = self.temp(usize_ty, expr_span);
let lt = self.temp(bool_ty, expr_span);
let slice = slice.to_place(self);

// len = len(slice)
self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice.to_place(self)));
let len = self.len_of_slice_or_array(block, slice, expr_span, source_info);

// lt = idx < len
let bool_ty = self.tcx.types.bool;
let lt = self.temp(bool_ty, expr_span);
self.cfg.push_assign(
block,
source_info,
lt,
Rvalue::BinaryOp(
BinOp::Lt,
Box::new((Operand::Copy(Place::from(index)), Operand::Copy(len))),
Box::new((Operand::Copy(Place::from(index)), len.to_copy())),
),
);
let msg = BoundsCheck { len: Operand::Move(len), index: Operand::Copy(Place::from(index)) };
let msg = BoundsCheck { len, index: Operand::Copy(Place::from(index)) };

// assert!(lt, "...")
self.assert(block, Operand::Move(lt), true, msg, expr_span)
}
Expand Down
Loading
Loading