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 #98883

Closed
wants to merge 18 commits into from
Closed
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
369555c
Implement `FusedIterator` for `std::net::[Into]Incoming`
ChayimFriedman2 May 23, 2022
b884797
Clarify MIR semantics of checked binary operations
tmiasko Jun 30, 2022
b8213bb
Enable raw-dylib for binaries
dpaoliello Jul 1, 2022
a368830
Improve spans for specialization error
compiler-errors Jul 1, 2022
76c0429
Bump std::net::Incoming FusedIterator impl to Rust 1.64
dtolnay Jul 2, 2022
583d61f
adjust dangling-int-ptr error message
RalfJung Jul 3, 2022
7fc7780
fix interpreter validity check on Box
RalfJung Jul 3, 2022
d7edf66
move Box mess handling into general visitor
RalfJung Jul 4, 2022
658b7f3
more `rustc_pass_by_value`
lcnr Jul 4, 2022
eef5630
Fix wrap parenthesis suggestion for async closure
compiler-errors Jul 4, 2022
2acf859
Rollup merge of #97300 - ChayimFriedman2:patch-1, r=dtolnay
JohnTitor Jul 4, 2022
cf0557c
Rollup merge of #98738 - tmiasko:checked-binop, r=oli-obk
JohnTitor Jul 4, 2022
6aace7f
Rollup merge of #98778 - dpaoliello:rawdylibbin, r=michaelwoerister
JohnTitor Jul 4, 2022
0fe8ac3
Rollup merge of #98782 - compiler-errors:specialization-error-span, r…
JohnTitor Jul 4, 2022
392fbde
Rollup merge of #98847 - RalfJung:box-is-special, r=oli-obk
JohnTitor Jul 4, 2022
cf4ff4e
Rollup merge of #98860 - RalfJung:dangling-int-ptr, r=davidtwco
JohnTitor Jul 4, 2022
c9857bf
Rollup merge of #98878 - lcnr:more-rustc_pass_by_value, r=oli-obk
JohnTitor Jul 4, 2022
fc9b5de
Rollup merge of #98879 - compiler-errors:async-closure-wrap-parens, r…
JohnTitor Jul 4, 2022
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
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/constraint_generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
fn visit_ascribe_user_ty(
&mut self,
_place: &Place<'tcx>,
_variance: &ty::Variance,
_variance: ty::Variance,
_user_ty: &UserTypeProjection,
_location: Location,
) {
Expand Down
8 changes: 3 additions & 5 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2212,7 +2212,9 @@ fn add_local_native_libraries(
NativeLibKind::Dylib { as_needed } => {
cmd.link_dylib(name, verbatim, as_needed.unwrap_or(true))
}
NativeLibKind::Unspecified => cmd.link_dylib(name, verbatim, true),
NativeLibKind::RawDylib | NativeLibKind::Unspecified => {
cmd.link_dylib(name, verbatim, true)
}
NativeLibKind::Framework { as_needed } => {
cmd.link_framework(name, as_needed.unwrap_or(true))
}
Expand All @@ -2233,10 +2235,6 @@ fn add_local_native_libraries(
cmd.link_staticlib(name, verbatim)
}
}
NativeLibKind::RawDylib => {
// FIXME(#58713): Proper handling for raw dylibs.
bug!("raw_dylib feature not yet implemented");
}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/interpret/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
_ecx: &InterpCx<$mir, $tcx, Self>,
addr: u64,
) -> Pointer<Option<AllocId>> {
Pointer::new(None, Size::from_bytes(addr))
Pointer::from_addr(addr)
}

#[inline(always)]
Expand All @@ -523,7 +523,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
) -> InterpResult<$tcx, Pointer<Option<AllocId>>> {
// Allow these casts, but make the pointer not dereferenceable.
// (I.e., they behave like transmutation.)
Ok(Pointer::new(None, Size::from_bytes(addr)))
Ok(Pointer::from_addr(addr))
}

#[inline(always)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ impl<'tcx, Tag: Provenance> MPlaceTy<'tcx, Tag> {
#[inline]
pub fn dangling(layout: TyAndLayout<'tcx>) -> Self {
let align = layout.align.abi;
let ptr = Pointer::new(None, Size::from_bytes(align.bytes())); // no provenance, absolute address
let ptr = Pointer::from_addr(align.bytes()); // no provenance, absolute address
// `Poison` this to make sure that the pointer value `ptr` is never observable by the program.
MPlaceTy { mplace: MemPlace { ptr, align, meta: MemPlaceMeta::Poison }, layout }
}
Expand Down
18 changes: 6 additions & 12 deletions compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,16 +593,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
self.check_safe_pointer(value, "reference")?;
Ok(true)
}
ty::Adt(def, ..) if def.is_box() => {
let unique = self.ecx.operand_field(value, 0)?;
let nonnull = self.ecx.operand_field(&unique, 0)?;
let ptr = self.ecx.operand_field(&nonnull, 0)?;
self.check_safe_pointer(&ptr, "box")?;

// Check other fields of Box
self.walk_value(value)?;
Ok(true)
}
ty::FnPtr(_sig) => {
let value = try_validation!(
self.ecx.read_scalar(value).and_then(|v| v.check_init()),
Expand Down Expand Up @@ -813,6 +803,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
Ok(())
}

#[inline]
fn visit_box(&mut self, op: &OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
self.check_safe_pointer(op, "box")?;
Ok(())
}

#[inline]
fn visit_value(&mut self, op: &OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
trace!("visit_value: {:?}, {:?}", *op, op.layout);
Expand All @@ -821,8 +817,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
if self.try_visit_primitive(op)? {
return Ok(());
}
// Sanity check: `builtin_deref` does not know any pointers that are not primitive.
assert!(op.layout.ty.builtin_deref(true).is_none());

// Special check preventing `UnsafeCell` in the inner part of constants
if let Some(def) = op.layout.ty.ty_adt_def() {
Expand Down
49 changes: 49 additions & 0 deletions compiler/rustc_const_eval/src/interpret/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,14 @@ macro_rules! make_value_visitor {
{
Ok(())
}
/// Visits the given value as the pointer of a `Box`. There is nothing to recurse into.
/// The type of `v` will be a raw pointer, but this is a field of `Box<T>` and the
/// pointee type is the actual `T`.
#[inline(always)]
fn visit_box(&mut self, _v: &Self::V) -> InterpResult<'tcx>
{
Ok(())
}
/// Visits this value as an aggregate, you are getting an iterator yielding
/// all the fields (still in an `InterpResult`, you have to do error handling yourself).
/// Recurses into the fields.
Expand Down Expand Up @@ -221,6 +229,47 @@ macro_rules! make_value_visitor {
// Slices do not need special handling here: they have `Array` field
// placement with length 0, so we enter the `Array` case below which
// indirectly uses the metadata to determine the actual length.

// However, `Box`... let's talk about `Box`.
ty::Adt(def, ..) if def.is_box() => {
// `Box` is a hybrid primitive-library-defined type that one the one hand is
// a dereferenceable pointer, on the other hand has *basically arbitrary
// user-defined layout* since the user controls the 'allocator' field. So it
// cannot be treated like a normal pointer, since it does not fit into an
// `Immediate`. Yeah, it is quite terrible. But many visitors want to do
// something with "all boxed pointers", so we handle this mess for them.
//
// When we hit a `Box`, we do not do the usual `visit_aggregate`; instead,
// we (a) call `visit_box` on the pointer value, and (b) recurse on the
// allocator field. We also assert tons of things to ensure we do not miss
// any other fields.

// `Box` has two fields: the pointer we care about, and the allocator.
assert_eq!(v.layout().fields.count(), 2, "`Box` must have exactly 2 fields");
let (unique_ptr, alloc) =
(v.project_field(self.ecx(), 0)?, v.project_field(self.ecx(), 1)?);
// Unfortunately there is some type junk in the way here: `unique_ptr` is a `Unique`...
// (which means another 2 fields, the second of which is a `PhantomData`)
assert_eq!(unique_ptr.layout().fields.count(), 2);
let (nonnull_ptr, phantom) = (
unique_ptr.project_field(self.ecx(), 0)?,
unique_ptr.project_field(self.ecx(), 1)?,
);
assert!(
phantom.layout().ty.ty_adt_def().is_some_and(|adt| adt.is_phantom_data()),
"2nd field of `Unique` should be PhantomData but is {:?}",
phantom.layout().ty,
);
// ... that contains a `NonNull`... (gladly, only a single field here)
assert_eq!(nonnull_ptr.layout().fields.count(), 1);
let raw_ptr = nonnull_ptr.project_field(self.ecx(), 0)?; // the actual raw ptr
// ... whose only field finally is a raw ptr we can dereference.
self.visit_box(&raw_ptr)?;

// The second `Box` field is the allocator, which we recursively check for validity
// like in regular structs.
self.visit_field(v, 1, &alloc)?;
}
_ => {},
};

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Rust MIR: a lowered representation of Rust.
#![feature(trusted_step)]
#![feature(try_blocks)]
#![feature(yeet_expr)]
#![feature(is_some_with)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]

Expand Down
18 changes: 8 additions & 10 deletions compiler/rustc_middle/src/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,17 +186,17 @@ pub enum CheckInAllocMsg {

impl fmt::Display for CheckInAllocMsg {
/// When this is printed as an error the context looks like this:
/// "{msg}0x01 is not a valid pointer".
/// "{msg}{pointer} is a dangling pointer".
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match *self {
CheckInAllocMsg::DerefTest => "dereferencing pointer failed: ",
CheckInAllocMsg::MemoryAccessTest => "memory access failed: ",
CheckInAllocMsg::PointerArithmeticTest => "pointer arithmetic failed: ",
CheckInAllocMsg::PointerArithmeticTest => "out-of-bounds pointer arithmetic: ",
CheckInAllocMsg::OffsetFromTest => "out-of-bounds offset_from: ",
CheckInAllocMsg::InboundsTest => "",
CheckInAllocMsg::InboundsTest => "out-of-bounds pointer use: ",
}
)
}
Expand Down Expand Up @@ -356,14 +356,12 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
ptr_size_p = pluralize!(ptr_size.bytes()),
ptr_offset = ptr_offset,
),
DanglingIntPointer(0, CheckInAllocMsg::InboundsTest) => {
write!(f, "null pointer is not a valid pointer for this operation")
}
DanglingIntPointer(0, msg) => {
write!(f, "{}null pointer is not a valid pointer", msg)
}
DanglingIntPointer(i, msg) => {
write!(f, "{}0x{:x} is not a valid pointer", msg, i)
write!(
f,
"{msg}{pointer} is a dangling pointer (it has no provenance)",
pointer = Pointer::<Option<AllocId>>::from_addr(*i),
)
}
AlignmentCheckFailed { required, has } => write!(
f,
Expand Down
19 changes: 17 additions & 2 deletions compiler/rustc_middle/src/mir/interpret/pointer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,17 @@ impl<Tag: Provenance> fmt::Debug for Pointer<Option<Tag>> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.provenance {
Some(tag) => Provenance::fmt(&Pointer::new(tag, self.offset), f),
None => write!(f, "0x{:x}", self.offset.bytes()),
None => write!(f, "0x{:x}[noalloc]", self.offset.bytes()),
}
}
}

impl<Tag: Provenance> fmt::Display for Pointer<Option<Tag>> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.provenance.is_none() && self.offset.bytes() == 0 {
write!(f, "null pointer")
} else {
fmt::Debug::fmt(self, f)
}
}
}
Expand Down Expand Up @@ -226,9 +236,14 @@ impl<Tag> Pointer<Option<Tag>> {
}

impl<Tag> Pointer<Option<Tag>> {
#[inline(always)]
pub fn from_addr(addr: u64) -> Self {
Pointer { provenance: None, offset: Size::from_bytes(addr) }
}

#[inline(always)]
pub fn null() -> Self {
Pointer { provenance: None, offset: Size::ZERO }
Pointer::from_addr(0)
}
}

Expand Down
17 changes: 13 additions & 4 deletions compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ pub enum StatementKind<'tcx> {

/// Describes what kind of retag is to be performed.
#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value]
pub enum RetagKind {
/// The initial retag when entering a function.
FnEntry,
Expand Down Expand Up @@ -990,11 +991,19 @@ pub enum Rvalue<'tcx> {
/// matching types and return a value of that type.
BinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),

/// Same as `BinaryOp`, but yields `(T, bool)` instead of `T`. In addition to performing the
/// same computation as the matching `BinaryOp`, checks if the infinite precison result would be
/// unequal to the actual result and sets the `bool` if this is the case.
/// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition.
///
/// This only supports addition, subtraction, multiplication, and shift operations on integers.
/// When overflow checking is disabled, the error condition is false. Otherwise, the error
/// condition is determined as described below.
///
/// For addition, subtraction, and multiplication on integers the error condition is set when
/// the infinite precision result would be unequal to the actual result.
///
/// For shift operations on integers the error condition is set when the value of right-hand
/// side is greater than or equal to the number of bits in the type of the left-hand side, or
/// when the value of right-hand side is negative.
///
/// Other combinations of types and operators are unsupported.
CheckedBinaryOp(BinOp, Box<(Operand<'tcx>, Operand<'tcx>)>),

/// Computes a value as described by the operation.
Expand Down
25 changes: 12 additions & 13 deletions compiler/rustc_middle/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ macro_rules! make_mir_visitor {
fn visit_ascribe_user_ty(
&mut self,
place: & $($mutability)? Place<'tcx>,
variance: & $($mutability)? ty::Variance,
variance: $(& $mutability)? ty::Variance,
user_ty: & $($mutability)? UserTypeProjection,
location: Location,
) {
Expand All @@ -164,7 +164,7 @@ macro_rules! make_mir_visitor {

fn visit_retag(
&mut self,
kind: & $($mutability)? RetagKind,
kind: $(& $mutability)? RetagKind,
place: & $($mutability)? Place<'tcx>,
location: Location,
) {
Expand Down Expand Up @@ -425,7 +425,7 @@ macro_rules! make_mir_visitor {
self.visit_source_info(source_info);
match kind {
StatementKind::Assign(
box(ref $($mutability)? place, ref $($mutability)? rvalue)
box (place, rvalue)
) => {
self.visit_assign(place, rvalue, location);
}
Expand Down Expand Up @@ -465,13 +465,13 @@ macro_rules! make_mir_visitor {
);
}
StatementKind::Retag(kind, place) => {
self.visit_retag(kind, place, location);
self.visit_retag($(& $mutability)? *kind, place, location);
}
StatementKind::AscribeUserType(
box(ref $($mutability)? place, ref $($mutability)? user_ty),
box (place, user_ty),
variance
) => {
self.visit_ascribe_user_ty(place, variance, user_ty, location);
self.visit_ascribe_user_ty(place, $(& $mutability)? *variance, user_ty, location);
}
StatementKind::Coverage(coverage) => {
self.visit_coverage(
Expand All @@ -480,9 +480,9 @@ macro_rules! make_mir_visitor {
)
}
StatementKind::CopyNonOverlapping(box crate::mir::CopyNonOverlapping{
ref $($mutability)? src,
ref $($mutability)? dst,
ref $($mutability)? count,
src,
dst,
count,
}) => {
self.visit_operand(src, location);
self.visit_operand(dst, location);
Expand Down Expand Up @@ -517,8 +517,7 @@ macro_rules! make_mir_visitor {
TerminatorKind::GeneratorDrop |
TerminatorKind::Unreachable |
TerminatorKind::FalseEdge { .. } |
TerminatorKind::FalseUnwind { .. } => {
}
TerminatorKind::FalseUnwind { .. } => {}

TerminatorKind::Return => {
// `return` logically moves from the return place `_0`. Note that the place
Expand Down Expand Up @@ -830,7 +829,7 @@ macro_rules! make_mir_visitor {

fn super_ascribe_user_ty(&mut self,
place: & $($mutability)? Place<'tcx>,
_variance: & $($mutability)? ty::Variance,
_variance: $(& $mutability)? ty::Variance,
user_ty: & $($mutability)? UserTypeProjection,
location: Location) {
self.visit_place(
Expand All @@ -847,7 +846,7 @@ macro_rules! make_mir_visitor {
}

fn super_retag(&mut self,
_kind: & $($mutability)? RetagKind,
_kind: $(& $mutability)? RetagKind,
place: & $($mutability)? Place<'tcx>,
location: Location) {
self.visit_place(
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_type_ir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,7 @@ impl UnifyKey for FloatVid {
}

#[derive(Copy, Clone, PartialEq, Decodable, Encodable, Hash)]
#[rustc_pass_by_value]
pub enum Variance {
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell
Expand Down
Loading