Skip to content

Commit f6a28aa

Browse files
committed
Auto merge of rust-lang#85720 - Dylan-DPC:rollup-in5917x, r=Dylan-DPC
Rollup of 8 pull requests Successful merges: - rust-lang#85478 (Disallow shadowing const parameters) - rust-lang#85625 (Prevent double drop in `Vec::dedup_by` if a destructor panics) - rust-lang#85627 (Fix a few details in THIR unsafeck) - rust-lang#85633 (Post-monomorphization errors traces MVP) - rust-lang#85670 (Remove arrays/IntoIterator message from Iterator trait.) - rust-lang#85678 (fix `matches!` and `assert_matches!` on edition 2021) - rust-lang#85679 (Remove num_as_ne_bytes feature) - rust-lang#85712 (Fix typo in core::array::IntoIter comment) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 1969c2e + 9ee87c7 commit f6a28aa

27 files changed

+444
-201
lines changed

compiler/rustc_middle/src/mir/mono.rs

+9
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,15 @@ impl<'tcx> MonoItem<'tcx> {
186186
pub fn codegen_dep_node(&self, tcx: TyCtxt<'tcx>) -> DepNode {
187187
crate::dep_graph::make_compile_mono_item(tcx, self)
188188
}
189+
190+
/// Returns the item's `CrateNum`
191+
pub fn krate(&self) -> CrateNum {
192+
match self {
193+
MonoItem::Fn(ref instance) => instance.def_id().krate,
194+
MonoItem::Static(def_id) => def_id.krate,
195+
MonoItem::GlobalAsm(..) => LOCAL_CRATE,
196+
}
197+
}
189198
}
190199

191200
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for MonoItem<'tcx> {

compiler/rustc_mir/src/monomorphize/collector.rs

+44-2
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
184184
use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
185185
use rustc_errors::{ErrorReported, FatalError};
186186
use rustc_hir as hir;
187-
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
187+
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
188188
use rustc_hir::itemlikevisit::ItemLikeVisitor;
189189
use rustc_hir::lang_items::LangItem;
190190
use rustc_index::bit_set::GrowableBitSet;
@@ -342,7 +342,8 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
342342
.collect()
343343
}
344344

345-
// Collect all monomorphized items reachable from `starting_point`
345+
/// Collect all monomorphized items reachable from `starting_point`, and emit a note diagnostic if a
346+
/// post-monorphization error is encountered during a collection step.
346347
fn collect_items_rec<'tcx>(
347348
tcx: TyCtxt<'tcx>,
348349
starting_point: Spanned<MonoItem<'tcx>>,
@@ -359,6 +360,31 @@ fn collect_items_rec<'tcx>(
359360
let mut neighbors = Vec::new();
360361
let recursion_depth_reset;
361362

363+
//
364+
// Post-monomorphization errors MVP
365+
//
366+
// We can encounter errors while monomorphizing an item, but we don't have a good way of
367+
// showing a complete stack of spans ultimately leading to collecting the erroneous one yet.
368+
// (It's also currently unclear exactly which diagnostics and information would be interesting
369+
// to report in such cases)
370+
//
371+
// This leads to suboptimal error reporting: a post-monomorphization error (PME) will be
372+
// shown with just a spanned piece of code causing the error, without information on where
373+
// it was called from. This is especially obscure if the erroneous mono item is in a
374+
// dependency. See for example issue #85155, where, before minimization, a PME happened two
375+
// crates downstream from libcore's stdarch, without a way to know which dependency was the
376+
// cause.
377+
//
378+
// If such an error occurs in the current crate, its span will be enough to locate the
379+
// source. If the cause is in another crate, the goal here is to quickly locate which mono
380+
// item in the current crate is ultimately responsible for causing the error.
381+
//
382+
// To give at least _some_ context to the user: while collecting mono items, we check the
383+
// error count. If it has changed, a PME occurred, and we trigger some diagnostics about the
384+
// current step of mono items collection.
385+
//
386+
let error_count = tcx.sess.diagnostic().err_count();
387+
362388
match starting_point.node {
363389
MonoItem::Static(def_id) => {
364390
let instance = Instance::mono(tcx, def_id);
@@ -411,6 +437,22 @@ fn collect_items_rec<'tcx>(
411437
}
412438
}
413439

440+
// Check for PMEs and emit a diagnostic if one happened. To try to show relevant edges of the
441+
// mono item graph where the PME diagnostics are currently the most problematic (e.g. ones
442+
// involving a dependency, and the lack of context is confusing) in this MVP, we focus on
443+
// diagnostics on edges crossing a crate boundary: the collected mono items which are not
444+
// defined in the local crate.
445+
if tcx.sess.diagnostic().err_count() > error_count && starting_point.node.krate() != LOCAL_CRATE
446+
{
447+
tcx.sess.span_note_without_error(
448+
starting_point.span,
449+
&format!(
450+
"the above error was encountered while instantiating `{}`",
451+
starting_point.node
452+
),
453+
);
454+
}
455+
414456
record_accesses(tcx, starting_point.node, neighbors.iter().map(|i| &i.node), inlining_map);
415457

416458
for neighbour in neighbors {

compiler/rustc_mir_build/src/check_unsafety.rs

+25-16
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
4242
self.warn_unused_unsafe(
4343
hir_id,
4444
block_span,
45-
Some(self.tcx.sess.source_map().guess_head_span(enclosing_span)),
45+
Some((self.tcx.sess.source_map().guess_head_span(enclosing_span), "block")),
4646
);
4747
f(self);
4848
} else {
@@ -52,7 +52,15 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
5252
f(self);
5353

5454
if let SafetyContext::UnsafeBlock { used: false, span, hir_id } = self.safety_context {
55-
self.warn_unused_unsafe(hir_id, span, self.body_unsafety.unsafe_fn_sig_span());
55+
self.warn_unused_unsafe(
56+
hir_id,
57+
span,
58+
if self.unsafe_op_in_unsafe_fn_allowed() {
59+
self.body_unsafety.unsafe_fn_sig_span().map(|span| (span, "fn"))
60+
} else {
61+
None
62+
},
63+
);
5664
}
5765
self.safety_context = prev_context;
5866
return;
@@ -72,16 +80,20 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
7280
SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {}
7381
SafetyContext::UnsafeFn => {
7482
// unsafe_op_in_unsafe_fn is disallowed
75-
struct_span_err!(
76-
self.tcx.sess,
83+
self.tcx.struct_span_lint_hir(
84+
UNSAFE_OP_IN_UNSAFE_FN,
85+
self.hir_context,
7786
span,
78-
E0133,
79-
"{} is unsafe and requires unsafe block",
80-
description,
87+
|lint| {
88+
lint.build(&format!(
89+
"{} is unsafe and requires unsafe block (error E0133)",
90+
description,
91+
))
92+
.span_label(span, description)
93+
.note(note)
94+
.emit();
95+
},
8196
)
82-
.span_label(span, description)
83-
.note(note)
84-
.emit();
8597
}
8698
SafetyContext::Safe => {
8799
let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" };
@@ -104,18 +116,15 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
104116
&self,
105117
hir_id: hir::HirId,
106118
block_span: Span,
107-
enclosing_span: Option<Span>,
119+
enclosing_unsafe: Option<(Span, &'static str)>,
108120
) {
109121
let block_span = self.tcx.sess.source_map().guess_head_span(block_span);
110122
self.tcx.struct_span_lint_hir(UNUSED_UNSAFE, hir_id, block_span, |lint| {
111123
let msg = "unnecessary `unsafe` block";
112124
let mut db = lint.build(msg);
113125
db.span_label(block_span, msg);
114-
if let Some(enclosing_span) = enclosing_span {
115-
db.span_label(
116-
enclosing_span,
117-
format!("because it's nested under this `unsafe` block"),
118-
);
126+
if let Some((span, kind)) = enclosing_unsafe {
127+
db.span_label(span, format!("because it's nested under this `unsafe` {}", kind));
119128
}
120129
db.emit();
121130
});

compiler/rustc_resolve/src/diagnostics.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -425,24 +425,29 @@ impl<'a> Resolver<'a> {
425425
}
426426
err
427427
}
428-
ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => {
429-
let res = binding.res();
430-
let shadows_what = res.descr();
428+
ResolutionError::BindingShadowsSomethingUnacceptable {
429+
shadowing_binding_descr,
430+
name,
431+
participle,
432+
article,
433+
shadowed_binding_descr,
434+
shadowed_binding_span,
435+
} => {
431436
let mut err = struct_span_err!(
432437
self.session,
433438
span,
434439
E0530,
435440
"{}s cannot shadow {}s",
436-
what_binding,
437-
shadows_what
441+
shadowing_binding_descr,
442+
shadowed_binding_descr,
438443
);
439444
err.span_label(
440445
span,
441-
format!("cannot be named the same as {} {}", res.article(), shadows_what),
446+
format!("cannot be named the same as {} {}", article, shadowed_binding_descr),
442447
);
443-
let participle = if binding.is_import() { "imported" } else { "defined" };
444-
let msg = format!("the {} `{}` is {} here", shadows_what, name, participle);
445-
err.span_label(binding.span, msg);
448+
let msg =
449+
format!("the {} `{}` is {} here", shadowed_binding_descr, name, participle);
450+
err.span_label(shadowed_binding_span, msg);
446451
err
447452
}
448453
ResolutionError::ForwardDeclaredTyParam => {

compiler/rustc_resolve/src/late.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -1763,13 +1763,33 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
17631763
// to something unusable as a pattern (e.g., constructor function),
17641764
// but we still conservatively report an error, see
17651765
// issues/33118#issuecomment-233962221 for one reason why.
1766+
let binding = binding.expect("no binding for a ctor or static");
17661767
self.report_error(
17671768
ident.span,
1768-
ResolutionError::BindingShadowsSomethingUnacceptable(
1769-
pat_src.descr(),
1770-
ident.name,
1771-
binding.expect("no binding for a ctor or static"),
1772-
),
1769+
ResolutionError::BindingShadowsSomethingUnacceptable {
1770+
shadowing_binding_descr: pat_src.descr(),
1771+
name: ident.name,
1772+
participle: if binding.is_import() { "imported" } else { "defined" },
1773+
article: binding.res().article(),
1774+
shadowed_binding_descr: binding.res().descr(),
1775+
shadowed_binding_span: binding.span,
1776+
},
1777+
);
1778+
None
1779+
}
1780+
Res::Def(DefKind::ConstParam, def_id) => {
1781+
// Same as for DefKind::Const above, but here, `binding` is `None`, so we
1782+
// have to construct the error differently
1783+
self.report_error(
1784+
ident.span,
1785+
ResolutionError::BindingShadowsSomethingUnacceptable {
1786+
shadowing_binding_descr: pat_src.descr(),
1787+
name: ident.name,
1788+
participle: "defined",
1789+
article: res.article(),
1790+
shadowed_binding_descr: res.descr(),
1791+
shadowed_binding_span: self.r.opt_span(def_id).expect("const parameter defined outside of local crate"),
1792+
}
17731793
);
17741794
None
17751795
}

compiler/rustc_resolve/src/lib.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,14 @@ enum ResolutionError<'a> {
233233
/* current */ &'static str,
234234
),
235235
/// Error E0530: `X` bindings cannot shadow `Y`s.
236-
BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>),
236+
BindingShadowsSomethingUnacceptable {
237+
shadowing_binding_descr: &'static str,
238+
name: Symbol,
239+
participle: &'static str,
240+
article: &'static str,
241+
shadowed_binding_descr: &'static str,
242+
shadowed_binding_span: Span,
243+
},
237244
/// Error E0128: generic parameters with a default cannot use forward-declared identifiers.
238245
ForwardDeclaredTyParam, // FIXME(const_generics_defaults)
239246
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.

library/alloc/src/vec/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1619,6 +1619,8 @@ impl<T, A: Allocator> Vec<T, A> {
16191619
let prev_ptr = ptr.add(gap.write.wrapping_sub(1));
16201620

16211621
if same_bucket(&mut *read_ptr, &mut *prev_ptr) {
1622+
// Increase `gap.read` now since the drop may panic.
1623+
gap.read += 1;
16221624
/* We have found duplicate, drop it in-place */
16231625
ptr::drop_in_place(read_ptr);
16241626
} else {
@@ -1631,9 +1633,8 @@ impl<T, A: Allocator> Vec<T, A> {
16311633

16321634
/* We have filled that place, so go further */
16331635
gap.write += 1;
1636+
gap.read += 1;
16341637
}
1635-
1636-
gap.read += 1;
16371638
}
16381639

16391640
/* Technically we could let `gap` clean up with its Drop, but

library/alloc/tests/vec.rs

+25-23
Original file line numberDiff line numberDiff line change
@@ -2234,48 +2234,50 @@ fn test_vec_dedup() {
22342234
#[test]
22352235
fn test_vec_dedup_panicking() {
22362236
#[derive(Debug)]
2237-
struct Panic {
2238-
drop_counter: &'static AtomicU32,
2237+
struct Panic<'a> {
2238+
drop_counter: &'a Cell<u32>,
22392239
value: bool,
22402240
index: usize,
22412241
}
22422242

2243-
impl PartialEq for Panic {
2243+
impl<'a> PartialEq for Panic<'a> {
22442244
fn eq(&self, other: &Self) -> bool {
22452245
self.value == other.value
22462246
}
22472247
}
22482248

2249-
impl Drop for Panic {
2249+
impl<'a> Drop for Panic<'a> {
22502250
fn drop(&mut self) {
2251-
let x = self.drop_counter.fetch_add(1, Ordering::SeqCst);
2252-
assert!(x != 4);
2251+
self.drop_counter.set(self.drop_counter.get() + 1);
2252+
if !std::thread::panicking() {
2253+
assert!(self.index != 4);
2254+
}
22532255
}
22542256
}
22552257

2256-
static DROP_COUNTER: AtomicU32 = AtomicU32::new(0);
2258+
let drop_counter = &Cell::new(0);
22572259
let expected = [
2258-
Panic { drop_counter: &DROP_COUNTER, value: false, index: 0 },
2259-
Panic { drop_counter: &DROP_COUNTER, value: false, index: 5 },
2260-
Panic { drop_counter: &DROP_COUNTER, value: true, index: 6 },
2261-
Panic { drop_counter: &DROP_COUNTER, value: true, index: 7 },
2260+
Panic { drop_counter, value: false, index: 0 },
2261+
Panic { drop_counter, value: false, index: 5 },
2262+
Panic { drop_counter, value: true, index: 6 },
2263+
Panic { drop_counter, value: true, index: 7 },
22622264
];
22632265
let mut vec = vec![
2264-
Panic { drop_counter: &DROP_COUNTER, value: false, index: 0 },
2266+
Panic { drop_counter, value: false, index: 0 },
22652267
// these elements get deduplicated
2266-
Panic { drop_counter: &DROP_COUNTER, value: false, index: 1 },
2267-
Panic { drop_counter: &DROP_COUNTER, value: false, index: 2 },
2268-
Panic { drop_counter: &DROP_COUNTER, value: false, index: 3 },
2269-
Panic { drop_counter: &DROP_COUNTER, value: false, index: 4 },
2270-
// here it panics
2271-
Panic { drop_counter: &DROP_COUNTER, value: false, index: 5 },
2272-
Panic { drop_counter: &DROP_COUNTER, value: true, index: 6 },
2273-
Panic { drop_counter: &DROP_COUNTER, value: true, index: 7 },
2268+
Panic { drop_counter, value: false, index: 1 },
2269+
Panic { drop_counter, value: false, index: 2 },
2270+
Panic { drop_counter, value: false, index: 3 },
2271+
Panic { drop_counter, value: false, index: 4 },
2272+
// here it panics while dropping the item with index==4
2273+
Panic { drop_counter, value: false, index: 5 },
2274+
Panic { drop_counter, value: true, index: 6 },
2275+
Panic { drop_counter, value: true, index: 7 },
22742276
];
22752277

2276-
let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
2277-
vec.dedup();
2278-
}));
2278+
let _ = catch_unwind(AssertUnwindSafe(|| vec.dedup())).unwrap_err();
2279+
2280+
assert_eq!(drop_counter.get(), 4);
22792281

22802282
let ok = vec.iter().zip(expected.iter()).all(|(x, y)| x.index == y.index);
22812283

library/core/src/array/iter.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
139139
// SAFETY: Callers are only allowed to pass an index that is in bounds
140140
// Additionally Self: TrustedRandomAccess is only implemented for T: Copy which means even
141141
// multiple repeated reads of the same index would be safe and the
142-
// values aree !Drop, thus won't suffer from double drops.
142+
// values are !Drop, thus won't suffer from double drops.
143143
unsafe { self.data.get_unchecked(self.alive.start + idx).assume_init_read() }
144144
}
145145
}

library/core/src/iter/traits/iterator.rs

-5
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,6 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
7979
_Self = "std::string::String",
8080
label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
8181
),
82-
on(
83-
_Self = "[]",
84-
label = "arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)`",
85-
note = "see <https://github.com/rust-lang/rust/pull/65819> for more details"
86-
),
8782
on(
8883
_Self = "{integral}",
8984
note = "if you want to iterate between `start` until a value `end`, use the exclusive range \

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@
168168
#![feature(no_coverage)] // rust-lang/rust#84605
169169
#![feature(int_error_matching)]
170170
#![deny(unsafe_op_in_unsafe_fn)]
171+
#![deny(or_patterns_back_compat)]
171172

172173
// allow using `core::` in intra-doc links
173174
#[allow(unused_extern_crates)]

0 commit comments

Comments
 (0)