Skip to content

Commit fdd1a3b

Browse files
committed
Auto merge of rust-lang#136185 - matthiaskrgr:rollup-zqzy6wb, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#133151 (Trim extra whitespace in fn ptr suggestion span) - rust-lang#133829 (Implement `AtomicT::update` & `AtomicT::try_update`) - rust-lang#135367 (Enable `unreachable_pub` lint in `alloc`) - rust-lang#135748 (Lower index bounds checking to `PtrMetadata`, this time with the right fake borrow semantics 😸) - rust-lang#135805 (Add missing allocator safety in alloc crate) - rust-lang#135886 (Document purpose of closure in from_fn.rs more clearly) - rust-lang#135961 (Fix 2/4 tests skipped by opt-dist) - rust-lang#136012 (Document powf and powi values that are always 1.0) r? `@ghost` `@rustbot` modify labels: rollup
2 parents aa6f5ab + 9a192b2 commit fdd1a3b

File tree

155 files changed

+2374
-1993
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

155 files changed

+2374
-1993
lines changed

compiler/rustc_borrowck/src/lib.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1284,15 +1284,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
12841284
);
12851285
}
12861286

1287-
&Rvalue::RawPtr(mutability, place) => {
1288-
let access_kind = match mutability {
1289-
Mutability::Mut => (
1287+
&Rvalue::RawPtr(kind, place) => {
1288+
let access_kind = match kind {
1289+
RawPtrKind::Mut => (
12901290
Deep,
12911291
Write(WriteKind::MutableBorrow(BorrowKind::Mut {
12921292
kind: MutBorrowKind::Default,
12931293
})),
12941294
),
1295-
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
1295+
RawPtrKind::Const => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
1296+
RawPtrKind::FakeForPtrMetadata => {
1297+
(Shallow(Some(ArtificialField::ArrayLength)), Read(ReadKind::Copy))
1298+
}
12961299
};
12971300

12981301
self.access_place(

compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs

+10-11
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,7 @@ use std::ops::ControlFlow;
33
use rustc_data_structures::graph::dominators::Dominators;
44
use rustc_middle::bug;
55
use rustc_middle::mir::visit::Visitor;
6-
use rustc_middle::mir::{
7-
self, BasicBlock, Body, BorrowKind, FakeBorrowKind, InlineAsmOperand, Location, Mutability,
8-
NonDivergingIntrinsic, Operand, Place, Rvalue, Statement, StatementKind, Terminator,
9-
TerminatorKind,
10-
};
6+
use rustc_middle::mir::*;
117
use rustc_middle::ty::TyCtxt;
128
use tracing::debug;
139

@@ -60,7 +56,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> {
6056
StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => {
6157
self.consume_operand(location, op);
6258
}
63-
StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
59+
StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
6460
src,
6561
dst,
6662
count,
@@ -273,15 +269,18 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
273269
self.access_place(location, place, access_kind, LocalMutationIsAllowed::No);
274270
}
275271

276-
&Rvalue::RawPtr(mutability, place) => {
277-
let access_kind = match mutability {
278-
Mutability::Mut => (
272+
&Rvalue::RawPtr(kind, place) => {
273+
let access_kind = match kind {
274+
RawPtrKind::Mut => (
279275
Deep,
280276
Write(WriteKind::MutableBorrow(BorrowKind::Mut {
281-
kind: mir::MutBorrowKind::Default,
277+
kind: MutBorrowKind::Default,
282278
})),
283279
),
284-
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
280+
RawPtrKind::Const => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
281+
RawPtrKind::FakeForPtrMetadata => {
282+
(Shallow(Some(ArtificialField::ArrayLength)), Read(ReadKind::Copy))
283+
}
285284
};
286285

287286
self.access_place(location, place, access_kind, LocalMutationIsAllowed::No);

compiler/rustc_borrowck/src/type_check/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -349,8 +349,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
349349
let tcx = self.tcx();
350350
let maybe_uneval = match constant.const_ {
351351
Const::Ty(_, ct) => match ct.kind() {
352-
ty::ConstKind::Unevaluated(_) => {
353-
bug!("should not encounter unevaluated Const::Ty here, got {:?}", ct)
352+
ty::ConstKind::Unevaluated(uv) => {
353+
Some(UnevaluatedConst { def: uv.def, args: uv.args, promoted: None })
354354
}
355355
_ => None,
356356
},

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -612,9 +612,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
612612
mir::Rvalue::CopyForDeref(place) => {
613613
self.codegen_operand(bx, &mir::Operand::Copy(place))
614614
}
615-
mir::Rvalue::RawPtr(mutability, place) => {
616-
let mk_ptr =
617-
move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| Ty::new_ptr(tcx, ty, mutability);
615+
mir::Rvalue::RawPtr(kind, place) => {
616+
let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| {
617+
Ty::new_ptr(tcx, ty, kind.to_mutbl_lossy())
618+
};
618619
self.codegen_place_to_pointer(bx, place, mk_ptr)
619620
}
620621

compiler/rustc_const_eval/src/check_consts/check.rs

+24-7
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
518518
}
519519

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

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

551+
Rvalue::RawPtr(RawPtrKind::FakeForPtrMetadata, place) => {
552+
// These are only inserted for slice length, so the place must already be indirect.
553+
// This implies we do not have to worry about whether the borrow escapes.
554+
assert!(place.is_indirect(), "fake borrows are always indirect");
555+
}
556+
551557
Rvalue::Cast(
552558
CastKind::PointerCoercion(
553559
PointerCoercion::MutToConstPointer
@@ -586,12 +592,23 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
586592
) => {}
587593
Rvalue::ShallowInitBox(_, _) => {}
588594

589-
Rvalue::UnaryOp(_, operand) => {
595+
Rvalue::UnaryOp(op, operand) => {
590596
let ty = operand.ty(self.body, self.tcx);
591-
if is_int_bool_float_or_char(ty) {
592-
// Int, bool, float, and char operations are fine.
593-
} else {
594-
span_bug!(self.span, "non-primitive type in `Rvalue::UnaryOp`: {:?}", ty);
597+
match op {
598+
UnOp::Not | UnOp::Neg => {
599+
if is_int_bool_float_or_char(ty) {
600+
// Int, bool, float, and char operations are fine.
601+
} else {
602+
span_bug!(
603+
self.span,
604+
"non-primitive type in `Rvalue::UnaryOp{op:?}`: {ty:?}",
605+
);
606+
}
607+
}
608+
UnOp::PtrMetadata => {
609+
// Getting the metadata from a pointer is always const.
610+
// We already validated the type is valid in the validator.
611+
}
595612
}
596613
}
597614

compiler/rustc_const_eval/src/interpret/step.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
237237
self.write_immediate(*val, &dest)?;
238238
}
239239

240-
RawPtr(_, place) => {
240+
RawPtr(kind, place) => {
241241
// Figure out whether this is an addr_of of an already raw place.
242242
let place_base_raw = if place.is_indirect_first_projection() {
243243
let ty = self.frame().body.local_decls[place.local].ty;
@@ -250,8 +250,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
250250
let src = self.eval_place(place)?;
251251
let place = self.force_allocation(&src)?;
252252
let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
253-
if !place_base_raw {
254-
// If this was not already raw, it needs retagging.
253+
if !place_base_raw && !kind.is_fake() {
254+
// If this was not already raw, it needs retagging -- except for "fake"
255+
// raw borrows whose defining property is that they do not get retagged.
255256
val = M::retag_ptr_value(self, mir::RetagKind::Raw, &val)?;
256257
}
257258
self.write_immediate(*val, &dest)?;

compiler/rustc_middle/src/mir/syntax.rs

+54-1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,59 @@ pub enum BorrowKind {
180180
Mut { kind: MutBorrowKind },
181181
}
182182

183+
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
184+
#[derive(Hash, HashStable)]
185+
pub enum RawPtrKind {
186+
Mut,
187+
Const,
188+
/// Creates a raw pointer to a place that will only be used to access its metadata,
189+
/// not the data behind the pointer. Note that this limitation is *not* enforced
190+
/// by the validator.
191+
///
192+
/// The borrow checker allows overlap of these raw pointers with references to the
193+
/// data. This is sound even if the pointer is "misused" since any such use is anyway
194+
/// unsafe. In terms of the operational semantics (i.e., Miri), this is equivalent
195+
/// to `RawPtrKind::Mut`, but will never incur a retag.
196+
FakeForPtrMetadata,
197+
}
198+
199+
impl From<Mutability> for RawPtrKind {
200+
fn from(other: Mutability) -> Self {
201+
match other {
202+
Mutability::Mut => RawPtrKind::Mut,
203+
Mutability::Not => RawPtrKind::Const,
204+
}
205+
}
206+
}
207+
208+
impl RawPtrKind {
209+
pub fn is_fake(self) -> bool {
210+
match self {
211+
RawPtrKind::Mut | RawPtrKind::Const => false,
212+
RawPtrKind::FakeForPtrMetadata => true,
213+
}
214+
}
215+
216+
pub fn to_mutbl_lossy(self) -> Mutability {
217+
match self {
218+
RawPtrKind::Mut => Mutability::Mut,
219+
RawPtrKind::Const => Mutability::Not,
220+
221+
// We have no type corresponding to a fake borrow, so use
222+
// `*const` as an approximation.
223+
RawPtrKind::FakeForPtrMetadata => Mutability::Not,
224+
}
225+
}
226+
227+
pub fn ptr_str(self) -> &'static str {
228+
match self {
229+
RawPtrKind::Mut => "mut",
230+
RawPtrKind::Const => "const",
231+
RawPtrKind::FakeForPtrMetadata => "const (fake)",
232+
}
233+
}
234+
}
235+
183236
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
184237
#[derive(Hash, HashStable)]
185238
pub enum MutBorrowKind {
@@ -1356,7 +1409,7 @@ pub enum Rvalue<'tcx> {
13561409
///
13571410
/// Like with references, the semantics of this operation are heavily dependent on the aliasing
13581411
/// model.
1359-
RawPtr(Mutability, Place<'tcx>),
1412+
RawPtr(RawPtrKind, Place<'tcx>),
13601413

13611414
/// Yields the length of the place, as a `usize`.
13621415
///

compiler/rustc_middle/src/mir/tcx.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,9 @@ impl<'tcx> Rvalue<'tcx> {
206206
let place_ty = place.ty(local_decls, tcx).ty;
207207
Ty::new_ref(tcx, reg, place_ty, bk.to_mutbl_lossy())
208208
}
209-
Rvalue::RawPtr(mutability, ref place) => {
209+
Rvalue::RawPtr(kind, ref place) => {
210210
let place_ty = place.ty(local_decls, tcx).ty;
211-
Ty::new_ptr(tcx, place_ty, mutability)
211+
Ty::new_ptr(tcx, place_ty, kind.to_mutbl_lossy())
212212
}
213213
Rvalue::Len(..) => tcx.types.usize,
214214
Rvalue::Cast(.., ty) => ty,

compiler/rustc_middle/src/mir/type_foldable.rs

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ TrivialTypeTraversalImpls! {
1515
SourceScopeLocalData,
1616
UserTypeAnnotationIndex,
1717
BorrowKind,
18+
RawPtrKind,
1819
CastKind,
1920
BasicBlock,
2021
SwitchTargets,

compiler/rustc_middle/src/mir/visit.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -685,12 +685,15 @@ macro_rules! make_mir_visitor {
685685

686686
Rvalue::RawPtr(m, path) => {
687687
let ctx = match m {
688-
Mutability::Mut => PlaceContext::MutatingUse(
688+
RawPtrKind::Mut => PlaceContext::MutatingUse(
689689
MutatingUseContext::RawBorrow
690690
),
691-
Mutability::Not => PlaceContext::NonMutatingUse(
691+
RawPtrKind::Const => PlaceContext::NonMutatingUse(
692692
NonMutatingUseContext::RawBorrow
693693
),
694+
RawPtrKind::FakeForPtrMetadata => PlaceContext::NonMutatingUse(
695+
NonMutatingUseContext::Inspect
696+
),
694697
};
695698
self.visit_place(path, ctx, location);
696699
}

compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
253253
Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
254254
),
255255
ExprKind::RawBorrow { mutability, arg } => Ok(
256-
Rvalue::RawPtr(*mutability, self.parse_place(*arg)?)
256+
Rvalue::RawPtr((*mutability).into(), self.parse_place(*arg)?)
257257
),
258258
ExprKind::Binary { op, lhs, rhs } => Ok(
259259
Rvalue::BinaryOp(*op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?)))

compiler/rustc_mir_build/src/builder/expr/as_place.rs

+71-8
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,69 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
630630
block.and(base_place.index(idx))
631631
}
632632

633+
/// Given a place that's either an array or a slice, returns an operand
634+
/// with the length of the array/slice.
635+
///
636+
/// For arrays it'll be `Operand::Constant` with the actual length;
637+
/// For slices it'll be `Operand::Move` of a local using `PtrMetadata`.
638+
fn len_of_slice_or_array(
639+
&mut self,
640+
block: BasicBlock,
641+
place: Place<'tcx>,
642+
span: Span,
643+
source_info: SourceInfo,
644+
) -> Operand<'tcx> {
645+
let place_ty = place.ty(&self.local_decls, self.tcx).ty;
646+
match place_ty.kind() {
647+
ty::Array(_elem_ty, len_const) => {
648+
// We know how long an array is, so just use that as a constant
649+
// directly -- no locals needed. We do need one statement so
650+
// that borrow- and initialization-checking consider it used,
651+
// though. FIXME: Do we really *need* to count this as a use?
652+
// Could partial array tracking work off something else instead?
653+
self.cfg.push_fake_read(block, source_info, FakeReadCause::ForIndex, place);
654+
let const_ = Const::Ty(self.tcx.types.usize, *len_const);
655+
Operand::Constant(Box::new(ConstOperand { span, user_ty: None, const_ }))
656+
}
657+
ty::Slice(_elem_ty) => {
658+
let ptr_or_ref = if let [PlaceElem::Deref] = place.projection[..]
659+
&& let local_ty = self.local_decls[place.local].ty
660+
&& local_ty.is_trivially_pure_clone_copy()
661+
{
662+
// It's extremely common that we have something that can be
663+
// directly passed to `PtrMetadata`, so avoid an unnecessary
664+
// temporary and statement in those cases. Note that we can
665+
// only do that for `Copy` types -- not `&mut [_]` -- because
666+
// the MIR we're building here needs to pass NLL later.
667+
Operand::Copy(Place::from(place.local))
668+
} else {
669+
let ptr_ty = Ty::new_imm_ptr(self.tcx, place_ty);
670+
let slice_ptr = self.temp(ptr_ty, span);
671+
self.cfg.push_assign(
672+
block,
673+
source_info,
674+
slice_ptr,
675+
Rvalue::RawPtr(RawPtrKind::FakeForPtrMetadata, place),
676+
);
677+
Operand::Move(slice_ptr)
678+
};
679+
680+
let len = self.temp(self.tcx.types.usize, span);
681+
self.cfg.push_assign(
682+
block,
683+
source_info,
684+
len,
685+
Rvalue::UnaryOp(UnOp::PtrMetadata, ptr_or_ref),
686+
);
687+
688+
Operand::Move(len)
689+
}
690+
_ => {
691+
span_bug!(span, "len called on place of type {place_ty:?}")
692+
}
693+
}
694+
}
695+
633696
fn bounds_check(
634697
&mut self,
635698
block: BasicBlock,
@@ -638,25 +701,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
638701
expr_span: Span,
639702
source_info: SourceInfo,
640703
) -> BasicBlock {
641-
let usize_ty = self.tcx.types.usize;
642-
let bool_ty = self.tcx.types.bool;
643-
// bounds check:
644-
let len = self.temp(usize_ty, expr_span);
645-
let lt = self.temp(bool_ty, expr_span);
704+
let slice = slice.to_place(self);
646705

647706
// len = len(slice)
648-
self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice.to_place(self)));
707+
let len = self.len_of_slice_or_array(block, slice, expr_span, source_info);
708+
649709
// lt = idx < len
710+
let bool_ty = self.tcx.types.bool;
711+
let lt = self.temp(bool_ty, expr_span);
650712
self.cfg.push_assign(
651713
block,
652714
source_info,
653715
lt,
654716
Rvalue::BinaryOp(
655717
BinOp::Lt,
656-
Box::new((Operand::Copy(Place::from(index)), Operand::Copy(len))),
718+
Box::new((Operand::Copy(Place::from(index)), len.to_copy())),
657719
),
658720
);
659-
let msg = BoundsCheck { len: Operand::Move(len), index: Operand::Copy(Place::from(index)) };
721+
let msg = BoundsCheck { len, index: Operand::Copy(Place::from(index)) };
722+
660723
// assert!(lt, "...")
661724
self.assert(block, Operand::Move(lt), true, msg, expr_span)
662725
}

0 commit comments

Comments
 (0)