Skip to content

Commit

Permalink
Auto merge of rust-lang#93390 - matthiaskrgr:rollup-4xeki5w, r=matthi…
Browse files Browse the repository at this point in the history
…askrgr

Rollup of 8 pull requests

Successful merges:

 - rust-lang#91641 (Define c_char using cfg_if rather than repeating 40-line cfg)
 - rust-lang#92899 (Mention std::iter::zip in Iterator::zip docs)
 - rust-lang#93193 (Add test for stable hash uniqueness of adjacent field values)
 - rust-lang#93325 (Introduce a limit to Levenshtein distance computation)
 - rust-lang#93339 (rustdoc: add test case for multiple traits and erased names)
 - rust-lang#93357 (Clarify the `usage-of-qualified-ty` error message.)
 - rust-lang#93363 (`#[rustc_pass_by_value]` cleanup)
 - rust-lang#93365 (More arena cleanups)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jan 27, 2022
2 parents 21b4a9c + 0eb6753 commit 1b41093
Show file tree
Hide file tree
Showing 22 changed files with 322 additions and 180 deletions.
61 changes: 40 additions & 21 deletions compiler/rustc_arena/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,24 @@ pub struct TypedArena<T> {
end: Cell<*mut T>,

/// A vector of arena chunks.
chunks: RefCell<Vec<TypedArenaChunk<T>>>,
chunks: RefCell<Vec<ArenaChunk<T>>>,

/// Marker indicating that dropping the arena causes its owned
/// instances of `T` to be dropped.
_own: PhantomData<T>,
}

struct TypedArenaChunk<T> {
struct ArenaChunk<T = u8> {
/// The raw storage for the arena chunk.
storage: Box<[MaybeUninit<T>]>,
/// The number of valid entries in the chunk.
entries: usize,
}

impl<T> TypedArenaChunk<T> {
impl<T> ArenaChunk<T> {
#[inline]
unsafe fn new(capacity: usize) -> TypedArenaChunk<T> {
TypedArenaChunk { storage: Box::new_uninit_slice(capacity), entries: 0 }
unsafe fn new(capacity: usize) -> ArenaChunk<T> {
ArenaChunk { storage: Box::new_uninit_slice(capacity), entries: 0 }
}

/// Destroys this arena chunk.
Expand Down Expand Up @@ -125,6 +125,11 @@ impl<I, T> IterExt<T> for I
where
I: IntoIterator<Item = T>,
{
// This default collects into a `SmallVec` and then allocates by copying
// from it. The specializations below for types like `Vec` are more
// efficient, copying directly without the intermediate collecting step.
// This default could be made more efficient, like
// `DroplessArena::alloc_from_iter`, but it's not hot enough to bother.
#[inline]
default fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T] {
let vec: SmallVec<[_; 8]> = self.into_iter().collect();
Expand All @@ -139,7 +144,7 @@ impl<T, const N: usize> IterExt<T> for std::array::IntoIter<T, N> {
if len == 0 {
return &mut [];
}
// Move the content to the arena by copying and then forgetting it
// Move the content to the arena by copying and then forgetting it.
unsafe {
let start_ptr = arena.alloc_raw_slice(len);
self.as_slice().as_ptr().copy_to_nonoverlapping(start_ptr, len);
Expand All @@ -156,7 +161,7 @@ impl<T> IterExt<T> for Vec<T> {
if len == 0 {
return &mut [];
}
// Move the content to the arena by copying and then forgetting it
// Move the content to the arena by copying and then forgetting it.
unsafe {
let start_ptr = arena.alloc_raw_slice(len);
self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
Expand All @@ -173,7 +178,7 @@ impl<A: smallvec::Array> IterExt<A::Item> for SmallVec<A> {
if len == 0 {
return &mut [];
}
// Move the content to the arena by copying and then forgetting it
// Move the content to the arena by copying and then forgetting it.
unsafe {
let start_ptr = arena.alloc_raw_slice(len);
self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
Expand Down Expand Up @@ -272,7 +277,7 @@ impl<T> TypedArena<T> {
// Also ensure that this chunk can fit `additional`.
new_cap = cmp::max(additional, new_cap);

let mut chunk = TypedArenaChunk::<T>::new(new_cap);
let mut chunk = ArenaChunk::<T>::new(new_cap);
self.ptr.set(chunk.start());
self.end.set(chunk.end());
chunks.push(chunk);
Expand All @@ -281,7 +286,7 @@ impl<T> TypedArena<T> {

// Drops the contents of the last chunk. The last chunk is partially empty, unlike all other
// chunks.
fn clear_last_chunk(&self, last_chunk: &mut TypedArenaChunk<T>) {
fn clear_last_chunk(&self, last_chunk: &mut ArenaChunk<T>) {
// Determine how much was filled.
let start = last_chunk.start() as usize;
// We obtain the value of the pointer to the first uninitialized element.
Expand Down Expand Up @@ -340,7 +345,7 @@ pub struct DroplessArena {
end: Cell<*mut u8>,

/// A vector of arena chunks.
chunks: RefCell<Vec<TypedArenaChunk<u8>>>,
chunks: RefCell<Vec<ArenaChunk>>,
}

unsafe impl Send for DroplessArena {}
Expand Down Expand Up @@ -378,7 +383,7 @@ impl DroplessArena {
// Also ensure that this chunk can fit `additional`.
new_cap = cmp::max(additional, new_cap);

let mut chunk = TypedArenaChunk::<u8>::new(new_cap);
let mut chunk = ArenaChunk::new(new_cap);
self.start.set(chunk.start());
self.end.set(chunk.end());
chunks.push(chunk);
Expand Down Expand Up @@ -520,10 +525,19 @@ impl DroplessArena {
}
}

// Declare an `Arena` containing one dropless arena and many typed arenas (the
// types of the typed arenas are specified by the arguments). The dropless
// arena will be used for any types that impl `Copy`, and also for any of the
// specified types that satisfy `!mem::needs_drop`.
/// Declare an `Arena` containing one dropless arena and many typed arenas (the
/// types of the typed arenas are specified by the arguments).
///
/// There are three cases of interest.
/// - Types that are `Copy`: these need not be specified in the arguments. They
/// will use the `DroplessArena`.
/// - Types that are `!Copy` and `!Drop`: these must be specified in the
/// arguments. An empty `TypedArena` will be created for each one, but the
/// `DroplessArena` will always be used and the `TypedArena` will stay empty.
/// This is odd but harmless, because an empty arena allocates no memory.
/// - Types that are `!Copy` and `Drop`: these must be specified in the
/// arguments. The `TypedArena` will be used for them.
///
#[rustc_macro_transparency = "semitransparent"]
pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
#[derive(Default)]
Expand All @@ -532,7 +546,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
$($name: $crate::TypedArena<$ty>,)*
}

pub trait ArenaAllocatable<'tcx, T = Self>: Sized {
pub trait ArenaAllocatable<'tcx, C = rustc_arena::IsNotCopy>: Sized {
fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self;
fn allocate_from_iter<'a>(
arena: &'a Arena<'tcx>,
Expand All @@ -541,7 +555,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
}

// Any type that impls `Copy` can be arena-allocated in the `DroplessArena`.
impl<'tcx, T: Copy> ArenaAllocatable<'tcx, ()> for T {
impl<'tcx, T: Copy> ArenaAllocatable<'tcx, rustc_arena::IsCopy> for T {
#[inline]
fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self {
arena.dropless.alloc(self)
Expand All @@ -555,7 +569,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
}
}
$(
impl<'tcx> ArenaAllocatable<'tcx, $ty> for $ty {
impl<'tcx> ArenaAllocatable<'tcx, rustc_arena::IsNotCopy> for $ty {
#[inline]
fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self {
if !::std::mem::needs_drop::<Self>() {
Expand All @@ -581,7 +595,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {

impl<'tcx> Arena<'tcx> {
#[inline]
pub fn alloc<T: ArenaAllocatable<'tcx, U>, U>(&self, value: T) -> &mut T {
pub fn alloc<T: ArenaAllocatable<'tcx, C>, C>(&self, value: T) -> &mut T {
value.allocate_on(self)
}

Expand All @@ -594,7 +608,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
self.dropless.alloc_slice(value)
}

pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, U>, U>(
pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, C>, C>(
&'a self,
iter: impl ::std::iter::IntoIterator<Item = T>,
) -> &'a mut [T] {
Expand All @@ -603,5 +617,10 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
}
}

// Marker types that let us give different behaviour for arenas allocating
// `Copy` types vs `!Copy` types.
pub struct IsCopy;
pub struct IsNotCopy;

#[cfg(test)]
mod tests;
4 changes: 2 additions & 2 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
&mut self,
macro_def: &ast::MacroDef,
ident: &Ident,
sp: &Span,
sp: Span,
print_visibility: impl FnOnce(&mut Self),
) {
let (kw, has_bang) = if macro_def.macro_rules {
Expand All @@ -623,7 +623,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
macro_def.body.delim(),
&macro_def.body.inner_tokens(),
true,
*sp,
sp,
);
if macro_def.body.need_semicolon() {
self.word(";");
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ impl<'a> State<'a> {
}
}
ast::ItemKind::MacroDef(ref macro_def) => {
self.print_mac_def(macro_def, &item.ident, &item.span, |state| {
self.print_mac_def(macro_def, &item.ident, item.span, |state| {
state.print_visibility(&item.vis)
});
}
Expand Down
42 changes: 42 additions & 0 deletions compiler/rustc_data_structures/src/stable_hasher/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,45 @@ fn test_hash_bit_matrix() {
assert_ne!(a, b);
assert_ne!(hash(&a), hash(&b));
}

// Check that exchanging the value of two adjacent fields changes the hash.
#[test]
fn test_attribute_permutation() {
macro_rules! test_type {
($ty: ty) => {{
struct Foo {
a: $ty,
b: $ty,
}

impl<CTX> HashStable<CTX> for Foo {
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
self.a.hash_stable(hcx, hasher);
self.b.hash_stable(hcx, hasher);
}
}

#[allow(overflowing_literals)]
let mut item = Foo { a: 0xFF, b: 0xFF_FF };
let hash_a = hash(&item);
std::mem::swap(&mut item.a, &mut item.b);
let hash_b = hash(&item);
assert_ne!(
hash_a,
hash_b,
"The hash stayed the same after values were swapped for type `{}`!",
stringify!($ty)
);
}};
}

test_type!(u16);
test_type!(u32);
test_type!(u64);
test_type!(u128);

test_type!(i16);
test_type!(i32);
test_type!(i64);
test_type!(i128);
}
2 changes: 1 addition & 1 deletion compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
),
rustc_attr!(
rustc_pass_by_value, Normal,
template!(Word), WarnFollowing,
template!(Word), ErrorFollowing,
"#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference."
),
BuiltinAttribute {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ impl<'a> State<'a> {
self.ann.nested(self, Nested::Body(body));
}
hir::ItemKind::Macro(ref macro_def) => {
self.print_mac_def(macro_def, &item.ident, &item.span, |state| {
self.print_mac_def(macro_def, &item.ident, item.span, |state| {
state.print_visibility(&item.vis)
});
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
lint.build(&format!("usage of qualified `ty::{}`", t))
.span_suggestion(
path.span,
"try using it unqualified",
"try importing it and using it unqualified",
t,
// The import probably needs to be changed
Applicability::MaybeIncorrect,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/non_fmt_panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,5 +336,5 @@ fn is_arg_inside_call(arg: Span, call: Span) -> bool {
// panic call in the source file, to avoid invalid suggestions when macros are involved.
// We specifically check for the spans to not be identical, as that happens sometimes when
// proc_macros lie about spans and apply the same span to all the tokens they produce.
call.contains(arg) && !call.source_equal(&arg)
call.contains(arg) && !call.source_equal(arg)
}
4 changes: 2 additions & 2 deletions compiler/rustc_lint/src/pass_by_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String {
.map(|arg| match arg {
GenericArg::Lifetime(lt) => lt.name.ident().to_string(),
GenericArg::Type(ty) => {
cx.tcx.sess.source_map().span_to_snippet(ty.span).unwrap_or_default()
cx.tcx.sess.source_map().span_to_snippet(ty.span).unwrap_or_else(|_| "_".into())
}
GenericArg::Const(c) => {
cx.tcx.sess.source_map().span_to_snippet(c.span).unwrap_or_default()
cx.tcx.sess.source_map().span_to_snippet(c.span).unwrap_or_else(|_| "_".into())
}
GenericArg::Infer(_) => String::from("_"),
})
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/mir/spanview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ where
}

/// Format a string showing the start line and column, and end line and column within a file.
pub fn source_range_no_file<'tcx>(tcx: TyCtxt<'tcx>, span: &Span) -> String {
pub fn source_range_no_file<'tcx>(tcx: TyCtxt<'tcx>, span: Span) -> String {
let source_map = tcx.sess.source_map();
let start = source_map.lookup_char_pos(span.lo());
let end = source_map.lookup_char_pos(span.hi());
Expand Down Expand Up @@ -629,7 +629,7 @@ fn tooltip<'tcx>(
let mut text = Vec::new();
text.push(format!("{}: {}:", spanview_id, &source_map.span_to_embeddable_string(span)));
for statement in statements {
let source_range = source_range_no_file(tcx, &statement.source_info.span);
let source_range = source_range_no_file(tcx, statement.source_info.span);
text.push(format!(
"\n{}{}: {}: {:?}",
TOOLTIP_INDENT,
Expand All @@ -639,7 +639,7 @@ fn tooltip<'tcx>(
));
}
if let Some(term) = terminator {
let source_range = source_range_no_file(tcx, &term.source_info.span);
let source_range = source_range_no_file(tcx, term.source_info.span);
text.push(format!(
"\n{}{}: {}: {:?}",
TOOLTIP_INDENT,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_mir_transform/src/coverage/spans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl CoverageStatement {
let stmt = &mir_body[bb].statements[stmt_index];
format!(
"{}: @{}[{}]: {:?}",
source_range_no_file(tcx, &span),
source_range_no_file(tcx, span),
bb.index(),
stmt_index,
stmt
Expand All @@ -38,7 +38,7 @@ impl CoverageStatement {
let term = mir_body[bb].terminator();
format!(
"{}: @{}.{}: {:?}",
source_range_no_file(tcx, &span),
source_range_no_file(tcx, span),
bb.index(),
term_type(&term.kind),
term.kind
Expand Down Expand Up @@ -155,7 +155,7 @@ impl CoverageSpan {
pub fn format<'tcx>(&self, tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>) -> String {
format!(
"{}\n {}",
source_range_no_file(tcx, &self.span),
source_range_no_file(tcx, self.span),
self.format_coverage_statements(tcx, mir_body).replace('\n', "\n "),
)
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ impl<'a> Parser<'a> {
// Maybe the user misspelled `macro_rules` (issue #91227)
if self.token.is_ident()
&& path.segments.len() == 1
&& lev_distance("macro_rules", &path.segments[0].ident.to_string()) <= 3
&& lev_distance("macro_rules", &path.segments[0].ident.to_string(), 3).is_some()
{
err.span_suggestion(
path.span,
Expand Down
Loading

0 comments on commit 1b41093

Please sign in to comment.