Skip to content

Commit 1b41093

Browse files
committed
Auto merge of rust-lang#93390 - matthiaskrgr:rollup-4xeki5w, r=matthiaskrgr
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
2 parents 21b4a9c + 0eb6753 commit 1b41093

File tree

22 files changed

+322
-180
lines changed

22 files changed

+322
-180
lines changed

compiler/rustc_arena/src/lib.rs

+40-21
Original file line numberDiff line numberDiff line change
@@ -45,24 +45,24 @@ pub struct TypedArena<T> {
4545
end: Cell<*mut T>,
4646

4747
/// A vector of arena chunks.
48-
chunks: RefCell<Vec<TypedArenaChunk<T>>>,
48+
chunks: RefCell<Vec<ArenaChunk<T>>>,
4949

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

55-
struct TypedArenaChunk<T> {
55+
struct ArenaChunk<T = u8> {
5656
/// The raw storage for the arena chunk.
5757
storage: Box<[MaybeUninit<T>]>,
5858
/// The number of valid entries in the chunk.
5959
entries: usize,
6060
}
6161

62-
impl<T> TypedArenaChunk<T> {
62+
impl<T> ArenaChunk<T> {
6363
#[inline]
64-
unsafe fn new(capacity: usize) -> TypedArenaChunk<T> {
65-
TypedArenaChunk { storage: Box::new_uninit_slice(capacity), entries: 0 }
64+
unsafe fn new(capacity: usize) -> ArenaChunk<T> {
65+
ArenaChunk { storage: Box::new_uninit_slice(capacity), entries: 0 }
6666
}
6767

6868
/// Destroys this arena chunk.
@@ -125,6 +125,11 @@ impl<I, T> IterExt<T> for I
125125
where
126126
I: IntoIterator<Item = T>,
127127
{
128+
// This default collects into a `SmallVec` and then allocates by copying
129+
// from it. The specializations below for types like `Vec` are more
130+
// efficient, copying directly without the intermediate collecting step.
131+
// This default could be made more efficient, like
132+
// `DroplessArena::alloc_from_iter`, but it's not hot enough to bother.
128133
#[inline]
129134
default fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T] {
130135
let vec: SmallVec<[_; 8]> = self.into_iter().collect();
@@ -139,7 +144,7 @@ impl<T, const N: usize> IterExt<T> for std::array::IntoIter<T, N> {
139144
if len == 0 {
140145
return &mut [];
141146
}
142-
// Move the content to the arena by copying and then forgetting it
147+
// Move the content to the arena by copying and then forgetting it.
143148
unsafe {
144149
let start_ptr = arena.alloc_raw_slice(len);
145150
self.as_slice().as_ptr().copy_to_nonoverlapping(start_ptr, len);
@@ -156,7 +161,7 @@ impl<T> IterExt<T> for Vec<T> {
156161
if len == 0 {
157162
return &mut [];
158163
}
159-
// Move the content to the arena by copying and then forgetting it
164+
// Move the content to the arena by copying and then forgetting it.
160165
unsafe {
161166
let start_ptr = arena.alloc_raw_slice(len);
162167
self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
@@ -173,7 +178,7 @@ impl<A: smallvec::Array> IterExt<A::Item> for SmallVec<A> {
173178
if len == 0 {
174179
return &mut [];
175180
}
176-
// Move the content to the arena by copying and then forgetting it
181+
// Move the content to the arena by copying and then forgetting it.
177182
unsafe {
178183
let start_ptr = arena.alloc_raw_slice(len);
179184
self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
@@ -272,7 +277,7 @@ impl<T> TypedArena<T> {
272277
// Also ensure that this chunk can fit `additional`.
273278
new_cap = cmp::max(additional, new_cap);
274279

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

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

342347
/// A vector of arena chunks.
343-
chunks: RefCell<Vec<TypedArenaChunk<u8>>>,
348+
chunks: RefCell<Vec<ArenaChunk>>,
344349
}
345350

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

381-
let mut chunk = TypedArenaChunk::<u8>::new(new_cap);
386+
let mut chunk = ArenaChunk::new(new_cap);
382387
self.start.set(chunk.start());
383388
self.end.set(chunk.end());
384389
chunks.push(chunk);
@@ -520,10 +525,19 @@ impl DroplessArena {
520525
}
521526
}
522527

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

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

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

582596
impl<'tcx> Arena<'tcx> {
583597
#[inline]
584-
pub fn alloc<T: ArenaAllocatable<'tcx, U>, U>(&self, value: T) -> &mut T {
598+
pub fn alloc<T: ArenaAllocatable<'tcx, C>, C>(&self, value: T) -> &mut T {
585599
value.allocate_on(self)
586600
}
587601

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

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

620+
// Marker types that let us give different behaviour for arenas allocating
621+
// `Copy` types vs `!Copy` types.
622+
pub struct IsCopy;
623+
pub struct IsNotCopy;
624+
606625
#[cfg(test)]
607626
mod tests;

compiler/rustc_ast_pretty/src/pprust/state.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
607607
&mut self,
608608
macro_def: &ast::MacroDef,
609609
ident: &Ident,
610-
sp: &Span,
610+
sp: Span,
611611
print_visibility: impl FnOnce(&mut Self),
612612
) {
613613
let (kw, has_bang) = if macro_def.macro_rules {
@@ -623,7 +623,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
623623
macro_def.body.delim(),
624624
&macro_def.body.inner_tokens(),
625625
true,
626-
*sp,
626+
sp,
627627
);
628628
if macro_def.body.need_semicolon() {
629629
self.word(";");

compiler/rustc_ast_pretty/src/pprust/state/item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ impl<'a> State<'a> {
347347
}
348348
}
349349
ast::ItemKind::MacroDef(ref macro_def) => {
350-
self.print_mac_def(macro_def, &item.ident, &item.span, |state| {
350+
self.print_mac_def(macro_def, &item.ident, item.span, |state| {
351351
state.print_visibility(&item.vis)
352352
});
353353
}

compiler/rustc_data_structures/src/stable_hasher/tests.rs

+42
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,45 @@ fn test_hash_bit_matrix() {
9898
assert_ne!(a, b);
9999
assert_ne!(hash(&a), hash(&b));
100100
}
101+
102+
// Check that exchanging the value of two adjacent fields changes the hash.
103+
#[test]
104+
fn test_attribute_permutation() {
105+
macro_rules! test_type {
106+
($ty: ty) => {{
107+
struct Foo {
108+
a: $ty,
109+
b: $ty,
110+
}
111+
112+
impl<CTX> HashStable<CTX> for Foo {
113+
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
114+
self.a.hash_stable(hcx, hasher);
115+
self.b.hash_stable(hcx, hasher);
116+
}
117+
}
118+
119+
#[allow(overflowing_literals)]
120+
let mut item = Foo { a: 0xFF, b: 0xFF_FF };
121+
let hash_a = hash(&item);
122+
std::mem::swap(&mut item.a, &mut item.b);
123+
let hash_b = hash(&item);
124+
assert_ne!(
125+
hash_a,
126+
hash_b,
127+
"The hash stayed the same after values were swapped for type `{}`!",
128+
stringify!($ty)
129+
);
130+
}};
131+
}
132+
133+
test_type!(u16);
134+
test_type!(u32);
135+
test_type!(u64);
136+
test_type!(u128);
137+
138+
test_type!(i16);
139+
test_type!(i32);
140+
test_type!(i64);
141+
test_type!(i128);
142+
}

compiler/rustc_feature/src/builtin_attrs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
625625
),
626626
rustc_attr!(
627627
rustc_pass_by_value, Normal,
628-
template!(Word), WarnFollowing,
628+
template!(Word), ErrorFollowing,
629629
"#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference."
630630
),
631631
BuiltinAttribute {

compiler/rustc_hir_pretty/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ impl<'a> State<'a> {
571571
self.ann.nested(self, Nested::Body(body));
572572
}
573573
hir::ItemKind::Macro(ref macro_def) => {
574-
self.print_mac_def(macro_def, &item.ident, &item.span, |state| {
574+
self.print_mac_def(macro_def, &item.ident, item.span, |state| {
575575
state.print_visibility(&item.vis)
576576
});
577577
}

compiler/rustc_lint/src/internal.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
108108
lint.build(&format!("usage of qualified `ty::{}`", t))
109109
.span_suggestion(
110110
path.span,
111-
"try using it unqualified",
111+
"try importing it and using it unqualified",
112112
t,
113113
// The import probably needs to be changed
114114
Applicability::MaybeIncorrect,

compiler/rustc_lint/src/non_fmt_panic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -336,5 +336,5 @@ fn is_arg_inside_call(arg: Span, call: Span) -> bool {
336336
// panic call in the source file, to avoid invalid suggestions when macros are involved.
337337
// We specifically check for the spans to not be identical, as that happens sometimes when
338338
// proc_macros lie about spans and apply the same span to all the tokens they produce.
339-
call.contains(arg) && !call.source_equal(&arg)
339+
call.contains(arg) && !call.source_equal(arg)
340340
}

compiler/rustc_lint/src/pass_by_value.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String {
7676
.map(|arg| match arg {
7777
GenericArg::Lifetime(lt) => lt.name.ident().to_string(),
7878
GenericArg::Type(ty) => {
79-
cx.tcx.sess.source_map().span_to_snippet(ty.span).unwrap_or_default()
79+
cx.tcx.sess.source_map().span_to_snippet(ty.span).unwrap_or_else(|_| "_".into())
8080
}
8181
GenericArg::Const(c) => {
82-
cx.tcx.sess.source_map().span_to_snippet(c.span).unwrap_or_default()
82+
cx.tcx.sess.source_map().span_to_snippet(c.span).unwrap_or_else(|_| "_".into())
8383
}
8484
GenericArg::Infer(_) => String::from("_"),
8585
})

compiler/rustc_middle/src/mir/spanview.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ where
230230
}
231231

232232
/// Format a string showing the start line and column, and end line and column within a file.
233-
pub fn source_range_no_file<'tcx>(tcx: TyCtxt<'tcx>, span: &Span) -> String {
233+
pub fn source_range_no_file<'tcx>(tcx: TyCtxt<'tcx>, span: Span) -> String {
234234
let source_map = tcx.sess.source_map();
235235
let start = source_map.lookup_char_pos(span.lo());
236236
let end = source_map.lookup_char_pos(span.hi());
@@ -629,7 +629,7 @@ fn tooltip<'tcx>(
629629
let mut text = Vec::new();
630630
text.push(format!("{}: {}:", spanview_id, &source_map.span_to_embeddable_string(span)));
631631
for statement in statements {
632-
let source_range = source_range_no_file(tcx, &statement.source_info.span);
632+
let source_range = source_range_no_file(tcx, statement.source_info.span);
633633
text.push(format!(
634634
"\n{}{}: {}: {:?}",
635635
TOOLTIP_INDENT,
@@ -639,7 +639,7 @@ fn tooltip<'tcx>(
639639
));
640640
}
641641
if let Some(term) = terminator {
642-
let source_range = source_range_no_file(tcx, &term.source_info.span);
642+
let source_range = source_range_no_file(tcx, term.source_info.span);
643643
text.push(format!(
644644
"\n{}{}: {}: {:?}",
645645
TOOLTIP_INDENT,

compiler/rustc_mir_transform/src/coverage/spans.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl CoverageStatement {
2828
let stmt = &mir_body[bb].statements[stmt_index];
2929
format!(
3030
"{}: @{}[{}]: {:?}",
31-
source_range_no_file(tcx, &span),
31+
source_range_no_file(tcx, span),
3232
bb.index(),
3333
stmt_index,
3434
stmt
@@ -38,7 +38,7 @@ impl CoverageStatement {
3838
let term = mir_body[bb].terminator();
3939
format!(
4040
"{}: @{}.{}: {:?}",
41-
source_range_no_file(tcx, &span),
41+
source_range_no_file(tcx, span),
4242
bb.index(),
4343
term_type(&term.kind),
4444
term.kind
@@ -155,7 +155,7 @@ impl CoverageSpan {
155155
pub fn format<'tcx>(&self, tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>) -> String {
156156
format!(
157157
"{}\n {}",
158-
source_range_no_file(tcx, &self.span),
158+
source_range_no_file(tcx, self.span),
159159
self.format_coverage_statements(tcx, mir_body).replace('\n', "\n "),
160160
)
161161
}

compiler/rustc_parse/src/parser/item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ impl<'a> Parser<'a> {
423423
// Maybe the user misspelled `macro_rules` (issue #91227)
424424
if self.token.is_ident()
425425
&& path.segments.len() == 1
426-
&& lev_distance("macro_rules", &path.segments[0].ident.to_string()) <= 3
426+
&& lev_distance("macro_rules", &path.segments[0].ident.to_string(), 3).is_some()
427427
{
428428
err.span_suggestion(
429429
path.span,

0 commit comments

Comments
 (0)