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

Merged
merged 23 commits into from
Jan 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
db5a2ae
Define c_char using cfg_if rather than repeating 40-line cfg
dtolnay Dec 7, 2021
4e8b91a
Work around Clippy false positive on `as c_char`
dtolnay Dec 8, 2021
1ffd043
Add test stable hash uniqueness of adjacent field values
Kobzol Jan 22, 2022
0c17893
Rename `TypedArenaChunk` as `ArenaChunk`.
nnethercote Jan 25, 2022
f93bd00
Hoist `to_uppercase` out of the loop
tmiasko Jan 17, 2022
380d53f
Check namespace before computing the Levenshtein distance
tmiasko Jan 17, 2022
6236882
Introduce a limit to Levenshtein distance computation
tmiasko Jan 20, 2022
f5cdfb4
rustdoc: add test case for multiple traits and erased names
notriddle Jan 26, 2022
696d503
Clarify the `usage-of-qualified-ty` error message.
nnethercote Jan 27, 2022
f27758e
mention std::iter::zip in Iterator::zip docs
cameron1024 Jan 27, 2022
e680838
update pass_by_value
lcnr Jan 27, 2022
2684dfe
try apply `rustc_pass_by_value` to `Span`
lcnr Jan 27, 2022
9065c7c
Add some comments.
nnethercote Jan 25, 2022
6035487
Clarify `ArenaAllocatable`'s second parameter.
nnethercote Jan 25, 2022
857ea1e
Touch up PR 92899 Iterator::zip docs
dtolnay Jan 27, 2022
4af3930
Rollup merge of #91641 - dtolnay:cchar-if, r=Mark-Simulacrum
matthiaskrgr Jan 27, 2022
54f3578
Rollup merge of #92899 - cameron1024:zip-docs, r=dtolnay
matthiaskrgr Jan 27, 2022
bc26f97
Rollup merge of #93193 - Kobzol:stable-hash-permutation-test, r=the8472
matthiaskrgr Jan 27, 2022
6caa533
Rollup merge of #93325 - tmiasko:lev, r=davidtwco
matthiaskrgr Jan 27, 2022
b232c46
Rollup merge of #93339 - notriddle:notriddle/test-generics-multi-trai…
matthiaskrgr Jan 27, 2022
5d79874
Rollup merge of #93357 - nnethercote:clarify-usage-of-qualified-ty, r…
matthiaskrgr Jan 27, 2022
8347f78
Rollup merge of #93363 - lcnr:pass-by-value, r=petrochenkov
matthiaskrgr Jan 27, 2022
0eb6753
Rollup merge of #93365 - nnethercote:more-arena-cleanups, r=oli-obk
matthiaskrgr Jan 27, 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
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