Skip to content

Commit a39c778

Browse files
committed
Auto merge of #73486 - Manishearth:rollup-11iyqpc, r=Manishearth
Rollup of 17 pull requests Successful merges: - #70551 (Make all uses of ty::Error delay a span bug) - #71338 (Expand "recursive opaque type" diagnostic) - #71976 (Improve diagnostics for `let x += 1`) - #72279 (add raw_ref macros) - #72628 (Add tests for 'impl Default for [T; N]') - #72804 (Further tweak lifetime errors involving `dyn Trait` and `impl Trait` in return position) - #72814 (remove visit_terminator_kind from MIR visitor) - #72836 (Complete the std::time documentation to warn about the inconsistencies between OS) - #72968 (Only highlight doc search results via mouseover if mouse has moved) - #73034 (Export `#[inline]` fns with extern indicators) - #73315 (Clean up some weird command strings) - #73320 (Make new type param suggestion more targetted) - #73361 (Tweak "non-primitive cast" error) - #73425 (Mention functions pointers in the documentation) - #73428 (Fix typo in librustc_ast docs) - #73447 (Improve document for `Result::as_deref(_mut)` methods) - #73476 (Added tooltip for should_panic code examples) Failed merges: r? @ghost
2 parents 036b5fe + 6c53a0c commit a39c778

File tree

197 files changed

+2110
-921
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

197 files changed

+2110
-921
lines changed

src/libcore/convert/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ pub trait Into<T>: Sized {
374374
/// [`Into`]: trait.Into.html
375375
/// [`from`]: trait.From.html#tymethod.from
376376
/// [book]: ../../book/ch09-00-error-handling.html
377+
#[rustc_diagnostic_item = "from_trait"]
377378
#[stable(feature = "rust1", since = "1.0.0")]
378379
#[rustc_on_unimplemented(on(
379380
all(_Self = "&str", T = "std::string::String"),

src/libcore/mem/mod.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -581,11 +581,12 @@ pub const fn needs_drop<T>() -> bool {
581581
/// This means that, for example, the padding byte in `(u8, u16)` is not
582582
/// necessarily zeroed.
583583
///
584-
/// There is no guarantee that an all-zero byte-pattern represents a valid value of
585-
/// some type `T`. For example, the all-zero byte-pattern is not a valid value
586-
/// for reference types (`&T` and `&mut T`). Using `zeroed` on such types
587-
/// causes immediate [undefined behavior][ub] because [the Rust compiler assumes][inv]
588-
/// that there always is a valid value in a variable it considers initialized.
584+
/// There is no guarantee that an all-zero byte-pattern represents a valid value
585+
/// of some type `T`. For example, the all-zero byte-pattern is not a valid value
586+
/// for reference types (`&T`, `&mut T`) and functions pointers. Using `zeroed`
587+
/// on such types causes immediate [undefined behavior][ub] because [the Rust
588+
/// compiler assumes][inv] that there always is a valid value in a variable it
589+
/// considers initialized.
589590
///
590591
/// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed].
591592
/// It is useful for FFI sometimes, but should generally be avoided.
@@ -612,6 +613,7 @@ pub const fn needs_drop<T>() -> bool {
612613
/// use std::mem;
613614
///
614615
/// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior!
616+
/// let _y: fn() = unsafe { mem::zeroed() }; // And again!
615617
/// ```
616618
#[inline(always)]
617619
#[stable(feature = "rust1", since = "1.0.0")]

src/libcore/ptr/mod.rs

+67
Original file line numberDiff line numberDiff line change
@@ -1399,3 +1399,70 @@ fnptr_impls_args! { A, B, C, D, E, F, G, H, I }
13991399
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J }
14001400
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K }
14011401
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L }
1402+
1403+
/// Create a `const` raw pointer to a place, without creating an intermediate reference.
1404+
///
1405+
/// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned
1406+
/// and points to initialized data. For cases where those requirements do not hold,
1407+
/// raw pointers should be used instead. However, `&expr as *const _` creates a reference
1408+
/// before casting it to a raw pointer, and that reference is subject to the same rules
1409+
/// as all other references. This macro can create a raw pointer *without* creating
1410+
/// a reference first.
1411+
///
1412+
/// # Example
1413+
///
1414+
/// ```
1415+
/// #![feature(raw_ref_macros)]
1416+
/// use std::ptr;
1417+
///
1418+
/// #[repr(packed)]
1419+
/// struct Packed {
1420+
/// f1: u8,
1421+
/// f2: u16,
1422+
/// }
1423+
///
1424+
/// let packed = Packed { f1: 1, f2: 2 };
1425+
/// // `&packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
1426+
/// let raw_f2 = ptr::raw_const!(packed.f2);
1427+
/// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
1428+
/// ```
1429+
#[unstable(feature = "raw_ref_macros", issue = "73394")]
1430+
#[rustc_macro_transparency = "semitransparent"]
1431+
#[allow_internal_unstable(raw_ref_op)]
1432+
pub macro raw_const($e:expr) {
1433+
&raw const $e
1434+
}
1435+
1436+
/// Create a `mut` raw pointer to a place, without creating an intermediate reference.
1437+
///
1438+
/// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned
1439+
/// and points to initialized data. For cases where those requirements do not hold,
1440+
/// raw pointers should be used instead. However, `&mut expr as *mut _` creates a reference
1441+
/// before casting it to a raw pointer, and that reference is subject to the same rules
1442+
/// as all other references. This macro can create a raw pointer *without* creating
1443+
/// a reference first.
1444+
///
1445+
/// # Example
1446+
///
1447+
/// ```
1448+
/// #![feature(raw_ref_macros)]
1449+
/// use std::ptr;
1450+
///
1451+
/// #[repr(packed)]
1452+
/// struct Packed {
1453+
/// f1: u8,
1454+
/// f2: u16,
1455+
/// }
1456+
///
1457+
/// let mut packed = Packed { f1: 1, f2: 2 };
1458+
/// // `&mut packed.f2` would create an unaligned reference, and thus be Undefined Behavior!
1459+
/// let raw_f2 = ptr::raw_mut!(packed.f2);
1460+
/// unsafe { raw_f2.write_unaligned(42); }
1461+
/// assert_eq!({packed.f2}, 42); // `{...}` forces copying the field instead of creating a reference.
1462+
/// ```
1463+
#[unstable(feature = "raw_ref_macros", issue = "73394")]
1464+
#[rustc_macro_transparency = "semitransparent"]
1465+
#[allow_internal_unstable(raw_ref_op)]
1466+
pub macro raw_mut($e:expr) {
1467+
&raw mut $e
1468+
}

src/libcore/result.rs

+40-16
Original file line numberDiff line numberDiff line change
@@ -1145,45 +1145,69 @@ impl<T, E: Into<!>> Result<T, E> {
11451145
}
11461146
}
11471147

1148-
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
1148+
#[unstable(feature = "inner_deref", issue = "50264")]
11491149
impl<T: Deref, E> Result<T, E> {
1150-
/// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T::Target, &E>`.
1150+
/// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&<T as Deref>::Target, &E>`.
11511151
///
1152-
/// Leaves the original `Result` in-place, creating a new one containing a reference to the
1153-
/// `Ok` type's `Deref::Target` type.
1152+
/// Coerces the [`Ok`] variant of the original [`Result`] via [`Deref`](crate::ops::Deref)
1153+
/// and returns the new [`Result`].
1154+
///
1155+
/// # Examples
1156+
///
1157+
/// ```
1158+
/// let x: Result<String, u32> = Ok("hello".to_string());
1159+
/// let y: Result<&str, &u32> = Ok("hello");
1160+
/// assert_eq!(x.as_deref(), y);
1161+
///
1162+
/// let x: Result<String, u32> = Err(42);
1163+
/// let y: Result<&str, &u32> = Err(&42);
1164+
/// assert_eq!(x.as_deref(), y);
1165+
/// ```
11541166
pub fn as_deref(&self) -> Result<&T::Target, &E> {
11551167
self.as_ref().map(|t| t.deref())
11561168
}
11571169
}
11581170

1159-
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
1171+
#[unstable(feature = "inner_deref", issue = "50264")]
11601172
impl<T, E: Deref> Result<T, E> {
1161-
/// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T, &E::Target>`.
1173+
/// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T, &<E as Deref>::Target>`.
11621174
///
1163-
/// Leaves the original `Result` in-place, creating a new one containing a reference to the
1164-
/// `Err` type's `Deref::Target` type.
1175+
/// Coerces the [`Err`] variant of the original [`Result`] via [`Deref`](crate::ops::Deref)
1176+
/// and returns the new [`Result`].
11651177
pub fn as_deref_err(&self) -> Result<&T, &E::Target> {
11661178
self.as_ref().map_err(|e| e.deref())
11671179
}
11681180
}
11691181

1170-
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
1182+
#[unstable(feature = "inner_deref", issue = "50264")]
11711183
impl<T: DerefMut, E> Result<T, E> {
1172-
/// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut T::Target, &mut E>`.
1184+
/// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut <T as DerefMut>::Target, &mut E>`.
11731185
///
1174-
/// Leaves the original `Result` in-place, creating a new one containing a mutable reference to
1175-
/// the `Ok` type's `Deref::Target` type.
1186+
/// Coerces the [`Ok`] variant of the original [`Result`] via [`DerefMut`](crate::ops::DerefMut)
1187+
/// and returns the new [`Result`].
1188+
///
1189+
/// # Examples
1190+
///
1191+
/// ```
1192+
/// let mut x: Result<String, u32> = Ok("hello".to_string());
1193+
/// let y: Result<&mut str, &mut u32> = Ok("HELLO");
1194+
/// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
1195+
///
1196+
/// let mut x: Result<String, u32> = Err(42);
1197+
/// let y: Result<&mut str, &mut u32> = Err(&42);
1198+
/// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
1199+
/// ```
11761200
pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> {
11771201
self.as_mut().map(|t| t.deref_mut())
11781202
}
11791203
}
11801204

1181-
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
1205+
#[unstable(feature = "inner_deref", issue = "50264")]
11821206
impl<T, E: DerefMut> Result<T, E> {
1183-
/// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut T, &mut E::Target>`.
1207+
/// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut T, &mut <E as DerefMut>::Target>`.
11841208
///
1185-
/// Leaves the original `Result` in-place, creating a new one containing a mutable reference to
1186-
/// the `Err` type's `Deref::Target` type.
1209+
/// Coerces the [`Err`] variant of the original [`Result`] via [`DerefMut`](crate::ops::DerefMut)
1210+
/// and returns the new [`Result`].
11871211
pub fn as_deref_mut_err(&mut self) -> Result<&mut T, &mut E::Target> {
11881212
self.as_mut().map_err(|e| e.deref_mut())
11891213
}

src/libcore/tests/array.rs

+49
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,52 @@ fn iterator_drops() {
241241
}
242242
assert_eq!(i.get(), 5);
243243
}
244+
245+
// This test does not work on targets without panic=unwind support.
246+
// To work around this problem, test is marked is should_panic, so it will
247+
// be automagically skipped on unsuitable targets, such as
248+
// wasm32-unknown-unkown.
249+
//
250+
// It means that we use panic for indicating success.
251+
#[test]
252+
#[should_panic(expected = "test succeeded")]
253+
fn array_default_impl_avoids_leaks_on_panic() {
254+
use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
255+
static COUNTER: AtomicUsize = AtomicUsize::new(0);
256+
#[derive(Debug)]
257+
struct Bomb(usize);
258+
259+
impl Default for Bomb {
260+
fn default() -> Bomb {
261+
if COUNTER.load(Relaxed) == 3 {
262+
panic!("bomb limit exceeded");
263+
}
264+
265+
COUNTER.fetch_add(1, Relaxed);
266+
Bomb(COUNTER.load(Relaxed))
267+
}
268+
}
269+
270+
impl Drop for Bomb {
271+
fn drop(&mut self) {
272+
COUNTER.fetch_sub(1, Relaxed);
273+
}
274+
}
275+
276+
let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default());
277+
let panic_msg = match res {
278+
Ok(_) => unreachable!(),
279+
Err(p) => p.downcast::<&'static str>().unwrap(),
280+
};
281+
assert_eq!(*panic_msg, "bomb limit exceeded");
282+
// check that all bombs are successfully dropped
283+
assert_eq!(COUNTER.load(Relaxed), 0);
284+
panic!("test succeeded")
285+
}
286+
287+
#[test]
288+
fn empty_array_is_always_default() {
289+
struct DoesNotImplDefault;
290+
291+
let _arr = <[DoesNotImplDefault; 0]>::default();
292+
}

src/librustc_ast/ast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
//! additional metadata), and [`ItemKind`] (which represents a concrete type and contains
66
//! information specific to the type of the item).
77
//!
8-
//! Other module items that worth mentioning:
8+
//! Other module items worth mentioning:
99
//! - [`Ty`] and [`TyKind`]: A parsed Rust type.
1010
//! - [`Expr`] and [`ExprKind`]: A parsed Rust expression.
1111
//! - [`Pat`] and [`PatKind`]: A parsed Rust pattern. Patterns are often dual to expressions.

src/librustc_codegen_ssa/back/symbol_export.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,12 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
8989
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
9090
let def_id = tcx.hir().local_def_id(hir_id);
9191
let generics = tcx.generics_of(def_id);
92-
if !generics.requires_monomorphization(tcx) &&
93-
// Functions marked with #[inline] are only ever codegened
94-
// with "internal" linkage and are never exported.
95-
!Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
92+
if !generics.requires_monomorphization(tcx)
93+
// Functions marked with #[inline] are codegened with "internal"
94+
// linkage and are not exported unless marked with an extern
95+
// inidicator
96+
&& (!Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
97+
|| tcx.codegen_fn_attrs(def_id.to_def_id()).contains_extern_indicator())
9698
{
9799
Some(def_id)
98100
} else {

src/librustc_codegen_ssa/debuginfo/type_names.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ pub fn push_debuginfo_type_name<'tcx>(
195195
tcx.def_key(def_id).disambiguated_data.disambiguator
196196
));
197197
}
198-
ty::Error
198+
ty::Error(_)
199199
| ty::Infer(_)
200200
| ty::Placeholder(..)
201201
| ty::Projection(..)

src/librustc_codegen_ssa/mir/analyze.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,8 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
234234
self.visit_rvalue(rvalue, location);
235235
}
236236

237-
fn visit_terminator_kind(&mut self, kind: &mir::TerminatorKind<'tcx>, location: Location) {
238-
let check = match *kind {
237+
fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
238+
let check = match terminator.kind {
239239
mir::TerminatorKind::Call { func: mir::Operand::Constant(ref c), ref args, .. } => {
240240
match c.literal.ty.kind {
241241
ty::FnDef(did, _) => Some((did, args)),
@@ -259,7 +259,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
259259
}
260260
}
261261

262-
self.super_terminator_kind(kind, location);
262+
self.super_terminator(terminator, location);
263263
}
264264

265265
fn visit_place(&mut self, place: &mir::Place<'tcx>, context: PlaceContext, location: Location) {

src/librustc_codegen_ssa/mir/block.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -998,8 +998,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
998998
bx.unreachable();
999999
}
10001000

1001-
mir::TerminatorKind::Drop { location, target, unwind } => {
1002-
self.codegen_drop_terminator(helper, bx, location, target, unwind);
1001+
mir::TerminatorKind::Drop { place, target, unwind } => {
1002+
self.codegen_drop_terminator(helper, bx, place, target, unwind);
10031003
}
10041004

10051005
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {

src/librustc_error_codes/error_codes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,7 @@ E0752: include_str!("./error_codes/E0752.md"),
439439
E0753: include_str!("./error_codes/E0753.md"),
440440
E0754: include_str!("./error_codes/E0754.md"),
441441
E0758: include_str!("./error_codes/E0758.md"),
442+
E0759: include_str!("./error_codes/E0759.md"),
442443
E0760: include_str!("./error_codes/E0760.md"),
443444
E0761: include_str!("./error_codes/E0761.md"),
444445
E0762: include_str!("./error_codes/E0762.md"),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
A `'static` requirement in a return type involving a trait is not fulfilled.
2+
3+
Erroneous code examples:
4+
5+
```compile_fail,E0759
6+
use std::fmt::Debug;
7+
8+
fn foo(x: &i32) -> impl Debug {
9+
x
10+
}
11+
```
12+
13+
```compile_fail,E0759
14+
# use std::fmt::Debug;
15+
fn bar(x: &i32) -> Box<dyn Debug> {
16+
Box::new(x)
17+
}
18+
```
19+
20+
These examples have the same semantics as the following:
21+
22+
```compile_fail,E0759
23+
# use std::fmt::Debug;
24+
fn foo(x: &i32) -> impl Debug + 'static {
25+
x
26+
}
27+
```
28+
29+
```compile_fail,E0759
30+
# use std::fmt::Debug;
31+
fn bar(x: &i32) -> Box<dyn Debug + 'static> {
32+
Box::new(x)
33+
}
34+
```
35+
36+
Both [`dyn Trait`] and [`impl Trait`] in return types have a an implicit
37+
`'static` requirement, meaning that the value implementing them that is being
38+
returned has to be either a `'static` borrow or an owned value.
39+
40+
In order to change the requirement from `'static` to be a lifetime derived from
41+
its arguments, you can add an explicit bound, either to an anonymous lifetime
42+
`'_` or some appropriate named lifetime.
43+
44+
```
45+
# use std::fmt::Debug;
46+
fn foo(x: &i32) -> impl Debug + '_ {
47+
x
48+
}
49+
fn bar(x: &i32) -> Box<dyn Debug + '_> {
50+
Box::new(x)
51+
}
52+
```
53+
54+
These are equivalent to the following explicit lifetime annotations:
55+
56+
```
57+
# use std::fmt::Debug;
58+
fn foo<'a>(x: &'a i32) -> impl Debug + 'a {
59+
x
60+
}
61+
fn bar<'a>(x: &'a i32) -> Box<dyn Debug + 'a> {
62+
Box::new(x)
63+
}
64+
```
65+
66+
[`dyn Trait`]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types
67+
[`impl Trait`]: https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits

0 commit comments

Comments
 (0)