Skip to content

Commit e41ced3

Browse files
committed
Auto merge of #66686 - Centril:rollup-07slyoo, r=Centril
Rollup of 5 pull requests Successful merges: - #64856 (Scope format! temporaries) - #66411 (mem::forget docs: mention ManuallyDrop) - #66594 (Fix cycle when debug-printing opaque types) - #66641 (parser: recover on nested ADTs as enum variants) - #66659 (make `./x.py bench` again) Failed merges: r? @ghost
2 parents ad808d9 + d22bf91 commit e41ced3

File tree

14 files changed

+315
-159
lines changed

14 files changed

+315
-159
lines changed

src/liballoc/macros.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,8 @@ macro_rules! vec {
9898
#[macro_export]
9999
#[stable(feature = "rust1", since = "1.0.0")]
100100
macro_rules! format {
101-
($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*)))
101+
($($arg:tt)*) => {{
102+
let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
103+
res
104+
}}
102105
}

src/libcore/benches/num/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ macro_rules! from_str_bench {
3535
.iter()
3636
.cycle()
3737
.take(5_000)
38-
.filter_map(|s| <($t)>::from_str(s).ok())
38+
.filter_map(|s| <$t>::from_str(s).ok())
3939
.max()
4040
})
4141
}
@@ -51,7 +51,7 @@ macro_rules! from_str_radix_bench {
5151
.iter()
5252
.cycle()
5353
.take(5_000)
54-
.filter_map(|s| <($t)>::from_str_radix(s, $radix).ok())
54+
.filter_map(|s| <$t>::from_str_radix(s, $radix).ok())
5555
.max()
5656
})
5757
}

src/libcore/mem/mod.rs

+33-3
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ pub use crate::intrinsics::transmute;
4545
/// `mem::forget` from safe code does not fundamentally change Rust's safety
4646
/// guarantees.
4747
///
48-
/// That said, leaking resources such as memory or I/O objects is usually undesirable,
49-
/// so `forget` is only recommended for specialized use cases like those shown below.
48+
/// That said, leaking resources such as memory or I/O objects is usually undesirable.
49+
/// The need comes up in some specialized use cases for FFI or unsafe code, but even
50+
/// then, [`ManuallyDrop`] is typically preferred.
5051
///
5152
/// Because forgetting a value is allowed, any `unsafe` code you write must
5253
/// allow for this possibility. You cannot return a value and expect that the
@@ -68,7 +69,35 @@ pub use crate::intrinsics::transmute;
6869
/// ```
6970
///
7071
/// The practical use cases for `forget` are rather specialized and mainly come
71-
/// up in unsafe or FFI code.
72+
/// up in unsafe or FFI code. However, [`ManuallyDrop`] is usually preferred
73+
/// for such cases, e.g.:
74+
///
75+
/// ```
76+
/// use std::mem::ManuallyDrop;
77+
///
78+
/// let v = vec![65, 122];
79+
/// // Before we disassemble `v` into its raw parts, make sure it
80+
/// // does not get dropped!
81+
/// let mut v = ManuallyDrop::new(v);
82+
/// // Now disassemble `v`. These operations cannot panic, so there cannot be a leak.
83+
/// let ptr = v.as_mut_ptr();
84+
/// let cap = v.capacity();
85+
/// // Finally, build a `String`.
86+
/// let s = unsafe { String::from_raw_parts(ptr, 2, cap) };
87+
/// assert_eq!(s, "Az");
88+
/// // `s` is implicitly dropped and its memory deallocated.
89+
/// ```
90+
///
91+
/// Using `ManuallyDrop` here has two advantages:
92+
///
93+
/// * We do not "touch" `v` after disassembling it. For some types, operations
94+
/// such as passing ownership (to a funcion like `mem::forget`) requires them to actually
95+
/// be fully owned right now; that is a promise we do not want to make here as we are
96+
/// in the process of transferring ownership to the new `String` we are building.
97+
/// * In case of an unexpected panic, `ManuallyDrop` is not dropped, but if the panic
98+
/// occurs before `mem::forget` was called we might end up dropping invalid data,
99+
/// or double-dropping. In other words, `ManuallyDrop` errs on the side of leaking
100+
/// instead of erring on the side of dropping.
72101
///
73102
/// [drop]: fn.drop.html
74103
/// [uninit]: fn.uninitialized.html
@@ -78,6 +107,7 @@ pub use crate::intrinsics::transmute;
78107
/// [leak]: ../../std/boxed/struct.Box.html#method.leak
79108
/// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw
80109
/// [ub]: ../../reference/behavior-considered-undefined.html
110+
/// [`ManuallyDrop`]: struct.ManuallyDrop.html
81111
#[inline]
82112
#[stable(feature = "rust1", since = "1.0.0")]
83113
pub fn forget<T>(t: T) {

src/librustc/benches/dispatch.rs

-34
This file was deleted.

src/librustc/benches/lib.rs

+59-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,63 @@
1+
#![feature(slice_patterns)]
12
#![feature(test)]
23

34
extern crate test;
45

5-
mod dispatch;
6-
mod pattern;
6+
use test::Bencher;
7+
8+
// Static/dynamic method dispatch
9+
10+
struct Struct {
11+
field: isize
12+
}
13+
14+
trait Trait {
15+
fn method(&self) -> isize;
16+
}
17+
18+
impl Trait for Struct {
19+
fn method(&self) -> isize {
20+
self.field
21+
}
22+
}
23+
24+
#[bench]
25+
fn trait_vtable_method_call(b: &mut Bencher) {
26+
let s = Struct { field: 10 };
27+
let t = &s as &dyn Trait;
28+
b.iter(|| {
29+
t.method()
30+
});
31+
}
32+
33+
#[bench]
34+
fn trait_static_method_call(b: &mut Bencher) {
35+
let s = Struct { field: 10 };
36+
b.iter(|| {
37+
s.method()
38+
});
39+
}
40+
41+
// Overhead of various match forms
42+
43+
#[bench]
44+
fn option_some(b: &mut Bencher) {
45+
let x = Some(10);
46+
b.iter(|| {
47+
match x {
48+
Some(y) => y,
49+
None => 11
50+
}
51+
});
52+
}
53+
54+
#[bench]
55+
fn vec_pattern(b: &mut Bencher) {
56+
let x = [1,2,3,4,5,6];
57+
b.iter(|| {
58+
match x {
59+
[1,2,3,..] => 10,
60+
_ => 11,
61+
}
62+
});
63+
}

src/librustc/benches/pattern.rs

-25
This file was deleted.

src/librustc/ty/print/pretty.rs

+65-38
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,24 @@ macro_rules! define_scoped_cx {
4949
thread_local! {
5050
static FORCE_IMPL_FILENAME_LINE: Cell<bool> = Cell::new(false);
5151
static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = Cell::new(false);
52+
static NO_QUERIES: Cell<bool> = Cell::new(false);
53+
}
54+
55+
/// Avoids running any queries during any prints that occur
56+
/// during the closure. This may alter the apperance of some
57+
/// types (e.g. forcing verbose printing for opaque types).
58+
/// This method is used during some queries (e.g. `predicates_of`
59+
/// for opaque types), to ensure that any debug printing that
60+
/// occurs during the query computation does not end up recursively
61+
/// calling the same query.
62+
pub fn with_no_queries<F: FnOnce() -> R, R>(f: F) -> R {
63+
NO_QUERIES.with(|no_queries| {
64+
let old = no_queries.get();
65+
no_queries.set(true);
66+
let result = f();
67+
no_queries.set(old);
68+
result
69+
})
5270
}
5371

5472
/// Force us to name impls with just the filename/line number. We
@@ -556,52 +574,61 @@ pub trait PrettyPrinter<'tcx>:
556574
}
557575
ty::Opaque(def_id, substs) => {
558576
// FIXME(eddyb) print this with `print_def_path`.
559-
if self.tcx().sess.verbose() {
577+
// We use verbose printing in 'NO_QUERIES' mode, to
578+
// avoid needing to call `predicates_of`. This should
579+
// only affect certain debug messages (e.g. messages printed
580+
// from `rustc::ty` during the computation of `tcx.predicates_of`),
581+
// and should have no effect on any compiler output.
582+
if self.tcx().sess.verbose() || NO_QUERIES.with(|q| q.get()) {
560583
p!(write("Opaque({:?}, {:?})", def_id, substs));
561584
return Ok(self);
562585
}
563586

564-
let def_key = self.tcx().def_key(def_id);
565-
if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
566-
p!(write("{}", name));
567-
let mut substs = substs.iter();
568-
// FIXME(eddyb) print this with `print_def_path`.
569-
if let Some(first) = substs.next() {
570-
p!(write("::<"));
571-
p!(print(first));
572-
for subst in substs {
573-
p!(write(", "), print(subst));
587+
return Ok(with_no_queries(|| {
588+
589+
let def_key = self.tcx().def_key(def_id);
590+
if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
591+
p!(write("{}", name));
592+
let mut substs = substs.iter();
593+
// FIXME(eddyb) print this with `print_def_path`.
594+
if let Some(first) = substs.next() {
595+
p!(write("::<"));
596+
p!(print(first));
597+
for subst in substs {
598+
p!(write(", "), print(subst));
599+
}
600+
p!(write(">"));
574601
}
575-
p!(write(">"));
602+
return Ok(self);
576603
}
577-
return Ok(self);
578-
}
579-
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
580-
// by looking up the projections associated with the def_id.
581-
let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
582-
583-
let mut first = true;
584-
let mut is_sized = false;
585-
p!(write("impl"));
586-
for predicate in bounds.predicates {
587-
if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
588-
// Don't print +Sized, but rather +?Sized if absent.
589-
if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
590-
is_sized = true;
591-
continue;
592-
}
604+
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
605+
// by looking up the projections associated with the def_id.
606+
let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
607+
608+
let mut first = true;
609+
let mut is_sized = false;
610+
p!(write("impl"));
611+
for predicate in bounds.predicates {
612+
if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
613+
// Don't print +Sized, but rather +?Sized if absent.
614+
if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
615+
is_sized = true;
616+
continue;
617+
}
593618

594-
p!(
595-
write("{}", if first { " " } else { "+" }),
596-
print(trait_ref));
597-
first = false;
619+
p!(
620+
write("{}", if first { " " } else { "+" }),
621+
print(trait_ref));
622+
first = false;
623+
}
598624
}
599-
}
600-
if !is_sized {
601-
p!(write("{}?Sized", if first { " " } else { "+" }));
602-
} else if first {
603-
p!(write(" Sized"));
604-
}
625+
if !is_sized {
626+
p!(write("{}?Sized", if first { " " } else { "+" }));
627+
} else if first {
628+
p!(write(" Sized"));
629+
}
630+
Ok(self)
631+
})?);
605632
}
606633
ty::Str => p!(write("str")),
607634
ty::Generator(did, substs, movability) => {

src/librustc_codegen_ssa/back/rpath/tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ fn test_minimize2() {
5252
fn test_rpath_relative() {
5353
if cfg!(target_os = "macos") {
5454
let config = &mut RPathConfig {
55-
used_crates: Vec::new(),
55+
used_crates: &[],
5656
has_rpath: true,
5757
is_like_osx: true,
5858
linker_is_gnu: false,
@@ -64,7 +64,7 @@ fn test_rpath_relative() {
6464
assert_eq!(res, "@loader_path/../lib");
6565
} else {
6666
let config = &mut RPathConfig {
67-
used_crates: Vec::new(),
67+
used_crates: &[],
6868
out_filename: PathBuf::from("bin/rustc"),
6969
get_install_prefix_lib_path: &mut || panic!(),
7070
has_rpath: true,

0 commit comments

Comments
 (0)