Skip to content

Commit dbf3ae7

Browse files
committed
Auto merge of #74019 - Manishearth:rollup-2st3jsk, r=Manishearth
Rollup of 12 pull requests Successful merges: - #73140 (Fallback to xml.etree.ElementTree) - #73670 (Add `format_args_capture` feature) - #73693 (Use exhaustive match in const_prop.rs) - #73845 (Use &raw in A|Rc::as_ptr) - #73861 (Create E0768) - #73881 (Standardize bibliographic citations in rustc API docs) - #73925 (Improve comments from #72617, as suggested by RalfJung) - #73949 ([mir-opt] Fix mis-optimization and other issues with the SimplifyArmIdentity pass) - #73984 (Edit docs for rustc_data_structures::graph::scc) - #73985 (Fix "getting started" link) - #73997 (fix typo) - #73999 (Bump mingw-check CI image from Ubuntu 16.04 to 18.04.) Failed merges: - #74000 (add `lazy_normalization_consts` feature gate) r? @ghost
2 parents 9a13ef2 + d69a846 commit dbf3ae7

Some content is hidden

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

45 files changed

+1859
-123
lines changed

CONTRIBUTING.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ Thank you for your interest in contributing to Rust!
44

55
To get started, read the [Getting Started] guide in the [rustc-dev-guide].
66

7-
[Getting Started]: https://rustc-dev-guide.rust-lang.org/getting-started.md
7+
[Getting Started]: https://rustc-dev-guide.rust-lang.org/getting-started.html
88
[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ The Rust build system uses a Python script called `x.py` to build the compiler,
2626
which manages the bootstrapping process. More information about it can be found
2727
by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild].
2828

29-
[gettingstarted]: https://rustc-dev-guide.rust-lang.org/getting-started.md
29+
[gettingstarted]: https://rustc-dev-guide.rust-lang.org/getting-started.html
3030
[rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html
3131

3232
### Building on a Unix-like system

src/ci/docker/host-x86_64/mingw-check/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM ubuntu:16.04
1+
FROM ubuntu:18.04
22

33
RUN apt-get update && apt-get install -y --no-install-recommends \
44
g++ \
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# `format_args_capture`
2+
3+
The tracking issue for this feature is: [#67984]
4+
5+
[#67984]: https://github.com/rust-lang/rust/issues/67984
6+
7+
------------------------
8+
9+
Enables `format_args!` (and macros which use `format_args!` in their implementation, such
10+
as `format!`, `print!` and `panic!`) to capture variables from the surrounding scope.
11+
This avoids the need to pass named parameters when the binding in question
12+
already exists in scope.
13+
14+
```rust
15+
#![feature(format_args_capture)]
16+
17+
let (person, species, name) = ("Charlie Brown", "dog", "Snoopy");
18+
19+
// captures named argument `person`
20+
print!("Hello {person}");
21+
22+
// captures named arguments `species` and `name`
23+
format!("The {species}'s name is {name}.");
24+
```
25+
26+
This also works for formatting parameters such as width and precision:
27+
28+
```rust
29+
#![feature(format_args_capture)]
30+
31+
let precision = 2;
32+
let s = format!("{:.precision$}", 1.324223);
33+
34+
assert_eq!(&s, "1.32");
35+
```
36+
37+
A non-exhaustive list of macros which benefit from this functionality include:
38+
- `format!`
39+
- `print!` and `println!`
40+
- `eprint!` and `eprintln!`
41+
- `write!` and `writeln!`
42+
- `panic!`
43+
- `unreachable!`
44+
- `unimplemented!`
45+
- `todo!`
46+
- `assert!` and similar
47+
- macros in many thirdparty crates, such as `log`

src/etc/htmldocck.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,10 @@
114114
from html.parser import HTMLParser
115115
except ImportError:
116116
from HTMLParser import HTMLParser
117-
from xml.etree import cElementTree as ET
117+
try:
118+
from xml.etree import cElementTree as ET
119+
except ImportError:
120+
from xml.etree import ElementTree as ET
118121

119122
try:
120123
from html.entities import name2codepoint

src/liballoc/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
#![feature(fundamental)]
101101
#![feature(internal_uninit_const)]
102102
#![feature(lang_items)]
103+
#![feature(layout_for_ptr)]
103104
#![feature(libc)]
104105
#![feature(negative_impls)]
105106
#![feature(new_uninit)]
@@ -109,6 +110,7 @@
109110
#![feature(pattern)]
110111
#![feature(ptr_internals)]
111112
#![feature(ptr_offset_from)]
113+
#![feature(raw_ref_op)]
112114
#![feature(rustc_attrs)]
113115
#![feature(receiver_trait)]
114116
#![feature(min_specialization)]

src/liballoc/rc.rs

+29-22
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ use core::hash::{Hash, Hasher};
245245
use core::intrinsics::abort;
246246
use core::iter;
247247
use core::marker::{self, PhantomData, Unpin, Unsize};
248-
use core::mem::{self, align_of, align_of_val, forget, size_of_val};
248+
use core::mem::{self, align_of_val_raw, forget, size_of_val};
249249
use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver};
250250
use core::pin::Pin;
251251
use core::ptr::{self, NonNull};
@@ -591,17 +591,11 @@ impl<T: ?Sized> Rc<T> {
591591
#[stable(feature = "weak_into_raw", since = "1.45.0")]
592592
pub fn as_ptr(this: &Self) -> *const T {
593593
let ptr: *mut RcBox<T> = NonNull::as_ptr(this.ptr);
594-
let fake_ptr = ptr as *mut T;
595594

596-
// SAFETY: This cannot go through Deref::deref.
597-
// Instead, we manually offset the pointer rather than manifesting a reference.
598-
// This is so that the returned pointer retains the same provenance as our pointer.
599-
// This is required so that e.g. `get_mut` can write through the pointer
600-
// after the Rc is recovered through `from_raw`.
601-
unsafe {
602-
let offset = data_offset(&(*ptr).value);
603-
set_data_ptr(fake_ptr, (ptr as *mut u8).offset(offset))
604-
}
595+
// SAFETY: This cannot go through Deref::deref or Rc::inner because
596+
// this is required to retain raw/mut provenance such that e.g. `get_mut` can
597+
// write through the pointer after the Rc is recovered through `from_raw`.
598+
unsafe { &raw const (*ptr).value }
605599
}
606600

607601
/// Constructs an `Rc<T>` from a raw pointer.
@@ -1647,6 +1641,7 @@ pub struct Weak<T: ?Sized> {
16471641
// `Weak::new` sets this to `usize::MAX` so that it doesn’t need
16481642
// to allocate space on the heap. That's not a value a real pointer
16491643
// will ever have because RcBox has alignment at least 2.
1644+
// This is only possible when `T: Sized`; unsized `T` never dangle.
16501645
ptr: NonNull<RcBox<T>>,
16511646
}
16521647

@@ -1708,9 +1703,18 @@ impl<T> Weak<T> {
17081703
/// [`null`]: ../../std/ptr/fn.null.html
17091704
#[stable(feature = "weak_into_raw", since = "1.45.0")]
17101705
pub fn as_ptr(&self) -> *const T {
1711-
let offset = data_offset_sized::<T>();
1712-
let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset);
1713-
ptr as *const T
1706+
let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr);
1707+
1708+
// SAFETY: we must offset the pointer manually, and said pointer may be
1709+
// a dangling weak (usize::MAX) if T is sized. data_offset is safe to call,
1710+
// because we know that a pointer to unsized T was derived from a real
1711+
// unsized T, as dangling weaks are only created for sized T. wrapping_offset
1712+
// is used so that we can use the same code path for the non-dangling
1713+
// unsized case and the potentially dangling sized case.
1714+
unsafe {
1715+
let offset = data_offset(ptr as *mut T);
1716+
set_data_ptr(ptr as *mut T, (ptr as *mut u8).wrapping_offset(offset))
1717+
}
17141718
}
17151719

17161720
/// Consumes the `Weak<T>` and turns it into a raw pointer.
@@ -2113,19 +2117,22 @@ impl<T: ?Sized> AsRef<T> for Rc<T> {
21132117
#[stable(feature = "pin", since = "1.33.0")]
21142118
impl<T: ?Sized> Unpin for Rc<T> {}
21152119

2120+
/// Get the offset within an `ArcInner` for
2121+
/// a payload of type described by a pointer.
2122+
///
2123+
/// # Safety
2124+
///
2125+
/// This has the same safety requirements as `align_of_val_raw`. In effect:
2126+
///
2127+
/// - This function is safe for any argument if `T` is sized, and
2128+
/// - if `T` is unsized, the pointer must have appropriate pointer metadata
2129+
/// aquired from the real instance that you are getting this offset for.
21162130
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
21172131
// Align the unsized value to the end of the `RcBox`.
21182132
// Because it is ?Sized, it will always be the last field in memory.
21192133
// Note: This is a detail of the current implementation of the compiler,
21202134
// and is not a guaranteed language detail. Do not rely on it outside of std.
2121-
unsafe { data_offset_align(align_of_val(&*ptr)) }
2122-
}
2123-
2124-
/// Computes the offset of the data field within `RcBox`.
2125-
///
2126-
/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
2127-
fn data_offset_sized<T>() -> isize {
2128-
data_offset_align(align_of::<T>())
2135+
unsafe { data_offset_align(align_of_val_raw(ptr)) }
21292136
}
21302137

21312138
#[inline]

src/liballoc/sync.rs

+28-22
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use core::hash::{Hash, Hasher};
1616
use core::intrinsics::abort;
1717
use core::iter;
1818
use core::marker::{PhantomData, Unpin, Unsize};
19-
use core::mem::{self, align_of, align_of_val, size_of_val};
19+
use core::mem::{self, align_of_val, size_of_val};
2020
use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver};
2121
use core::pin::Pin;
2222
use core::ptr::{self, NonNull};
@@ -267,6 +267,7 @@ pub struct Weak<T: ?Sized> {
267267
// `Weak::new` sets this to `usize::MAX` so that it doesn’t need
268268
// to allocate space on the heap. That's not a value a real pointer
269269
// will ever have because RcBox has alignment at least 2.
270+
// This is only possible when `T: Sized`; unsized `T` never dangle.
270271
ptr: NonNull<ArcInner<T>>,
271272
}
272273

@@ -590,17 +591,11 @@ impl<T: ?Sized> Arc<T> {
590591
#[stable(feature = "weak_into_raw", since = "1.45.0")]
591592
pub fn as_ptr(this: &Self) -> *const T {
592593
let ptr: *mut ArcInner<T> = NonNull::as_ptr(this.ptr);
593-
let fake_ptr = ptr as *mut T;
594594

595-
// SAFETY: This cannot go through Deref::deref.
596-
// Instead, we manually offset the pointer rather than manifesting a reference.
597-
// This is so that the returned pointer retains the same provenance as our pointer.
598-
// This is required so that e.g. `get_mut` can write through the pointer
599-
// after the Arc is recovered through `from_raw`.
600-
unsafe {
601-
let offset = data_offset(&(*ptr).data);
602-
set_data_ptr(fake_ptr, (ptr as *mut u8).offset(offset))
603-
}
595+
// SAFETY: This cannot go through Deref::deref or RcBoxPtr::inner because
596+
// this is required to retain raw/mut provenance such that e.g. `get_mut` can
597+
// write through the pointer after the Rc is recovered through `from_raw`.
598+
unsafe { &raw const (*ptr).data }
604599
}
605600

606601
/// Constructs an `Arc<T>` from a raw pointer.
@@ -1476,9 +1471,18 @@ impl<T> Weak<T> {
14761471
/// [`null`]: ../../std/ptr/fn.null.html
14771472
#[stable(feature = "weak_into_raw", since = "1.45.0")]
14781473
pub fn as_ptr(&self) -> *const T {
1479-
let offset = data_offset_sized::<T>();
1480-
let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset);
1481-
ptr as *const T
1474+
let ptr: *mut ArcInner<T> = NonNull::as_ptr(self.ptr);
1475+
1476+
// SAFETY: we must offset the pointer manually, and said pointer may be
1477+
// a dangling weak (usize::MAX) if T is sized. data_offset is safe to call,
1478+
// because we know that a pointer to unsized T was derived from a real
1479+
// unsized T, as dangling weaks are only created for sized T. wrapping_offset
1480+
// is used so that we can use the same code path for the non-dangling
1481+
// unsized case and the potentially dangling sized case.
1482+
unsafe {
1483+
let offset = data_offset(ptr as *mut T);
1484+
set_data_ptr(ptr as *mut T, (ptr as *mut u8).wrapping_offset(offset))
1485+
}
14821486
}
14831487

14841488
/// Consumes the `Weak<T>` and turns it into a raw pointer.
@@ -2270,7 +2274,16 @@ impl<T: ?Sized> AsRef<T> for Arc<T> {
22702274
#[stable(feature = "pin", since = "1.33.0")]
22712275
impl<T: ?Sized> Unpin for Arc<T> {}
22722276

2273-
/// Computes the offset of the data field within `ArcInner`.
2277+
/// Get the offset within an `ArcInner` for
2278+
/// a payload of type described by a pointer.
2279+
///
2280+
/// # Safety
2281+
///
2282+
/// This has the same safety requirements as `align_of_val_raw`. In effect:
2283+
///
2284+
/// - This function is safe for any argument if `T` is sized, and
2285+
/// - if `T` is unsized, the pointer must have appropriate pointer metadata
2286+
/// aquired from the real instance that you are getting this offset for.
22742287
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
22752288
// Align the unsized value to the end of the `ArcInner`.
22762289
// Because it is `?Sized`, it will always be the last field in memory.
@@ -2279,13 +2292,6 @@ unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
22792292
unsafe { data_offset_align(align_of_val(&*ptr)) }
22802293
}
22812294

2282-
/// Computes the offset of the data field within `ArcInner`.
2283-
///
2284-
/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
2285-
fn data_offset_sized<T>() -> isize {
2286-
data_offset_align(align_of::<T>())
2287-
}
2288-
22892295
#[inline]
22902296
fn data_offset_align(align: usize) -> isize {
22912297
let layout = Layout::new::<ArcInner<()>>();

src/libcore/marker.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ mod impls {
694694
)]
695695
#[lang = "discriminant_kind"]
696696
pub trait DiscriminantKind {
697-
/// The type of the dicriminant, which must satisfy the trait
697+
/// The type of the discriminant, which must satisfy the trait
698698
/// bounds required by `mem::Discriminant`.
699699
type Discriminant: Clone + Copy + Debug + Eq + PartialEq + Hash + Send + Sync + Unpin;
700700
}

src/librustc_ast_pretty/pp.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
//! This pretty-printer is a direct reimplementation of Philip Karlton's
2-
//! Mesa pretty-printer, as described in appendix A of
3-
//!
4-
//! ```text
5-
//! STAN-CS-79-770: "Pretty Printing", by Derek C. Oppen.
6-
//! Stanford Department of Computer Science, 1979.
7-
//! ```
2+
//! Mesa pretty-printer, as described in the appendix to
3+
//! Derek C. Oppen, "Pretty Printing" (1979),
4+
//! Stanford Computer Science Department STAN-CS-79-770,
5+
//! <http://i.stanford.edu/pub/cstr/reports/cs/tr/79/770/CS-TR-79-770.pdf>.
86
//!
97
//! The algorithm's aim is to break a stream into as few lines as possible
108
//! while respecting the indentation-consistency requirements of the enclosing

src/librustc_builtin_macros/format.rs

+53-4
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ struct Context<'a, 'b> {
107107
arg_spans: Vec<Span>,
108108
/// All the formatting arguments that have formatting flags set, in order for diagnostics.
109109
arg_with_formatting: Vec<parse::FormatSpec<'a>>,
110+
111+
/// Whether this format string came from a string literal, as opposed to a macro.
112+
is_literal: bool,
110113
}
111114

112115
/// Parses the arguments from the given list of tokens, returning the diagnostic
@@ -498,10 +501,55 @@ impl<'a, 'b> Context<'a, 'b> {
498501
self.verify_arg_type(Exact(idx), ty)
499502
}
500503
None => {
501-
let msg = format!("there is no argument named `{}`", name);
502-
let sp = *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp);
503-
let mut err = self.ecx.struct_span_err(sp, &msg[..]);
504-
err.emit();
504+
let capture_feature_enabled = self
505+
.ecx
506+
.ecfg
507+
.features
508+
.map_or(false, |features| features.format_args_capture);
509+
510+
// For the moment capturing variables from format strings expanded from macros is
511+
// disabled (see RFC #2795)
512+
let can_capture = capture_feature_enabled && self.is_literal;
513+
514+
if can_capture {
515+
// Treat this name as a variable to capture from the surrounding scope
516+
let idx = self.args.len();
517+
self.arg_types.push(Vec::new());
518+
self.arg_unique_types.push(Vec::new());
519+
self.args.push(
520+
self.ecx.expr_ident(self.fmtsp, Ident::new(name, self.fmtsp)),
521+
);
522+
self.names.insert(name, idx);
523+
self.verify_arg_type(Exact(idx), ty)
524+
} else {
525+
let msg = format!("there is no argument named `{}`", name);
526+
let sp = if self.is_literal {
527+
*self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp)
528+
} else {
529+
self.fmtsp
530+
};
531+
let mut err = self.ecx.struct_span_err(sp, &msg[..]);
532+
533+
if capture_feature_enabled && !self.is_literal {
534+
err.note(&format!(
535+
"did you intend to capture a variable `{}` from \
536+
the surrounding scope?",
537+
name
538+
));
539+
err.note(
540+
"to avoid ambiguity, `format_args!` cannot capture variables \
541+
when the format string is expanded from a macro",
542+
);
543+
} else if self.ecx.parse_sess().unstable_features.is_nightly_build() {
544+
err.help(&format!(
545+
"if you intended to capture `{}` from the surrounding scope, add \
546+
`#![feature(format_args_capture)]` to the crate attributes",
547+
name
548+
));
549+
}
550+
551+
err.emit();
552+
}
505553
}
506554
}
507555
}
@@ -951,6 +999,7 @@ pub fn expand_preparsed_format_args(
951999
invalid_refs: Vec::new(),
9521000
arg_spans,
9531001
arg_with_formatting: Vec::new(),
1002+
is_literal: parser.is_literal,
9541003
};
9551004

9561005
// This needs to happen *after* the Parser has consumed all pieces to create all the spans

src/librustc_data_structures/graph/dominators/mod.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
//! Algorithm citation:
2-
//! A Simple, Fast Dominance Algorithm.
3-
//! Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy
4-
//! Rice Computer Science TS-06-33870
5-
//! <https://www.cs.rice.edu/~keith/EMBED/dom.pdf>
1+
//! Finding the dominators in a control-flow graph.
2+
//!
3+
//! Algorithm based on Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy,
4+
//! "A Simple, Fast Dominance Algorithm",
5+
//! Rice Computer Science TS-06-33870,
6+
//! <https://www.cs.rice.edu/~keith/EMBED/dom.pdf>.
67
78
use super::iterate::reverse_post_order;
89
use super::ControlFlowGraph;

0 commit comments

Comments
 (0)