Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 12 pull requests #74019

Merged
merged 43 commits into from
Jul 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
291dce9
Fallback to xml.etree.ElementTree
tmiasko Jun 8, 2020
6b95f31
Add `format_args_capture` feature
davidhewitt Oct 12, 2019
8caf604
Improve messaging from PR feedback
davidhewitt Jun 27, 2020
a1217cb
Add `format_args_capture` to the unstable book
davidhewitt Jun 27, 2020
db539c6
Use raw_ref_op in A|Rc::as_ptr
CAD97 Jun 28, 2020
e4bdf47
Do not require ptr validity in rc::data_offset
CAD97 Jun 28, 2020
d8a9c61
Use impl for Weak::as_ptr that works for unsized T
CAD97 Jun 28, 2020
fc3dc72
Clarify safety comment for A|Rc::as_ptr
CAD97 Jun 30, 2020
0aecf3c
Fix invalid pointer deref in Weak::as_ptr
CAD97 Jun 30, 2020
aed88e1
Clarify when rc::data_offset is safe
CAD97 Jun 30, 2020
b4d0457
Use exhaustive match in const_prop.rs
wesleywiser Jun 24, 2020
1a03432
Amend wording of note
davidhewitt Jun 30, 2020
aac2f73
Improve comments from https://github.com/rust-lang/rust/pull/72617, a…
eduardosm Jul 1, 2020
10ebb2c
Update src/librustc_builtin_macros/format.rs
davidhewitt Jul 1, 2020
ac40d1e
Apply documentation review suggestions
CAD97 Jul 1, 2020
98789ac
Simplify Weak::as_ptr impl
CAD97 Jul 1, 2020
7498cad
Reclarify safety comments in Weak::as_ptr
CAD97 Jul 1, 2020
0f1adc8
Further improve comments in libstd/panicking.rs.
eduardosm Jul 2, 2020
1b5ac57
Note Weak.ptr never dangles sooner
CAD97 Jul 2, 2020
bdc1f40
Standardize bibliographic citations in rustc API docs
pierwill Jun 30, 2020
e3f599c
Add test for simplify-try misoptimization
wesleywiser Jun 22, 2020
9248d90
[mir-opt] Prevent mis-optimization when SimplifyArmIdentity runs
wesleywiser Jun 22, 2020
24bfdc9
Fix debuginfo so that it points to the correct local
wesleywiser Jun 21, 2020
e16d6a6
Fix missing return in `optimization_applies()`
wesleywiser Jun 21, 2020
df43dcd
Fix "getting started" link
e00E Jul 3, 2020
3ed320e
fix typo
lcnr Jul 3, 2020
3bb6dc7
Bump mingw-check CI image from Ubuntu 16.04 to 18.04.
eddyb Jul 3, 2020
93d662f
Ignore test with panic on wasm targets
davidhewitt Jul 3, 2020
20caf63
Edit docs for rustc_data_structures::graph::scc
pierwill Jun 30, 2020
d64a4b5
Create new E0768 error code for "no valid digits found for number" error
GuillaumeGomez Jul 3, 2020
6970c92
Update UI tests
GuillaumeGomez Jul 3, 2020
df8f551
Rollup merge of #73140 - tmiasko:element-tree, r=GuillaumeGomez
Manishearth Jul 4, 2020
4a8d9ea
Rollup merge of #73670 - davidhewitt:format-args-capture, r=varkor
Manishearth Jul 4, 2020
50dcefc
Rollup merge of #73693 - wesleywiser:const_prop_exhaustive_match, r=o…
Manishearth Jul 4, 2020
9a659c5
Rollup merge of #73845 - CAD97:weak-as-unsized-ptr, r=RalfJung
Manishearth Jul 4, 2020
6339abd
Rollup merge of #73861 - GuillaumeGomez:create-e0767, r=Dylan-DPC
Manishearth Jul 4, 2020
d46de10
Rollup merge of #73881 - pierwill:pierwill-citations, r=jonas-schievink
Manishearth Jul 4, 2020
9d0ca38
Rollup merge of #73925 - eduardosm:improve-pr72617-comments, r=RalfJung
Manishearth Jul 4, 2020
60cad20
Rollup merge of #73949 - wesleywiser:simplify_try_fixes, r=oli-obk
Manishearth Jul 4, 2020
70c4b2f
Rollup merge of #73984 - pierwill:pierwill-tarjan, r=jonas-schievink
Manishearth Jul 4, 2020
e4c505b
Rollup merge of #73985 - e00E:fix-getting-started-link, r=jonas-schie…
Manishearth Jul 4, 2020
e005c97
Rollup merge of #73997 - rust-lang:lcnr-patch-1, r=jonas-schievink
Manishearth Jul 4, 2020
d69a846
Rollup merge of #73999 - eddyb:svv-prereq, r=Mark-Simulacrum
Manishearth Jul 4, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ Thank you for your interest in contributing to Rust!

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

[Getting Started]: https://rustc-dev-guide.rust-lang.org/getting-started.md
[Getting Started]: https://rustc-dev-guide.rust-lang.org/getting-started.html
[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ The Rust build system uses a Python script called `x.py` to build the compiler,
which manages the bootstrapping process. More information about it can be found
by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild].

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

### Building on a Unix-like system
Expand Down
2 changes: 1 addition & 1 deletion src/ci/docker/mingw-check/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ubuntu:16.04
FROM ubuntu:18.04

RUN apt-get update && apt-get install -y --no-install-recommends \
g++ \
Expand Down
47 changes: 47 additions & 0 deletions src/doc/unstable-book/src/library-features/format-args-capture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# `format_args_capture`

The tracking issue for this feature is: [#67984]

[#67984]: https://github.com/rust-lang/rust/issues/67984

------------------------

Enables `format_args!` (and macros which use `format_args!` in their implementation, such
as `format!`, `print!` and `panic!`) to capture variables from the surrounding scope.
This avoids the need to pass named parameters when the binding in question
already exists in scope.

```rust
#![feature(format_args_capture)]

let (person, species, name) = ("Charlie Brown", "dog", "Snoopy");

// captures named argument `person`
print!("Hello {person}");

// captures named arguments `species` and `name`
format!("The {species}'s name is {name}.");
```

This also works for formatting parameters such as width and precision:

```rust
#![feature(format_args_capture)]

let precision = 2;
let s = format!("{:.precision$}", 1.324223);

assert_eq!(&s, "1.32");
```

A non-exhaustive list of macros which benefit from this functionality include:
- `format!`
- `print!` and `println!`
- `eprint!` and `eprintln!`
- `write!` and `writeln!`
- `panic!`
- `unreachable!`
- `unimplemented!`
- `todo!`
- `assert!` and similar
- macros in many thirdparty crates, such as `log`
5 changes: 4 additions & 1 deletion src/etc/htmldocck.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@
from html.parser import HTMLParser
except ImportError:
from HTMLParser import HTMLParser
from xml.etree import cElementTree as ET
try:
from xml.etree import cElementTree as ET
except ImportError:
from xml.etree import ElementTree as ET

try:
from html.entities import name2codepoint
Expand Down
2 changes: 2 additions & 0 deletions src/liballoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
#![feature(fundamental)]
#![feature(internal_uninit_const)]
#![feature(lang_items)]
#![feature(layout_for_ptr)]
#![feature(libc)]
#![feature(negative_impls)]
#![feature(new_uninit)]
Expand All @@ -109,6 +110,7 @@
#![feature(pattern)]
#![feature(ptr_internals)]
#![feature(ptr_offset_from)]
#![feature(raw_ref_op)]
#![feature(rustc_attrs)]
#![feature(receiver_trait)]
#![feature(min_specialization)]
Expand Down
51 changes: 29 additions & 22 deletions src/liballoc/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ use core::hash::{Hash, Hasher};
use core::intrinsics::abort;
use core::iter;
use core::marker::{self, PhantomData, Unpin, Unsize};
use core::mem::{self, align_of, align_of_val, forget, size_of_val};
use core::mem::{self, align_of_val_raw, forget, size_of_val};
use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver};
use core::pin::Pin;
use core::ptr::{self, NonNull};
Expand Down Expand Up @@ -591,17 +591,11 @@ impl<T: ?Sized> Rc<T> {
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub fn as_ptr(this: &Self) -> *const T {
let ptr: *mut RcBox<T> = NonNull::as_ptr(this.ptr);
let fake_ptr = ptr as *mut T;

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

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

Expand Down Expand Up @@ -1708,9 +1703,18 @@ impl<T> Weak<T> {
/// [`null`]: ../../std/ptr/fn.null.html
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub fn as_ptr(&self) -> *const T {
let offset = data_offset_sized::<T>();
let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset);
ptr as *const T
let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr);

// SAFETY: we must offset the pointer manually, and said pointer may be
// a dangling weak (usize::MAX) if T is sized. data_offset is safe to call,
// because we know that a pointer to unsized T was derived from a real
// unsized T, as dangling weaks are only created for sized T. wrapping_offset
// is used so that we can use the same code path for the non-dangling
// unsized case and the potentially dangling sized case.
unsafe {
let offset = data_offset(ptr as *mut T);
set_data_ptr(ptr as *mut T, (ptr as *mut u8).wrapping_offset(offset))
}
}

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

/// Get the offset within an `ArcInner` for
/// a payload of type described by a pointer.
///
/// # Safety
///
/// This has the same safety requirements as `align_of_val_raw`. In effect:
///
/// - This function is safe for any argument if `T` is sized, and
/// - if `T` is unsized, the pointer must have appropriate pointer metadata
/// aquired from the real instance that you are getting this offset for.
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
// Align the unsized value to the end of the `RcBox`.
// Because it is ?Sized, it will always be the last field in memory.
// Note: This is a detail of the current implementation of the compiler,
// and is not a guaranteed language detail. Do not rely on it outside of std.
unsafe { data_offset_align(align_of_val(&*ptr)) }
}

/// Computes the offset of the data field within `RcBox`.
///
/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
fn data_offset_sized<T>() -> isize {
data_offset_align(align_of::<T>())
unsafe { data_offset_align(align_of_val_raw(ptr)) }
}

#[inline]
Expand Down
50 changes: 28 additions & 22 deletions src/liballoc/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use core::hash::{Hash, Hasher};
use core::intrinsics::abort;
use core::iter;
use core::marker::{PhantomData, Unpin, Unsize};
use core::mem::{self, align_of, align_of_val, size_of_val};
use core::mem::{self, align_of_val, size_of_val};
use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver};
use core::pin::Pin;
use core::ptr::{self, NonNull};
Expand Down Expand Up @@ -267,6 +267,7 @@ pub struct Weak<T: ?Sized> {
// `Weak::new` sets this to `usize::MAX` so that it doesn’t need
// to allocate space on the heap. That's not a value a real pointer
// will ever have because RcBox has alignment at least 2.
// This is only possible when `T: Sized`; unsized `T` never dangle.
ptr: NonNull<ArcInner<T>>,
}

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

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

/// Constructs an `Arc<T>` from a raw pointer.
Expand Down Expand Up @@ -1476,9 +1471,18 @@ impl<T> Weak<T> {
/// [`null`]: ../../std/ptr/fn.null.html
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub fn as_ptr(&self) -> *const T {
let offset = data_offset_sized::<T>();
let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset);
ptr as *const T
let ptr: *mut ArcInner<T> = NonNull::as_ptr(self.ptr);

// SAFETY: we must offset the pointer manually, and said pointer may be
// a dangling weak (usize::MAX) if T is sized. data_offset is safe to call,
// because we know that a pointer to unsized T was derived from a real
// unsized T, as dangling weaks are only created for sized T. wrapping_offset
// is used so that we can use the same code path for the non-dangling
// unsized case and the potentially dangling sized case.
unsafe {
let offset = data_offset(ptr as *mut T);
set_data_ptr(ptr as *mut T, (ptr as *mut u8).wrapping_offset(offset))
}
}

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

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

/// Computes the offset of the data field within `ArcInner`.
///
/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
fn data_offset_sized<T>() -> isize {
data_offset_align(align_of::<T>())
}

#[inline]
fn data_offset_align(align: usize) -> isize {
let layout = Layout::new::<ArcInner<()>>();
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ mod impls {
)]
#[lang = "discriminant_kind"]
pub trait DiscriminantKind {
/// The type of the dicriminant, which must satisfy the trait
/// The type of the discriminant, which must satisfy the trait
/// bounds required by `mem::Discriminant`.
type Discriminant: Clone + Copy + Debug + Eq + PartialEq + Hash + Send + Sync + Unpin;
}
Expand Down
10 changes: 4 additions & 6 deletions src/librustc_ast_pretty/pp.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
//! This pretty-printer is a direct reimplementation of Philip Karlton's
//! Mesa pretty-printer, as described in appendix A of
//!
//! ```text
//! STAN-CS-79-770: "Pretty Printing", by Derek C. Oppen.
//! Stanford Department of Computer Science, 1979.
//! ```
//! Mesa pretty-printer, as described in the appendix to
//! Derek C. Oppen, "Pretty Printing" (1979),
//! Stanford Computer Science Department STAN-CS-79-770,
//! <http://i.stanford.edu/pub/cstr/reports/cs/tr/79/770/CS-TR-79-770.pdf>.
//!
//! The algorithm's aim is to break a stream into as few lines as possible
//! while respecting the indentation-consistency requirements of the enclosing
Expand Down
57 changes: 53 additions & 4 deletions src/librustc_builtin_macros/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ struct Context<'a, 'b> {
arg_spans: Vec<Span>,
/// All the formatting arguments that have formatting flags set, in order for diagnostics.
arg_with_formatting: Vec<parse::FormatSpec<'a>>,

/// Whether this format string came from a string literal, as opposed to a macro.
is_literal: bool,
}

/// Parses the arguments from the given list of tokens, returning the diagnostic
Expand Down Expand Up @@ -498,10 +501,55 @@ impl<'a, 'b> Context<'a, 'b> {
self.verify_arg_type(Exact(idx), ty)
}
None => {
let msg = format!("there is no argument named `{}`", name);
let sp = *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp);
let mut err = self.ecx.struct_span_err(sp, &msg[..]);
err.emit();
let capture_feature_enabled = self
.ecx
.ecfg
.features
.map_or(false, |features| features.format_args_capture);

// For the moment capturing variables from format strings expanded from macros is
// disabled (see RFC #2795)
let can_capture = capture_feature_enabled && self.is_literal;

if can_capture {
// Treat this name as a variable to capture from the surrounding scope
let idx = self.args.len();
self.arg_types.push(Vec::new());
self.arg_unique_types.push(Vec::new());
self.args.push(
self.ecx.expr_ident(self.fmtsp, Ident::new(name, self.fmtsp)),
);
self.names.insert(name, idx);
self.verify_arg_type(Exact(idx), ty)
} else {
let msg = format!("there is no argument named `{}`", name);
let sp = if self.is_literal {
*self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp)
} else {
self.fmtsp
};
let mut err = self.ecx.struct_span_err(sp, &msg[..]);

if capture_feature_enabled && !self.is_literal {
err.note(&format!(
"did you intend to capture a variable `{}` from \
the surrounding scope?",
name
));
err.note(
"to avoid ambiguity, `format_args!` cannot capture variables \
when the format string is expanded from a macro",
);
} else if self.ecx.parse_sess().unstable_features.is_nightly_build() {
err.help(&format!(
"if you intended to capture `{}` from the surrounding scope, add \
`#![feature(format_args_capture)]` to the crate attributes",
name
));
}

err.emit();
}
}
}
}
Expand Down Expand Up @@ -951,6 +999,7 @@ pub fn expand_preparsed_format_args(
invalid_refs: Vec::new(),
arg_spans,
arg_with_formatting: Vec::new(),
is_literal: parser.is_literal,
};

// This needs to happen *after* the Parser has consumed all pieces to create all the spans
Expand Down
11 changes: 6 additions & 5 deletions src/librustc_data_structures/graph/dominators/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
//! Algorithm citation:
//! A Simple, Fast Dominance Algorithm.
//! Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy
//! Rice Computer Science TS-06-33870
//! <https://www.cs.rice.edu/~keith/EMBED/dom.pdf>
//! Finding the dominators in a control-flow graph.
//!
//! Algorithm based on Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy,
//! "A Simple, Fast Dominance Algorithm",
//! Rice Computer Science TS-06-33870,
//! <https://www.cs.rice.edu/~keith/EMBED/dom.pdf>.

use super::iterate::reverse_post_order;
use super::ControlFlowGraph;
Expand Down
Loading