Skip to content

Commit 760ce94

Browse files
committed
Auto merge of #67874 - Dylan-DPC:rollup-xy6bkoe, r=Dylan-DPC
Rollup of 4 pull requests Successful merges: - #67137 (libstd uses `core::panic::Location` where possible.) - #67709 (Introduce an option for disabling deduplication of diagnostics) - #67775 (Make "use $crate" a hard error) - #67812 (Tweak and extend internal BTreeMap documentation, including debug asserts.) Failed merges: r? @ghost
2 parents cd8377d + 0bbe110 commit 760ce94

35 files changed

+211
-197
lines changed

src/liballoc/collections/btree/map.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
493493
BTreeMap { root: node::Root::shared_empty_root(), length: 0 }
494494
}
495495

496-
/// Clears the map, removing all values.
496+
/// Clears the map, removing all elements.
497497
///
498498
/// # Examples
499499
///
@@ -2605,7 +2605,7 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
26052605

26062606
// Handle underflow
26072607
let mut cur_node = small_leaf.forget_type();
2608-
while cur_node.len() < node::CAPACITY / 2 {
2608+
while cur_node.len() < node::MIN_LEN {
26092609
match handle_underfull_node(cur_node) {
26102610
AtRoot => break,
26112611
EmptyParent(_) => unreachable!(),

src/liballoc/collections/btree/node.rs

+37-13
Original file line numberDiff line numberDiff line change
@@ -308,15 +308,15 @@ impl<K, V> Root<K, V> {
308308
/// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the
309309
/// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
310310
/// `NodeRef` could be pointing to either type of node.
311-
/// Note that in case of a leaf node, this might still be the shared root! Only turn
312-
/// this into a `LeafNode` reference if you know it is not a root! Shared references
313-
/// must be dereferencable *for the entire size of their pointee*, so `&InternalNode`
314-
/// pointing to the shared root is UB.
315-
/// Turning this into a `NodeHeader` is always safe.
311+
/// Note that in case of a leaf node, this might still be the shared root!
312+
/// Only turn this into a `LeafNode` reference if you know it is not the shared root!
313+
/// Shared references must be dereferencable *for the entire size of their pointee*,
314+
/// so '&LeafNode` or `&InternalNode` pointing to the shared root is undefined behavior.
315+
/// Turning this into a `NodeHeader` reference is always safe.
316316
pub struct NodeRef<BorrowType, K, V, Type> {
317317
height: usize,
318318
node: NonNull<LeafNode<K, V>>,
319-
// This is null unless the borrow type is `Mut`
319+
// `root` is null unless the borrow type is `Mut`
320320
root: *const Root<K, V>,
321321
_marker: PhantomData<(BorrowType, Type)>,
322322
}
@@ -370,23 +370,33 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
370370
NodeRef { height: self.height, node: self.node, root: self.root, _marker: PhantomData }
371371
}
372372

373-
/// Assert that this is indeed a proper leaf node, and not the shared root.
373+
/// Exposes the leaf "portion" of any leaf or internal node that is not the shared root.
374+
/// If the node is a leaf, this function simply opens up its data.
375+
/// If the node is an internal node, so not a leaf, it does have all the data a leaf has
376+
/// (header, keys and values), and this function exposes that.
377+
/// See `NodeRef` on why the node may not be a shared root.
374378
unsafe fn as_leaf(&self) -> &LeafNode<K, V> {
379+
debug_assert!(!self.is_shared_root());
375380
self.node.as_ref()
376381
}
377382

378383
fn as_header(&self) -> &NodeHeader<K, V> {
379384
unsafe { &*(self.node.as_ptr() as *const NodeHeader<K, V>) }
380385
}
381386

387+
/// Returns whether the node is the shared, empty root.
382388
pub fn is_shared_root(&self) -> bool {
383389
self.as_header().is_shared_root()
384390
}
385391

392+
/// Borrows a view into the keys stored in the node.
393+
/// Works on all possible nodes, including the shared root.
386394
pub fn keys(&self) -> &[K] {
387395
self.reborrow().into_key_slice()
388396
}
389397

398+
/// Borrows a view into the values stored in the node.
399+
/// The caller must ensure that the node is not the shared root.
390400
fn vals(&self) -> &[V] {
391401
self.reborrow().into_val_slice()
392402
}
@@ -491,16 +501,24 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
491501
NodeRef { height: self.height, node: self.node, root: self.root, _marker: PhantomData }
492502
}
493503

504+
/// Exposes the leaf "portion" of any leaf or internal node for writing.
505+
/// If the node is a leaf, this function simply opens up its data.
506+
/// If the node is an internal node, so not a leaf, it does have all the data a leaf has
507+
/// (header, keys and values), and this function exposes that.
508+
///
494509
/// Returns a raw ptr to avoid asserting exclusive access to the entire node.
510+
/// This also implies you can invoke this member on the shared root, but the resulting pointer
511+
/// might not be properly aligned and definitely would not allow accessing keys and values.
495512
fn as_leaf_mut(&mut self) -> *mut LeafNode<K, V> {
496-
// We are mutable, so we cannot be the shared root, so accessing this as a leaf is okay.
497513
self.node.as_ptr()
498514
}
499515

516+
/// The caller must ensure that the node is not the shared root.
500517
fn keys_mut(&mut self) -> &mut [K] {
501518
unsafe { self.reborrow_mut().into_key_slice_mut() }
502519
}
503520

521+
/// The caller must ensure that the node is not the shared root.
504522
fn vals_mut(&mut self) -> &mut [V] {
505523
unsafe { self.reborrow_mut().into_val_slice_mut() }
506524
}
@@ -551,9 +569,10 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
551569
}
552570
}
553571

572+
/// The caller must ensure that the node is not the shared root.
554573
fn into_val_slice(self) -> &'a [V] {
555574
debug_assert!(!self.is_shared_root());
556-
// We cannot be the shared root, so `as_leaf` is okay
575+
// We cannot be the shared root, so `as_leaf` is okay.
557576
unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len()) }
558577
}
559578

@@ -587,6 +606,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
587606
}
588607
}
589608

609+
/// The caller must ensure that the node is not the shared root.
590610
fn into_val_slice_mut(mut self) -> &'a mut [V] {
591611
debug_assert!(!self.is_shared_root());
592612
unsafe {
@@ -597,6 +617,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
597617
}
598618
}
599619

620+
/// The caller must ensure that the node is not the shared root.
600621
fn into_slices_mut(mut self) -> (&'a mut [K], &'a mut [V]) {
601622
debug_assert!(!self.is_shared_root());
602623
// We cannot use the getters here, because calling the second one
@@ -655,6 +676,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
655676
// Necessary for correctness, but this is an internal module
656677
debug_assert!(edge.height == self.height - 1);
657678
debug_assert!(self.len() < CAPACITY);
679+
debug_assert!(!self.is_shared_root());
658680

659681
let idx = self.len();
660682

@@ -686,6 +708,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
686708
// Necessary for correctness, but this is an internal module
687709
debug_assert!(edge.height == self.height - 1);
688710
debug_assert!(self.len() < CAPACITY);
711+
debug_assert!(!self.is_shared_root());
689712

690713
unsafe {
691714
slice_insert(self.keys_mut(), 0, key);
@@ -773,6 +796,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
773796
}
774797
}
775798

799+
/// The caller must ensure that the node is not the shared root.
776800
fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) {
777801
(self.keys_mut().as_mut_ptr(), self.vals_mut().as_mut_ptr())
778802
}
@@ -1116,8 +1140,8 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
11161140
}
11171141
}
11181142

1119-
/// Removes the key/value pair pointed to by this handle, returning the edge between the
1120-
/// now adjacent key/value pairs to the left and right of this handle.
1143+
/// Removes the key/value pair pointed to by this handle and returns it, along with the edge
1144+
/// between the now adjacent key/value pairs (if any) to the left and right of this handle.
11211145
pub fn remove(
11221146
mut self,
11231147
) -> (Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>, K, V) {
@@ -1260,7 +1284,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
12601284
}
12611285
}
12621286

1263-
/// This removes a key/value pair from the left child and replaces it with the key/value pair
1287+
/// This removes a key/value pair from the left child and places it in the key/value storage
12641288
/// pointed to by this handle while pushing the old key/value pair of this handle into the right
12651289
/// child.
12661290
pub fn steal_left(&mut self) {
@@ -1277,7 +1301,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
12771301
}
12781302
}
12791303

1280-
/// This removes a key/value pair from the right child and replaces it with the key/value pair
1304+
/// This removes a key/value pair from the right child and places it in the key/value storage
12811305
/// pointed to by this handle while pushing the old key/value pair of this handle into the left
12821306
/// child.
12831307
pub fn steal_right(&mut self) {

src/libcore/macros/mod.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,21 @@
11
#[doc(include = "panic.md")]
22
#[macro_export]
3-
#[allow_internal_unstable(core_panic,
4-
// FIXME(anp, eddyb) `core_intrinsics` is used here to allow calling
5-
// the `caller_location` intrinsic, but once `#[track_caller]` is implemented,
6-
// `panicking::{panic, panic_fmt}` can use that instead of a `Location` argument.
7-
core_intrinsics,
8-
const_caller_location,
9-
)]
3+
#[allow_internal_unstable(core_panic, track_caller)]
104
#[stable(feature = "core", since = "1.6.0")]
115
macro_rules! panic {
126
() => (
137
$crate::panic!("explicit panic")
148
);
159
($msg:expr) => (
16-
$crate::panicking::panic($msg, $crate::intrinsics::caller_location())
10+
$crate::panicking::panic($msg)
1711
);
1812
($msg:expr,) => (
1913
$crate::panic!($msg)
2014
);
2115
($fmt:expr, $($arg:tt)+) => (
2216
$crate::panicking::panic_fmt(
2317
$crate::format_args!($fmt, $($arg)+),
24-
$crate::intrinsics::caller_location(),
18+
$crate::panic::Location::caller(),
2519
)
2620
);
2721
}

src/libcore/panicking.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ use crate::panic::{Location, PanicInfo};
3636
// never inline unless panic_immediate_abort to avoid code
3737
// bloat at the call sites as much as possible
3838
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
39+
#[track_caller]
3940
#[lang = "panic"] // needed by codegen for panic on overflow and other `Assert` MIR terminators
40-
pub fn panic(expr: &str, location: &Location<'_>) -> ! {
41+
pub fn panic(expr: &str) -> ! {
4142
if cfg!(feature = "panic_immediate_abort") {
4243
unsafe { super::intrinsics::abort() }
4344
}
@@ -48,7 +49,7 @@ pub fn panic(expr: &str, location: &Location<'_>) -> ! {
4849
// truncation and padding (even though none is used here). Using
4950
// Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
5051
// output binary, saving up to a few kilobytes.
51-
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), location)
52+
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), Location::caller())
5253
}
5354

5455
#[cold]

src/librustc_errors/lib.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,8 @@ pub struct HandlerFlags {
329329
/// show macro backtraces even for non-local macros.
330330
/// (rustc: see `-Z external-macro-backtrace`)
331331
pub external_macro_backtrace: bool,
332+
/// If true, identical diagnostics are reported only once.
333+
pub deduplicate_diagnostics: bool,
332334
}
333335

334336
impl Drop for HandlerInner {
@@ -736,16 +738,17 @@ impl HandlerInner {
736738
self.emitted_diagnostic_codes.insert(code.clone());
737739
}
738740

739-
let diagnostic_hash = {
741+
let already_emitted = |this: &mut Self| {
740742
use std::hash::Hash;
741743
let mut hasher = StableHasher::new();
742744
diagnostic.hash(&mut hasher);
743-
hasher.finish()
745+
let diagnostic_hash = hasher.finish();
746+
!this.emitted_diagnostics.insert(diagnostic_hash)
744747
};
745748

746-
// Only emit the diagnostic if we haven't already emitted an equivalent
747-
// one:
748-
if self.emitted_diagnostics.insert(diagnostic_hash) {
749+
// Only emit the diagnostic if we've been asked to deduplicate and
750+
// haven't already emitted an equivalent diagnostic.
751+
if !(self.flags.deduplicate_diagnostics && already_emitted(self)) {
749752
self.emitter.emit_diagnostic(diagnostic);
750753
if diagnostic.is_error() {
751754
self.deduplicated_err_count += 1;

src/librustc_expand/build.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use syntax::ast::{self, AttrVec, BlockCheckMode, Expr, Ident, PatKind, UnOp};
66
use syntax::attr;
77
use syntax::ptr::P;
88

9-
use rustc_span::{Pos, Span};
9+
use rustc_span::Span;
1010

1111
impl<'a> ExtCtxt<'a> {
1212
pub fn path(&self, span: Span, strs: Vec<ast::Ident>) -> ast::Path {
@@ -350,16 +350,10 @@ impl<'a> ExtCtxt<'a> {
350350
}
351351

352352
pub fn expr_fail(&self, span: Span, msg: Symbol) -> P<ast::Expr> {
353-
let loc = self.source_map().lookup_char_pos(span.lo());
354-
let expr_file = self.expr_str(span, Symbol::intern(&loc.file.name.to_string()));
355-
let expr_line = self.expr_u32(span, loc.line as u32);
356-
let expr_col = self.expr_u32(span, loc.col.to_usize() as u32 + 1);
357-
let expr_loc_tuple = self.expr_tuple(span, vec![expr_file, expr_line, expr_col]);
358-
let expr_loc_ptr = self.expr_addr_of(span, expr_loc_tuple);
359353
self.expr_call_global(
360354
span,
361355
[sym::std, sym::rt, sym::begin_panic].iter().map(|s| Ident::new(*s, span)).collect(),
362-
vec![self.expr_str(span, msg), expr_loc_ptr],
356+
vec![self.expr_str(span, msg)],
363357
)
364358
}
365359

src/librustc_mir/const_eval/machine.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
177177

178178
fn find_mir_or_eval_fn(
179179
ecx: &mut InterpCx<'mir, 'tcx, Self>,
180+
span: Span,
180181
instance: ty::Instance<'tcx>,
181182
args: &[OpTy<'tcx>],
182183
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
@@ -199,7 +200,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
199200
// Some functions we support even if they are non-const -- but avoid testing
200201
// that for const fn! We certainly do *not* want to actually call the fn
201202
// though, so be sure we return here.
202-
return if ecx.hook_panic_fn(instance, args, ret)? {
203+
return if ecx.hook_panic_fn(span, instance, args)? {
203204
Ok(None)
204205
} else {
205206
throw_unsup_format!("calling non-const function `{}`", instance)

src/librustc_mir/interpret/intrinsics.rs

+8-34
Original file line numberDiff line numberDiff line change
@@ -366,47 +366,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
366366
/// Returns `true` if an intercept happened.
367367
pub fn hook_panic_fn(
368368
&mut self,
369+
span: Span,
369370
instance: ty::Instance<'tcx>,
370371
args: &[OpTy<'tcx, M::PointerTag>],
371-
_ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
372372
) -> InterpResult<'tcx, bool> {
373373
let def_id = instance.def_id();
374-
if Some(def_id) == self.tcx.lang_items().panic_fn() {
375-
// &'static str, &core::panic::Location { &'static str, u32, u32 }
376-
assert!(args.len() == 2);
374+
if Some(def_id) == self.tcx.lang_items().panic_fn()
375+
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
376+
{
377+
// &'static str
378+
assert!(args.len() == 1);
377379

378380
let msg_place = self.deref_operand(args[0])?;
379381
let msg = Symbol::intern(self.read_str(msg_place)?);
380-
381-
let location = self.deref_operand(args[1])?;
382-
let (file, line, col) = (
383-
self.mplace_field(location, 0)?,
384-
self.mplace_field(location, 1)?,
385-
self.mplace_field(location, 2)?,
386-
);
387-
388-
let file_place = self.deref_operand(file.into())?;
389-
let file = Symbol::intern(self.read_str(file_place)?);
390-
let line = self.read_scalar(line.into())?.to_u32()?;
391-
let col = self.read_scalar(col.into())?.to_u32()?;
392-
throw_panic!(Panic { msg, file, line, col })
393-
} else if Some(def_id) == self.tcx.lang_items().begin_panic_fn() {
394-
assert!(args.len() == 2);
395-
// &'static str, &(&'static str, u32, u32)
396-
let msg = args[0];
397-
let place = self.deref_operand(args[1])?;
398-
let (file, line, col) = (
399-
self.mplace_field(place, 0)?,
400-
self.mplace_field(place, 1)?,
401-
self.mplace_field(place, 2)?,
402-
);
403-
404-
let msg_place = self.deref_operand(msg.into())?;
405-
let msg = Symbol::intern(self.read_str(msg_place)?);
406-
let file_place = self.deref_operand(file.into())?;
407-
let file = Symbol::intern(self.read_str(file_place)?);
408-
let line = self.read_scalar(line.into())?.to_u32()?;
409-
let col = self.read_scalar(col.into())?.to_u32()?;
382+
let span = self.find_closest_untracked_caller_location().unwrap_or(span);
383+
let (file, line, col) = self.location_triple_for_span(span);
410384
throw_panic!(Panic { msg, file, line, col })
411385
} else {
412386
return Ok(false);

src/librustc_mir/interpret/intrinsics/caller_location.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ use crate::interpret::{
99
};
1010

1111
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
12-
/// Walks up the callstack from the intrinsic's callsite, searching for the first frame which is
13-
/// not `#[track_caller]`.
12+
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
13+
/// frame which is not `#[track_caller]`. If the first frame found lacks `#[track_caller]`, then
14+
/// `None` is returned and the callsite of the function invocation itself should be used.
1415
crate fn find_closest_untracked_caller_location(&self) -> Option<Span> {
1516
let mut caller_span = None;
1617
for next_caller in self.stack.iter().rev() {
@@ -54,9 +55,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
5455
}
5556

5657
pub fn alloc_caller_location_for_span(&mut self, span: Span) -> MPlaceTy<'tcx, M::PointerTag> {
58+
let (file, line, column) = self.location_triple_for_span(span);
59+
self.alloc_caller_location(file, line, column)
60+
}
61+
62+
pub(super) fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
5763
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
5864
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
59-
self.alloc_caller_location(
65+
(
6066
Symbol::intern(&caller.file.name.to_string()),
6167
caller.line as u32,
6268
caller.col_display as u32 + 1,

0 commit comments

Comments
 (0)