Skip to content

Commit fc84f5f

Browse files
committed
Auto merge of #56581 - kennytm:rollup, r=kennytm
Rollup of 7 pull requests Successful merges: - #56000 (Add Armv8-M Mainline targets) - #56250 (Introduce ptr::hash for references) - #56434 (Improve query cycle errors for parallel queries) - #56516 (Replace usages of `..i + 1` ranges with `..=i`.) - #56555 (Send textual profile data to stderr, not stdout) - #56561 (Fix bug in from_key_hashed_nocheck) - #56574 (Fix a stutter in the docs for slice::exact_chunks) Failed merges: r? @ghost
2 parents 15a2607 + a40aa45 commit fc84f5f

File tree

30 files changed

+225
-77
lines changed

30 files changed

+225
-77
lines changed

src/liballoc/collections/vec_deque.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -2795,7 +2795,7 @@ mod tests {
27952795
// 0, 1, 2, .., len - 1
27962796
let expected = (0..).take(len).collect::<VecDeque<_>>();
27972797
for tail_pos in 0..cap {
2798-
for to_remove in 0..len + 1 {
2798+
for to_remove in 0..=len {
27992799
tester.tail = tail_pos;
28002800
tester.head = tail_pos;
28012801
for i in 0..len {
@@ -2821,10 +2821,10 @@ mod tests {
28212821
let mut tester: VecDeque<usize> = VecDeque::with_capacity(7);
28222822

28232823
let cap = tester.capacity();
2824-
for len in 0..cap + 1 {
2825-
for tail in 0..cap + 1 {
2826-
for drain_start in 0..len + 1 {
2827-
for drain_end in drain_start..len + 1 {
2824+
for len in 0..=cap {
2825+
for tail in 0..=cap {
2826+
for drain_start in 0..=len {
2827+
for drain_end in drain_start..=len {
28282828
tester.tail = tail;
28292829
tester.head = tail;
28302830
for i in 0..len {
@@ -2866,10 +2866,10 @@ mod tests {
28662866
tester.reserve(63);
28672867
let max_cap = tester.capacity();
28682868

2869-
for len in 0..cap + 1 {
2869+
for len in 0..=cap {
28702870
// 0, 1, 2, .., len - 1
28712871
let expected = (0..).take(len).collect::<VecDeque<_>>();
2872-
for tail_pos in 0..max_cap + 1 {
2872+
for tail_pos in 0..=max_cap {
28732873
tester.tail = tail_pos;
28742874
tester.head = tail_pos;
28752875
tester.reserve(63);
@@ -2899,7 +2899,7 @@ mod tests {
28992899
// len is the length *before* splitting
29002900
for len in 0..cap {
29012901
// index to split at
2902-
for at in 0..len + 1 {
2902+
for at in 0..=len {
29032903
// 0, 1, 2, .., at - 1 (may be empty)
29042904
let expected_self = (0..).take(at).collect::<VecDeque<_>>();
29052905
// at, at + 1, .., len - 1 (may be empty)
@@ -2927,7 +2927,7 @@ mod tests {
29272927
fn test_from_vec() {
29282928
use vec::Vec;
29292929
for cap in 0..35 {
2930-
for len in 0..cap + 1 {
2930+
for len in 0..=cap {
29312931
let mut vec = Vec::with_capacity(cap);
29322932
vec.extend(0..len);
29332933

src/liballoc/tests/binary_heap.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -318,11 +318,11 @@ fn panic_safe() {
318318
const NTEST: usize = 10;
319319

320320
// don't use 0 in the data -- we want to catch the zeroed-out case.
321-
let data = (1..DATASZ + 1).collect::<Vec<_>>();
321+
let data = (1..=DATASZ).collect::<Vec<_>>();
322322

323323
// since it's a fuzzy test, run several tries.
324324
for _ in 0..NTEST {
325-
for i in 1..DATASZ + 1 {
325+
for i in 1..=DATASZ {
326326
DROP_COUNTER.store(0, Ordering::SeqCst);
327327

328328
let mut panic_ords: Vec<_> = data.iter()

src/liballoc/tests/btree/map.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ fn test_range() {
302302
for i in 0..size {
303303
for j in i..size {
304304
let mut kvs = map.range((Included(&i), Included(&j))).map(|(&k, &v)| (k, v));
305-
let mut pairs = (i..j + 1).map(|i| (i, i));
305+
let mut pairs = (i..=j).map(|i| (i, i));
306306

307307
for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
308308
assert_eq!(kv, pair);
@@ -321,7 +321,7 @@ fn test_range_mut() {
321321
for i in 0..size {
322322
for j in i..size {
323323
let mut kvs = map.range_mut((Included(&i), Included(&j))).map(|(&k, &mut v)| (k, v));
324-
let mut pairs = (i..j + 1).map(|i| (i, i));
324+
let mut pairs = (i..=j).map(|i| (i, i));
325325

326326
for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
327327
assert_eq!(kv, pair);

src/liballoc/tests/str.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1378,7 +1378,7 @@ fn test_bool_from_str() {
13781378
fn check_contains_all_substrings(s: &str) {
13791379
assert!(s.contains(""));
13801380
for i in 0..s.len() {
1381-
for j in i+1..s.len() + 1 {
1381+
for j in i+1..=s.len() {
13821382
assert!(s.contains(&s[i..j]));
13831383
}
13841384
}

src/liballoc/tests/vec_deque.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -861,15 +861,15 @@ fn test_as_slices() {
861861
ring.push_back(i);
862862

863863
let (left, right) = ring.as_slices();
864-
let expected: Vec<_> = (0..i + 1).collect();
864+
let expected: Vec<_> = (0..=i).collect();
865865
assert_eq!(left, &expected[..]);
866866
assert_eq!(right, []);
867867
}
868868

869869
for j in -last..0 {
870870
ring.push_front(j);
871871
let (left, right) = ring.as_slices();
872-
let expected_left: Vec<_> = (-last..j + 1).rev().collect();
872+
let expected_left: Vec<_> = (-last..=j).rev().collect();
873873
let expected_right: Vec<_> = (0..first).collect();
874874
assert_eq!(left, &expected_left[..]);
875875
assert_eq!(right, &expected_right[..]);
@@ -889,15 +889,15 @@ fn test_as_mut_slices() {
889889
ring.push_back(i);
890890

891891
let (left, right) = ring.as_mut_slices();
892-
let expected: Vec<_> = (0..i + 1).collect();
892+
let expected: Vec<_> = (0..=i).collect();
893893
assert_eq!(left, &expected[..]);
894894
assert_eq!(right, []);
895895
}
896896

897897
for j in -last..0 {
898898
ring.push_front(j);
899899
let (left, right) = ring.as_mut_slices();
900-
let expected_left: Vec<_> = (-last..j + 1).rev().collect();
900+
let expected_left: Vec<_> = (-last..=j).rev().collect();
901901
let expected_right: Vec<_> = (0..first).collect();
902902
assert_eq!(left, &expected_left[..]);
903903
assert_eq!(right, &expected_right[..]);

src/libcore/ptr.rs

+30
Original file line numberDiff line numberDiff line change
@@ -2516,6 +2516,36 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
25162516
a == b
25172517
}
25182518

2519+
/// Hash the raw pointer address behind a reference, rather than the value
2520+
/// it points to.
2521+
///
2522+
/// # Examples
2523+
///
2524+
/// ```
2525+
/// #![feature(ptr_hash)]
2526+
/// use std::collections::hash_map::DefaultHasher;
2527+
/// use std::hash::{Hash, Hasher};
2528+
/// use std::ptr;
2529+
///
2530+
/// let five = 5;
2531+
/// let five_ref = &five;
2532+
///
2533+
/// let mut hasher = DefaultHasher::new();
2534+
/// ptr::hash(five_ref, &mut hasher);
2535+
/// let actual = hasher.finish();
2536+
///
2537+
/// let mut hasher = DefaultHasher::new();
2538+
/// (five_ref as *const i32).hash(&mut hasher);
2539+
/// let expected = hasher.finish();
2540+
///
2541+
/// assert_eq!(actual, expected);
2542+
/// ```
2543+
#[unstable(feature = "ptr_hash", reason = "newly added", issue = "56286")]
2544+
pub fn hash<T, S: hash::Hasher>(hashee: *const T, into: &mut S) {
2545+
use hash::Hash;
2546+
hashee.hash(into);
2547+
}
2548+
25192549
// Impls for function pointers
25202550
macro_rules! fnptr_impls_safety_abi {
25212551
($FnTy: ty, $($Arg: ident),*) => {

src/libcore/slice/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -702,8 +702,7 @@ impl<T> [T] {
702702
/// resulting code better than in the case of [`chunks`].
703703
///
704704
/// See [`chunks`] for a variant of this iterator that also returns the remainder as a smaller
705-
/// chunk, and [`rchunks_exact`] for the same iterator but starting at the end of the slice of
706-
/// the slice.
705+
/// chunk, and [`rchunks_exact`] for the same iterator but starting at the end of the slice.
707706
///
708707
/// # Panics
709708
///

src/librustc/hir/map/hir_id_validator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> {
100100

101101
if max != self.hir_ids_seen.len() - 1 {
102102
// Collect the missing ItemLocalIds
103-
let missing: Vec<_> = (0 .. max as u32 + 1)
103+
let missing: Vec<_> = (0 ..= max as u32)
104104
.filter(|&i| !self.hir_ids_seen.contains_key(&ItemLocalId::from_u32(i)))
105105
.collect();
106106

src/librustc/mir/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ impl<'tcx> Mir<'tcx> {
339339
#[inline]
340340
pub fn args_iter(&self) -> impl Iterator<Item = Local> {
341341
let arg_count = self.arg_count;
342-
(1..arg_count + 1).map(Local::new)
342+
(1..=arg_count).map(Local::new)
343343
}
344344

345345
/// Returns an iterator over all user-defined variables and compiler-generated temporaries (all

src/librustc/ty/context.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1942,8 +1942,12 @@ pub mod tls {
19421942
/// This is a callback from libsyntax as it cannot access the implicit state
19431943
/// in librustc otherwise
19441944
fn span_debug(span: syntax_pos::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1945-
with(|tcx| {
1946-
write!(f, "{}", tcx.sess.source_map().span_to_string(span))
1945+
with_opt(|tcx| {
1946+
if let Some(tcx) = tcx {
1947+
write!(f, "{}", tcx.sess.source_map().span_to_string(span))
1948+
} else {
1949+
syntax_pos::default_span_debug(span, f)
1950+
}
19471951
})
19481952
}
19491953

src/librustc/ty/query/job.rs

+66-32
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,11 @@ impl<'tcx> QueryJob<'tcx> {
103103
condvar: Condvar::new(),
104104
});
105105
self.latch.await(&waiter);
106-
107-
match Lrc::get_mut(&mut waiter).unwrap().cycle.get_mut().take() {
106+
// FIXME: Get rid of this lock. We have ownership of the QueryWaiter
107+
// although another thread may still have a Lrc reference so we cannot
108+
// use Lrc::get_mut
109+
let mut cycle = waiter.cycle.lock();
110+
match cycle.take() {
108111
None => Ok(()),
109112
Some(cycle) => Err(cycle)
110113
}
@@ -326,19 +329,17 @@ fn connected_to_root<'tcx>(
326329
query: Lrc<QueryJob<'tcx>>,
327330
visited: &mut FxHashSet<*const QueryJob<'tcx>>
328331
) -> bool {
329-
// This query is connected to the root (it has no query parent), return true
330-
if query.parent.is_none() {
331-
return true;
332-
}
333-
334332
// We already visited this or we're deliberately ignoring it
335333
if visited.contains(&query.as_ptr()) {
336334
return false;
337335
}
338336

339-
visited.insert(query.as_ptr());
337+
// This query is connected to the root (it has no query parent), return true
338+
if query.parent.is_none() {
339+
return true;
340+
}
340341

341-
let mut connected = false;
342+
visited.insert(query.as_ptr());
342343

343344
visit_waiters(query, |_, successor| {
344345
if connected_to_root(successor, visited) {
@@ -349,6 +350,28 @@ fn connected_to_root<'tcx>(
349350
}).is_some()
350351
}
351352

353+
// Deterministically pick an query from a list
354+
#[cfg(parallel_queries)]
355+
fn pick_query<'a, 'tcx, T, F: Fn(&T) -> (Span, Lrc<QueryJob<'tcx>>)>(
356+
tcx: TyCtxt<'_, 'tcx, '_>,
357+
queries: &'a [T],
358+
f: F
359+
) -> &'a T {
360+
// Deterministically pick an entry point
361+
// FIXME: Sort this instead
362+
let mut hcx = tcx.create_stable_hashing_context();
363+
queries.iter().min_by_key(|v| {
364+
let (span, query) = f(v);
365+
let mut stable_hasher = StableHasher::<u64>::new();
366+
query.info.query.hash_stable(&mut hcx, &mut stable_hasher);
367+
// Prefer entry points which have valid spans for nicer error messages
368+
// We add an integer to the tuple ensuring that entry points
369+
// with valid spans are picked first
370+
let span_cmp = if span == DUMMY_SP { 1 } else { 0 };
371+
(span_cmp, stable_hasher.finish())
372+
}).unwrap()
373+
}
374+
352375
/// Looks for query cycles starting from the last query in `jobs`.
353376
/// If a cycle is found, all queries in the cycle is removed from `jobs` and
354377
/// the function return true.
@@ -388,41 +411,52 @@ fn remove_cycle<'tcx>(
388411

389412
// Find the queries in the cycle which are
390413
// connected to queries outside the cycle
391-
let entry_points = stack.iter().filter_map(|query| {
392-
// Mark all the other queries in the cycle as already visited
393-
let mut visited = FxHashSet::from_iter(stack.iter().filter_map(|q| {
394-
if q.1.as_ptr() != query.1.as_ptr() {
395-
Some(q.1.as_ptr())
396-
} else {
414+
let entry_points: Vec<_> = stack.iter().filter_map(|(span, query)| {
415+
if query.parent.is_none() {
416+
// This query is connected to the root (it has no query parent)
417+
Some((*span, query.clone(), None))
418+
} else {
419+
let mut waiters = Vec::new();
420+
// Find all the direct waiters who lead to the root
421+
visit_waiters(query.clone(), |span, waiter| {
422+
// Mark all the other queries in the cycle as already visited
423+
let mut visited = FxHashSet::from_iter(stack.iter().map(|q| q.1.as_ptr()));
424+
425+
if connected_to_root(waiter.clone(), &mut visited) {
426+
waiters.push((span, waiter));
427+
}
428+
429+
None
430+
});
431+
if waiters.is_empty() {
397432
None
433+
} else {
434+
// Deterministically pick one of the waiters to show to the user
435+
let waiter = pick_query(tcx, &waiters, |s| s.clone()).clone();
436+
Some((*span, query.clone(), Some(waiter)))
398437
}
399-
}));
400-
401-
if connected_to_root(query.1.clone(), &mut visited) {
402-
Some(query.1.clone())
403-
} else {
404-
None
405438
}
406-
});
439+
}).collect();
440+
441+
let entry_points: Vec<(Span, Lrc<QueryJob<'tcx>>, Option<(Span, Lrc<QueryJob<'tcx>>)>)>
442+
= entry_points;
407443

408444
// Deterministically pick an entry point
409-
// FIXME: Sort this instead
410-
let mut hcx = tcx.create_stable_hashing_context();
411-
let entry_point = entry_points.min_by_key(|q| {
412-
let mut stable_hasher = StableHasher::<u64>::new();
413-
q.info.query.hash_stable(&mut hcx, &mut stable_hasher);
414-
stable_hasher.finish()
415-
}).unwrap().as_ptr();
445+
let (_, entry_point, usage) = pick_query(tcx, &entry_points, |e| (e.0, e.1.clone()));
416446

417447
// Shift the stack so that our entry point is first
418-
let entry_point_pos = stack.iter().position(|(_, query)| query.as_ptr() == entry_point);
448+
let entry_point_pos = stack.iter().position(|(_, query)| {
449+
query.as_ptr() == entry_point.as_ptr()
450+
});
419451
if let Some(pos) = entry_point_pos {
420-
stack.rotate_right(pos);
452+
stack.rotate_left(pos);
421453
}
422454

455+
let usage = usage.as_ref().map(|(span, query)| (*span, query.info.query.clone()));
456+
423457
// Create the cycle error
424458
let mut error = CycleError {
425-
usage: None,
459+
usage,
426460
cycle: stack.iter().map(|&(s, ref q)| QueryInfo {
427461
span: s,
428462
query: q.info.query.clone(),

src/librustc/util/profiling.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use session::config::Options;
1212

1313
use std::fs;
14-
use std::io::{self, StdoutLock, Write};
14+
use std::io::{self, StderrLock, Write};
1515
use std::time::{Duration, Instant};
1616

1717
macro_rules! define_categories {
@@ -61,7 +61,7 @@ macro_rules! define_categories {
6161
}
6262
}
6363

64-
fn print(&self, lock: &mut StdoutLock<'_>) {
64+
fn print(&self, lock: &mut StderrLock<'_>) {
6565
writeln!(lock, "| Phase | Time (ms) | Queries | Hits (%) |")
6666
.unwrap();
6767
writeln!(lock, "| ---------------- | -------------- | -------------- | -------- |")
@@ -235,7 +235,7 @@ impl SelfProfiler {
235235
self.timer_stack.is_empty(),
236236
"there were timers running when print_results() was called");
237237

238-
let out = io::stdout();
238+
let out = io::stderr();
239239
let mut lock = out.lock();
240240

241241
let crate_name =

0 commit comments

Comments
 (0)