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

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
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
eb80407
suggest `#[derive(Default)]` to enums with `#[default]`
TaKO8Ki Jul 4, 2022
4e65d39
Rollup merge of #97300 - ChayimFriedman2:patch-1, r=dtolnay
Dylan-DPC Jul 4, 2022
9ed515f
Rollup merge of #98738 - tmiasko:checked-binop, r=oli-obk
Dylan-DPC Jul 4, 2022
829a718
Rollup merge of #98778 - dpaoliello:rawdylibbin, r=michaelwoerister
Dylan-DPC Jul 4, 2022
2ab4de7
Rollup merge of #98782 - compiler-errors:specialization-error-span, r…
Dylan-DPC Jul 4, 2022
7f27201
Rollup merge of #98847 - RalfJung:box-is-special, r=oli-obk
Dylan-DPC Jul 4, 2022
250f636
Rollup merge of #98873 - TaKO8Ki:suggest-default-derive-to-enum-with-…
Dylan-DPC Jul 4, 2022
bff8a2c
Rollup merge of #98878 - lcnr:more-rustc_pass_by_value, r=oli-obk
Dylan-DPC Jul 4, 2022
484fa44
Rollup merge of #98879 - compiler-errors:async-closure-wrap-parens, r…
Dylan-DPC 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
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
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
9 changes: 9 additions & 0 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1495,6 +1495,15 @@ impl<'a> Resolver<'a> {
err.help("have you added the `#[macro_use]` on the module/import?");
return;
}
if ident.name == kw::Default
&& let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind
&& let Some(span) = self.opt_span(def_id)
{
err.span_help(
self.session.source_map().guess_head_span(span),
"consider adding `#[derive(Default)]` to this enum",
);
}
for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
if let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
ident,
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
27 changes: 24 additions & 3 deletions compiler/rustc_typeck/src/check/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,15 +280,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
callee_node: &hir::ExprKind<'_>,
callee_span: Span,
) {
let hir_id = self.tcx.hir().get_parent_node(hir_id);
let parent_node = self.tcx.hir().get(hir_id);
let hir = self.tcx.hir();
let parent_hir_id = hir.get_parent_node(hir_id);
let parent_node = hir.get(parent_hir_id);
if let (
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure { fn_decl_span, .. }, ..
kind: hir::ExprKind::Closure { fn_decl_span, body, .. },
..
}),
hir::ExprKind::Block(..),
) = (parent_node, callee_node)
{
let fn_decl_span = if hir.body(*body).generator_kind
== Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure))
{
// Actually need to unwrap a few more layers of HIR to get to
// the _real_ closure...
let async_closure = hir.get_parent_node(hir.get_parent_node(parent_hir_id));
if let hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure { fn_decl_span, .. },
..
}) = hir.get(async_closure)
{
*fn_decl_span
} else {
return;
}
} else {
*fn_decl_span
};

let start = fn_decl_span.shrink_to_lo();
let end = callee_span.shrink_to_hi();
err.multipart_suggestion(
Expand Down
27 changes: 20 additions & 7 deletions compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,11 +279,16 @@ fn check_predicates<'tcx>(
span: Span,
) {
let tcx = infcx.tcx;
let impl1_predicates: Vec<_> = traits::elaborate_predicates(
let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span(
tcx,
tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).predicates.into_iter(),
std::iter::zip(
instantiated.predicates,
// Don't drop predicates (unsound!) because `spans` is too short
instantiated.spans.into_iter().chain(std::iter::repeat(span)),
),
)
.map(|obligation| obligation.predicate)
.map(|obligation| (obligation.predicate, obligation.cause.span))
.collect();

let mut impl2_predicates = if impl2_node.is_from_trait() {
Expand Down Expand Up @@ -321,7 +326,7 @@ fn check_predicates<'tcx>(
// which is sound because we forbid impls like the following
//
// impl<D: Debug> AlwaysApplicable for D { }
let always_applicable_traits = impl1_predicates.iter().copied().filter(|&predicate| {
let always_applicable_traits = impl1_predicates.iter().copied().filter(|&(predicate, _)| {
matches!(
trait_predicate_kind(tcx, predicate),
Some(TraitSpecializationKind::AlwaysApplicable)
Expand All @@ -345,11 +350,11 @@ fn check_predicates<'tcx>(
}
}
impl2_predicates.extend(
traits::elaborate_predicates(tcx, always_applicable_traits)
traits::elaborate_predicates_with_span(tcx, always_applicable_traits)
.map(|obligation| obligation.predicate),
);

for predicate in impl1_predicates {
for (predicate, span) in impl1_predicates {
if !impl2_predicates.contains(&predicate) {
check_specialization_on(tcx, predicate, span)
}
Expand Down Expand Up @@ -384,9 +389,17 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
.emit();
}
}
ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
tcx.sess
.struct_span_err(
span,
&format!("cannot specialize on associated type `{projection_ty} == {term}`",),
)
.emit();
}
_ => {
tcx.sess
.struct_span_err(span, &format!("cannot specialize on `{:?}`", predicate))
.struct_span_err(span, &format!("cannot specialize on predicate `{}`", predicate))
.emit();
}
}
Expand Down
Loading