1
Fork 0

Auto merge of #114553 - matthiaskrgr:rollup-5yddunv, r=matthiaskrgr

Rollup of 5 pull requests

Successful merges:

 - #114466 (Add Allocation to SMIR)
 - #114505 (Add documentation to has_deref)
 - #114519 (use offset_of! to calculate dirent64 field offsets)
 - #114537 (Migrate GUI colors test to original CSS color format)
 - #114539 (linkchecker: Remove unneeded FIXME about intra-doc links)

Failed merges:

 - #114485 (Add trait decls to SMIR)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-08-06 19:46:31 +00:00
commit 85fbb57149
13 changed files with 82 additions and 46 deletions

View file

@ -441,7 +441,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
LocalRef::Place(place) => place, LocalRef::Place(place) => place,
LocalRef::UnsizedPlace(place) => bx.load_operand(place).deref(cx), LocalRef::UnsizedPlace(place) => bx.load_operand(place).deref(cx),
LocalRef::Operand(..) => { LocalRef::Operand(..) => {
if place_ref.has_deref() { if place_ref.is_indirect_first_projection() {
base = 1; base = 1;
let cg_base = self.codegen_consume( let cg_base = self.codegen_consume(
bx, bx,

View file

@ -247,7 +247,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
AddressOf(_, place) => { AddressOf(_, place) => {
// Figure out whether this is an addr_of of an already raw place. // Figure out whether this is an addr_of of an already raw place.
let place_base_raw = if place.has_deref() { let place_base_raw = if place.is_indirect_first_projection() {
let ty = self.frame().body.local_decls[place.local].ty; let ty = self.frame().body.local_decls[place.local].ty;
ty.is_unsafe_ptr() ty.is_unsafe_ptr()
} else { } else {

View file

@ -1592,14 +1592,13 @@ impl<'tcx> Place<'tcx> {
self.projection.iter().any(|elem| elem.is_indirect()) self.projection.iter().any(|elem| elem.is_indirect())
} }
/// If MirPhase >= Derefered and if projection contains Deref, /// Returns `true` if this `Place`'s first projection is `Deref`.
/// It's guaranteed to be in the first place ///
pub fn has_deref(&self) -> bool { /// This is useful because for MIR phases `AnalysisPhase::PostCleanup` and later,
// To make sure this is not accidentally used in wrong mir phase /// `Deref` projections can only occur as the first projection. In that case this method
debug_assert!( /// is equivalent to `is_indirect`, but faster.
self.projection.is_empty() || !self.projection[1..].contains(&PlaceElem::Deref) pub fn is_indirect_first_projection(&self) -> bool {
); self.as_ref().is_indirect_first_projection()
self.projection.first() == Some(&PlaceElem::Deref)
} }
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
@ -1672,9 +1671,16 @@ impl<'tcx> PlaceRef<'tcx> {
self.projection.iter().any(|elem| elem.is_indirect()) self.projection.iter().any(|elem| elem.is_indirect())
} }
/// If MirPhase >= Derefered and if projection contains Deref, /// Returns `true` if this `Place`'s first projection is `Deref`.
/// It's guaranteed to be in the first place ///
pub fn has_deref(&self) -> bool { /// This is useful because for MIR phases `AnalysisPhase::PostCleanup` and later,
/// `Deref` projections can only occur as the first projection. In that case this method
/// is equivalent to `is_indirect`, but faster.
pub fn is_indirect_first_projection(&self) -> bool {
// To make sure this is not accidentally used in wrong mir phase
debug_assert!(
self.projection.is_empty() || !self.projection[1..].contains(&PlaceElem::Deref)
);
self.projection.first() == Some(&PlaceElem::Deref) self.projection.first() == Some(&PlaceElem::Deref)
} }

View file

@ -839,7 +839,7 @@ impl Map {
tail_elem: Option<TrackElem>, tail_elem: Option<TrackElem>,
f: &mut impl FnMut(ValueIndex), f: &mut impl FnMut(ValueIndex),
) { ) {
if place.has_deref() { if place.is_indirect_first_projection() {
// We do not track indirect places. // We do not track indirect places.
return; return;
} }

View file

@ -60,7 +60,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
let basic_blocks = body.basic_blocks.as_mut(); let basic_blocks = body.basic_blocks.as_mut();
let local_decls = &body.local_decls; let local_decls = &body.local_decls;
let needs_retag = |place: &Place<'tcx>| { let needs_retag = |place: &Place<'tcx>| {
!place.has_deref() // we're not really interested in stores to "outside" locations, they are hard to keep track of anyway !place.is_indirect_first_projection() // we're not really interested in stores to "outside" locations, they are hard to keep track of anyway
&& may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx) && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx)
&& !local_decls[place.local].is_deref_temp() && !local_decls[place.local].is_deref_temp()
}; };

View file

@ -154,7 +154,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) { fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) {
if let Operand::Move(place) = *operand if let Operand::Move(place) = *operand
// A move out of a projection of a copy is equivalent to a copy of the original projection. // A move out of a projection of a copy is equivalent to a copy of the original projection.
&& !place.has_deref() && !place.is_indirect_first_projection()
&& !self.fully_moved.contains(place.local) && !self.fully_moved.contains(place.local)
{ {
*operand = Operand::Copy(place); *operand = Operand::Copy(place);

View file

@ -1063,3 +1063,34 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::BoundTy {
BoundTy { var: self.var.as_usize(), kind: self.kind.stable(tables) } BoundTy { var: self.var.as_usize(), kind: self.kind.stable(tables) }
} }
} }
impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
type T = stable_mir::ty::Allocation;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
let size = self.size();
let mut bytes: Vec<Option<u8>> = self
.inspect_with_uninit_and_ptr_outside_interpreter(0..size.bytes_usize())
.iter()
.copied()
.map(Some)
.collect();
for (i, b) in bytes.iter_mut().enumerate() {
if !self.init_mask().get(rustc_target::abi::Size::from_bytes(i)) {
*b = None;
}
}
stable_mir::ty::Allocation {
bytes: bytes,
provenance: {
let mut ptrs = Vec::new();
for (size, prov) in self.provenance().ptrs().iter() {
ptrs.push((size.bytes_usize(), opaque(prov)));
}
stable_mir::ty::ProvenanceMap { ptrs }
},
align: self.align.bytes(),
mutability: self.mutability.stable(tables),
}
}
}

View file

@ -242,3 +242,25 @@ pub struct BoundTy {
pub var: usize, pub var: usize,
pub kind: BoundTyKind, pub kind: BoundTyKind,
} }
pub type Bytes = Vec<Option<u8>>;
pub type Size = usize;
pub type Prov = Opaque;
pub type Align = u64;
pub type InitMaskMaterialized = Vec<u64>;
/// Stores the provenance information of pointers stored in memory.
#[derive(Clone, Debug)]
pub struct ProvenanceMap {
/// Provenance in this map applies from the given offset for an entire pointer-size worth of
/// bytes. Two entries in this map are always at least a pointer size apart.
pub ptrs: Vec<(Size, Prov)>,
}
#[derive(Clone, Debug)]
pub struct Allocation {
pub bytes: Bytes,
pub provenance: ProvenanceMap,
pub align: Align,
pub mutability: Mutability,
}

View file

@ -298,6 +298,7 @@
#![feature(maybe_uninit_slice)] #![feature(maybe_uninit_slice)]
#![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_uninit_array)]
#![feature(maybe_uninit_write_slice)] #![feature(maybe_uninit_write_slice)]
#![feature(offset_of)]
#![feature(panic_can_unwind)] #![feature(panic_can_unwind)]
#![feature(panic_info_message)] #![feature(panic_info_message)]
#![feature(panic_internals)] #![feature(panic_internals)]

View file

@ -7,17 +7,6 @@ use crate::ffi::{CStr, OsStr, OsString};
use crate::fmt; use crate::fmt;
use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom}; use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom};
use crate::mem; use crate::mem;
#[cfg(any(
target_os = "android",
target_os = "linux",
target_os = "solaris",
target_os = "fuchsia",
target_os = "redox",
target_os = "illumos",
target_os = "nto",
target_os = "vita",
))]
use crate::mem::MaybeUninit;
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd};
use crate::path::{Path, PathBuf}; use crate::path::{Path, PathBuf};
use crate::ptr; use crate::ptr;
@ -712,22 +701,10 @@ impl Iterator for ReadDir {
// requires the full extent of *entry_ptr to be in bounds of the same // requires the full extent of *entry_ptr to be in bounds of the same
// allocation, which is not necessarily the case here. // allocation, which is not necessarily the case here.
// //
// Absent any other way to obtain a pointer to `(*entry_ptr).d_name` // Instead we must access fields individually through their offsets.
// legally in Rust analogously to how it would be done in C, we instead
// need to make our own non-libc allocation that conforms to the weird
// imaginary definition of dirent64, and use that for a field offset
// computation.
macro_rules! offset_ptr { macro_rules! offset_ptr {
($entry_ptr:expr, $field:ident) => {{ ($entry_ptr:expr, $field:ident) => {{
const OFFSET: isize = { const OFFSET: isize = mem::offset_of!(dirent64, $field) as isize;
let delusion = MaybeUninit::<dirent64>::uninit();
let entry_ptr = delusion.as_ptr();
unsafe {
ptr::addr_of!((*entry_ptr).$field)
.cast::<u8>()
.offset_from(entry_ptr.cast::<u8>())
}
};
if true { if true {
// Cast to the same type determined by the else branch. // Cast to the same type determined by the else branch.
$entry_ptr.byte_offset(OFFSET).cast::<_>() $entry_ptr.byte_offset(OFFSET).cast::<_>()

View file

@ -1170,7 +1170,7 @@ fn referent_used_exactly_once<'tcx>(
&& let [location] = *local_assignments(mir, local).as_slice() && let [location] = *local_assignments(mir, local).as_slice()
&& let Some(statement) = mir.basic_blocks[location.block].statements.get(location.statement_index) && let Some(statement) = mir.basic_blocks[location.block].statements.get(location.statement_index)
&& let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind && let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind
&& !place.has_deref() && !place.is_indirect_first_projection()
// Ensure not in a loop (https://github.com/rust-lang/rust-clippy/issues/9710) // Ensure not in a loop (https://github.com/rust-lang/rust-clippy/issues/9710)
&& TriColorDepthFirstSearch::new(&mir.basic_blocks).run_from(location.block, &mut CycleDetector).is_none() && TriColorDepthFirstSearch::new(&mir.basic_blocks).run_from(location.block, &mut CycleDetector).is_none()
{ {

View file

@ -368,7 +368,6 @@ impl Checker {
return; return;
} }
// Search for intra-doc links that rustdoc didn't warn about // Search for intra-doc links that rustdoc didn't warn about
// FIXME(#77199, 77200) Rustdoc should just warn about these directly.
// NOTE: only looks at one line at a time; in practice this should find most links // NOTE: only looks at one line at a time; in practice this should find most links
for (i, line) in source.lines().enumerate() { for (i, line) in source.lines().enumerate() {
for broken_link in BROKEN_INTRA_DOC_LINK.captures_iter(line) { for broken_link in BROKEN_INTRA_DOC_LINK.captures_iter(line) {

View file

@ -20,20 +20,20 @@ call-function: (
"check-colors", "check-colors",
{ {
"theme": "ayu", "theme": "ayu",
"error_background": "rgb(79, 76, 76)", "error_background": "#4f4c4c",
}, },
) )
call-function: ( call-function: (
"check-colors", "check-colors",
{ {
"theme": "dark", "theme": "dark",
"error_background": "rgb(72, 72, 72)", "error_background": "#484848",
}, },
) )
call-function: ( call-function: (
"check-colors", "check-colors",
{ {
"theme": "light", "theme": "light",
"error_background": "rgb(208, 204, 204)", "error_background": "#d0cccc",
}, },
) )