Skip to content

Commit

Permalink
Auto merge of #97729 - Dylan-DPC:rollup-dv43xo9, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - #96642 (Avoid zero-sized allocs in ThinBox if T and H are both ZSTs.)
 - #97647 (Lazily allocate and initialize pthread locks.)
 - #97715 (Support the `#[expect]` attribute on fn parameters (RFC-2383))
 - #97716 (Fix reachability analysis for const methods)
 - #97722 (Tighten spans for bad fields in struct deriving `Copy`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jun 4, 2022
2 parents 4a52e0f + 8c4c698 commit c7b0452
Show file tree
Hide file tree
Showing 49 changed files with 614 additions and 223 deletions.
12 changes: 10 additions & 2 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,15 @@ impl<'a> AstValidator<'a> {
.iter()
.flat_map(|i| i.attrs.as_ref())
.filter(|attr| {
let arr = [sym::allow, sym::cfg, sym::cfg_attr, sym::deny, sym::forbid, sym::warn];
let arr = [
sym::allow,
sym::cfg,
sym::cfg_attr,
sym::deny,
sym::expect,
sym::forbid,
sym::warn,
];
!arr.contains(&attr.name_or_empty()) && rustc_attr::is_builtin_attr(attr)
})
.for_each(|attr| {
Expand All @@ -435,7 +443,7 @@ impl<'a> AstValidator<'a> {
} else {
self.err_handler().span_err(
attr.span,
"allow, cfg, cfg_attr, deny, \
"allow, cfg, cfg_attr, deny, expect, \
forbid, and warn are the only allowed built-in attributes in function parameters",
);
}
Expand Down
33 changes: 8 additions & 25 deletions compiler/rustc_passes/src/reachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,32 +148,15 @@ impl<'tcx> ReachableContext<'tcx> {
hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_))
| hir::TraitItemKind::Type(..) => false,
},
Some(Node::ImplItem(impl_item)) => {
match impl_item.kind {
hir::ImplItemKind::Const(..) => true,
hir::ImplItemKind::Fn(..) => {
let attrs = self.tcx.codegen_fn_attrs(def_id);
let generics = self.tcx.generics_of(def_id);
if generics.requires_monomorphization(self.tcx) || attrs.requests_inline() {
true
} else {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let impl_did = self.tcx.hir().get_parent_item(hir_id);
// Check the impl. If the generics on the self
// type of the impl require inlining, this method
// does too.
match self.tcx.hir().expect_item(impl_did).kind {
hir::ItemKind::Impl { .. } => {
let generics = self.tcx.generics_of(impl_did);
generics.requires_monomorphization(self.tcx)
}
_ => false,
}
}
}
hir::ImplItemKind::TyAlias(_) => false,
Some(Node::ImplItem(impl_item)) => match impl_item.kind {
hir::ImplItemKind::Const(..) => true,
hir::ImplItemKind::Fn(..) => {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let impl_did = self.tcx.hir().get_parent_item(hir_id);
method_might_be_inlined(self.tcx, impl_item, impl_did)
}
}
hir::ImplItemKind::TyAlias(_) => false,
},
Some(_) => false,
None => false, // This will happen for default methods.
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_trait_selection/src/traits/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub fn can_type_implement_copy<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
self_type: Ty<'tcx>,
cause: ObligationCause<'tcx>,
parent_cause: ObligationCause<'tcx>,
) -> Result<(), CopyImplementationError<'tcx>> {
// FIXME: (@jroesch) float this code up
tcx.infer_ctxt().enter(|infcx| {
Expand Down Expand Up @@ -59,7 +59,7 @@ pub fn can_type_implement_copy<'tcx>(
.ty(tcx, traits::InternalSubsts::identity_for_item(tcx, adt.did()))
.has_param_types_or_consts()
{
cause.clone()
parent_cause.clone()
} else {
ObligationCause::dummy_with_span(span)
};
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_typeck/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {

for (field, ty) in fields {
let field_span = tcx.def_span(field.did);
let field_ty_span = match tcx.hir().get_if_local(field.did) {
Some(hir::Node::Field(field_def)) => field_def.ty.span,
_ => field_span,
};
err.span_label(field_span, "this field does not implement `Copy`");
// Spin up a new FulfillmentContext, so we can get the _precise_ reason
// why this field does not implement Copy. This is useful because sometimes
Expand All @@ -119,7 +123,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
param_env,
ty,
tcx.lang_items().copy_trait().unwrap(),
traits::ObligationCause::dummy_with_span(field_span),
traits::ObligationCause::dummy_with_span(field_ty_span),
);
for error in fulfill_cx.select_all_or_error(&infcx) {
let error_predicate = error.obligation.predicate;
Expand Down
65 changes: 46 additions & 19 deletions library/alloc/src/boxed/thin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,11 @@ impl<T: ?Sized> ThinBox<T> {
}
}

/// A pointer to type-erased data, guaranteed to have a header `H` before the pointed-to location.
/// A pointer to type-erased data, guaranteed to either be:
/// 1. `NonNull::dangling()`, in the case where both the pointee (`T`) and
/// metadata (`H`) are ZSTs.
/// 2. A pointer to a valid `T` that has a header `H` directly before the
/// pointed-to location.
struct WithHeader<H>(NonNull<u8>, PhantomData<H>);

impl<H> WithHeader<H> {
Expand All @@ -156,16 +160,27 @@ impl<H> WithHeader<H> {
};

unsafe {
let ptr = alloc::alloc(layout);

if ptr.is_null() {
alloc::handle_alloc_error(layout);
}
// Safety:
// - The size is at least `aligned_header_size`.
let ptr = ptr.add(value_offset) as *mut _;

let ptr = NonNull::new_unchecked(ptr);
// Note: It's UB to pass a layout with a zero size to `alloc::alloc`, so
// we use `layout.dangling()` for this case, which should have a valid
// alignment for both `T` and `H`.
let ptr = if layout.size() == 0 {
// Some paranoia checking, mostly so that the ThinBox tests are
// more able to catch issues.
debug_assert!(
value_offset == 0 && mem::size_of::<T>() == 0 && mem::size_of::<H>() == 0
);
layout.dangling()
} else {
let ptr = alloc::alloc(layout);
if ptr.is_null() {
alloc::handle_alloc_error(layout);
}
// Safety:
// - The size is at least `aligned_header_size`.
let ptr = ptr.add(value_offset) as *mut _;

NonNull::new_unchecked(ptr)
};

let result = WithHeader(ptr, PhantomData);
ptr::write(result.header(), header);
Expand All @@ -175,18 +190,28 @@ impl<H> WithHeader<H> {
}
}

// Safety:
// - Assumes that `value` can be dereferenced.
// Safety:
// - Assumes that either `value` can be dereferenced, or is the
// `NonNull::dangling()` we use when both `T` and `H` are ZSTs.
unsafe fn drop<T: ?Sized>(&self, value: *mut T) {
unsafe {
let value_layout = Layout::for_value_raw(value);
// SAFETY: Layout must have been computable if we're in drop
let (layout, value_offset) =
Self::alloc_layout(Layout::for_value_raw(value)).unwrap_unchecked();
let (layout, value_offset) = Self::alloc_layout(value_layout).unwrap_unchecked();

ptr::drop_in_place::<T>(value);
// We only drop the value because the Pointee trait requires that the metadata is copy
// aka trivially droppable
alloc::dealloc(self.0.as_ptr().sub(value_offset), layout);
// aka trivially droppable.
ptr::drop_in_place::<T>(value);

// Note: Don't deallocate if the layout size is zero, because the pointer
// didn't come from the allocator.
if layout.size() != 0 {
alloc::dealloc(self.0.as_ptr().sub(value_offset), layout);
} else {
debug_assert!(
value_offset == 0 && mem::size_of::<H>() == 0 && value_layout.size() == 0
);
}
}
}

Expand All @@ -198,7 +223,9 @@ impl<H> WithHeader<H> {
// needed to align the header. Subtracting the header size from the aligned data pointer
// will always result in an aligned header pointer, it just may not point to the
// beginning of the allocation.
unsafe { self.0.as_ptr().sub(Self::header_size()) as *mut H }
let hp = unsafe { self.0.as_ptr().sub(Self::header_size()) as *mut H };
debug_assert!(hp.is_aligned());
hp
}

fn value(&self) -> *mut u8 {
Expand Down
1 change: 1 addition & 0 deletions library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@
#![feature(nll)] // Not necessary, but here to test the `nll` feature.
#![feature(rustc_allow_const_fn_unstable)]
#![feature(rustc_attrs)]
#![feature(pointer_is_aligned)]
#![feature(slice_internals)]
#![feature(staged_api)]
#![feature(stmt_expr_attributes)]
Expand Down
3 changes: 3 additions & 0 deletions library/alloc/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
#![feature(panic_update_hook)]
#![feature(slice_flatten)]
#![feature(thin_box)]
#![feature(bench_black_box)]
#![feature(strict_provenance)]
#![feature(once_cell)]

use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
Expand Down
Loading

0 comments on commit c7b0452

Please sign in to comment.