1
Fork 0

Auto merge of #58644 - Centril:rollup, r=Centril

Rollup of 17 pull requests

Successful merges:

 - #57656 (Deprecate the unstable Vec::resize_default)
 - #58059 (deprecate before_exec in favor of unsafe pre_exec)
 - #58064 (override `VecDeque::try_rfold`, also update iterator)
 - #58198 (Suggest removing parentheses surrounding lifetimes)
 - #58431 (fix overlapping references in BTree)
 - #58555 (Add a note about 2018e if someone uses `try {` in 2015e)
 - #58588 (remove a bit of dead code)
 - #58589 (cleanup macro after 2018 transition)
 - #58591 (Dedup a rustdoc diagnostic construction)
 - #58600 (fix small documentation typo)
 - #58601 (Search for target_triple.json only if builtin target not found)
 - #58606 (Docs: put Future trait into spotlight)
 - #58607 (Fixes #58586: Make E0505 erronous example fail for the 2018 edition)
 - #58615 (miri: explain why we use static alignment in ref-to-place conversion)
 - #58620 (introduce benchmarks of BTreeSet.intersection)
 - #58621 (Update miri links)
 - #58632 (Make std feature list sorted)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-02-22 21:32:15 +00:00
commit 082c86175f
29 changed files with 544 additions and 212 deletions

View file

@ -161,10 +161,10 @@ it can be found [here][rctd].
Currently building Rust will also build the following external projects: Currently building Rust will also build the following external projects:
* [clippy](https://github.com/rust-lang-nursery/rust-clippy) * [clippy](https://github.com/rust-lang/rust-clippy)
* [miri](https://github.com/solson/miri) * [miri](https://github.com/rust-lang/miri)
* [rustfmt](https://github.com/rust-lang-nursery/rustfmt) * [rustfmt](https://github.com/rust-lang/rustfmt)
* [rls](https://github.com/rust-lang-nursery/rls/) * [rls](https://github.com/rust-lang/rls/)
We allow breakage of these tools in the nightly channel. Maintainers of these We allow breakage of these tools in the nightly channel. Maintainers of these
projects will be notified of the breakages and should fix them as soon as projects will be notified of the breakages and should fix them as soon as
@ -191,9 +191,9 @@ before the PR is merged.
Rust's build system builds a number of tools that make use of the Rust's build system builds a number of tools that make use of the
internals of the compiler. This includes internals of the compiler. This includes
[Clippy](https://github.com/rust-lang-nursery/rust-clippy), [Clippy](https://github.com/rust-lang/rust-clippy),
[RLS](https://github.com/rust-lang-nursery/rls) and [RLS](https://github.com/rust-lang/rls) and
[rustfmt](https://github.com/rust-lang-nursery/rustfmt). If these tools [rustfmt](https://github.com/rust-lang/rustfmt). If these tools
break because of your changes, you may run into a sort of "chicken and egg" break because of your changes, you may run into a sort of "chicken and egg"
problem. These tools rely on the latest compiler to be built so you can't update problem. These tools rely on the latest compiler to be built so you can't update
them to reflect your changes to the compiler until those changes are merged into them to reflect your changes to the compiler until those changes are merged into
@ -253,10 +253,10 @@ to complete a few more steps which are outlined with their rationale below.
*(This error may change in the future to include more information.)* *(This error may change in the future to include more information.)*
``` ```
error: failed to resolve patches for `https://github.com/rust-lang-nursery/rustfmt` error: failed to resolve patches for `https://github.com/rust-lang/rustfmt`
Caused by: Caused by:
patch for `rustfmt-nightly` in `https://github.com/rust-lang-nursery/rustfmt` did not resolve to any crates patch for `rustfmt-nightly` in `https://github.com/rust-lang/rustfmt` did not resolve to any crates
failed to run: ~/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo build --manifest-path ~/rust/src/bootstrap/Cargo.toml failed to run: ~/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo build --manifest-path ~/rust/src/bootstrap/Cargo.toml
``` ```

View file

@ -244,7 +244,7 @@ disambiguate the error type:
/// use std::io; /// use std::io;
/// let mut input = String::new(); /// let mut input = String::new();
/// io::stdin().read_line(&mut input)?; /// io::stdin().read_line(&mut input)?;
/// # Ok::<(), io:Error>(()) /// # Ok::<(), io::Error>(())
/// ``` /// ```
``` ```

View file

@ -1 +1,2 @@
mod map; mod map;
mod set;

View file

@ -0,0 +1,88 @@
use std::collections::BTreeSet;
use rand::{thread_rng, Rng};
use test::{black_box, Bencher};
fn random(n1: u32, n2: u32) -> [BTreeSet<usize>; 2] {
let mut rng = thread_rng();
let mut set1 = BTreeSet::new();
let mut set2 = BTreeSet::new();
for _ in 0..n1 {
let i = rng.gen::<usize>();
set1.insert(i);
}
for _ in 0..n2 {
let i = rng.gen::<usize>();
set2.insert(i);
}
[set1, set2]
}
fn staggered(n1: u32, n2: u32) -> [BTreeSet<u32>; 2] {
let mut even = BTreeSet::new();
let mut odd = BTreeSet::new();
for i in 0..n1 {
even.insert(i * 2);
}
for i in 0..n2 {
odd.insert(i * 2 + 1);
}
[even, odd]
}
fn neg_vs_pos(n1: u32, n2: u32) -> [BTreeSet<i32>; 2] {
let mut neg = BTreeSet::new();
let mut pos = BTreeSet::new();
for i in -(n1 as i32)..=-1 {
neg.insert(i);
}
for i in 1..=(n2 as i32) {
pos.insert(i);
}
[neg, pos]
}
fn pos_vs_neg(n1: u32, n2: u32) -> [BTreeSet<i32>; 2] {
let mut neg = BTreeSet::new();
let mut pos = BTreeSet::new();
for i in -(n1 as i32)..=-1 {
neg.insert(i);
}
for i in 1..=(n2 as i32) {
pos.insert(i);
}
[pos, neg]
}
macro_rules! set_intersection_bench {
($name: ident, $sets: expr) => {
#[bench]
pub fn $name(b: &mut Bencher) {
// setup
let sets = $sets;
// measure
b.iter(|| {
let x = sets[0].intersection(&sets[1]).count();
black_box(x);
})
}
};
}
set_intersection_bench! {intersect_random_100, random(100, 100)}
set_intersection_bench! {intersect_random_10k, random(10_000, 10_000)}
set_intersection_bench! {intersect_random_10_vs_10k, random(10, 10_000)}
set_intersection_bench! {intersect_random_10k_vs_10, random(10_000, 10)}
set_intersection_bench! {intersect_staggered_100, staggered(100, 100)}
set_intersection_bench! {intersect_staggered_10k, staggered(10_000, 10_000)}
set_intersection_bench! {intersect_staggered_10_vs_10k, staggered(10, 10_000)}
set_intersection_bench! {intersect_staggered_10k_vs_10, staggered(10_000, 10)}
set_intersection_bench! {intersect_neg_vs_pos_100, neg_vs_pos(100, 100)}
set_intersection_bench! {intersect_neg_vs_pos_10k, neg_vs_pos(10_000, 10_000)}
set_intersection_bench! {intersect_neg_vs_pos_10_vs_10k,neg_vs_pos(10, 10_000)}
set_intersection_bench! {intersect_neg_vs_pos_10k_vs_10,neg_vs_pos(10_000, 10)}
set_intersection_bench! {intersect_pos_vs_neg_100, pos_vs_neg(100, 100)}
set_intersection_bench! {intersect_pos_vs_neg_10k, pos_vs_neg(10_000, 10_000)}
set_intersection_bench! {intersect_pos_vs_neg_10_vs_10k,pos_vs_neg(10, 10_000)}
set_intersection_bench! {intersect_pos_vs_neg_10k_vs_10,pos_vs_neg(10_000, 10)}

View file

@ -45,3 +45,10 @@ fn bench_mut_iter_1000(b: &mut Bencher) {
black_box(sum); black_box(sum);
}) })
} }
#[bench]
fn bench_try_fold(b: &mut Bencher) {
let ring: VecDeque<_> = (0..1000).collect();
b.iter(|| black_box(ring.iter().try_fold(0, |a, b| Some(a + b))))
}

View file

@ -1634,9 +1634,11 @@ impl<'a, K, V> RangeMut<'a, K, V> {
let mut cur_handle = match handle.right_kv() { let mut cur_handle = match handle.right_kv() {
Ok(kv) => { Ok(kv) => {
let (k, v) = ptr::read(&kv).into_kv_mut(); self.front = ptr::read(&kv).right_edge();
self.front = kv.right_edge(); // Doing the descend invalidates the references returned by `into_kv_mut`,
return (k, v); // so we have to do this last.
let (k, v) = kv.into_kv_mut();
return (k, v); // coerce k from `&mut K` to `&K`
} }
Err(last_edge) => { Err(last_edge) => {
let next_level = last_edge.into_node().ascend().ok(); let next_level = last_edge.into_node().ascend().ok();
@ -1647,9 +1649,11 @@ impl<'a, K, V> RangeMut<'a, K, V> {
loop { loop {
match cur_handle.right_kv() { match cur_handle.right_kv() {
Ok(kv) => { Ok(kv) => {
let (k, v) = ptr::read(&kv).into_kv_mut(); self.front = first_leaf_edge(ptr::read(&kv).right_edge().descend());
self.front = first_leaf_edge(kv.right_edge().descend()); // Doing the descend invalidates the references returned by `into_kv_mut`,
return (k, v); // so we have to do this last.
let (k, v) = kv.into_kv_mut();
return (k, v); // coerce k from `&mut K` to `&K`
} }
Err(last_edge) => { Err(last_edge) => {
let next_level = last_edge.into_node().ascend().ok(); let next_level = last_edge.into_node().ascend().ok();
@ -1680,9 +1684,11 @@ impl<'a, K, V> RangeMut<'a, K, V> {
let mut cur_handle = match handle.left_kv() { let mut cur_handle = match handle.left_kv() {
Ok(kv) => { Ok(kv) => {
let (k, v) = ptr::read(&kv).into_kv_mut(); self.back = ptr::read(&kv).left_edge();
self.back = kv.left_edge(); // Doing the descend invalidates the references returned by `into_kv_mut`,
return (k, v); // so we have to do this last.
let (k, v) = kv.into_kv_mut();
return (k, v); // coerce k from `&mut K` to `&K`
} }
Err(last_edge) => { Err(last_edge) => {
let next_level = last_edge.into_node().ascend().ok(); let next_level = last_edge.into_node().ascend().ok();
@ -1693,9 +1699,11 @@ impl<'a, K, V> RangeMut<'a, K, V> {
loop { loop {
match cur_handle.left_kv() { match cur_handle.left_kv() {
Ok(kv) => { Ok(kv) => {
let (k, v) = ptr::read(&kv).into_kv_mut(); self.back = last_leaf_edge(ptr::read(&kv).left_edge().descend());
self.back = last_leaf_edge(kv.left_edge().descend()); // Doing the descend invalidates the references returned by `into_kv_mut`,
return (k, v); // so we have to do this last.
let (k, v) = kv.into_kv_mut();
return (k, v); // coerce k from `&mut K` to `&K`
} }
Err(last_edge) => { Err(last_edge) => {
let next_level = last_edge.into_node().ascend().ok(); let next_level = last_edge.into_node().ascend().ok();

View file

@ -645,6 +645,8 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
} }
fn into_key_slice_mut(mut self) -> &'a mut [K] { fn into_key_slice_mut(mut self) -> &'a mut [K] {
// Same as for `into_key_slice` above, we try to avoid a run-time check
// (the alignment comparison will usually be performed at compile-time).
if mem::align_of::<K>() > mem::align_of::<LeafNode<(), ()>>() && self.is_shared_root() { if mem::align_of::<K>() > mem::align_of::<LeafNode<(), ()>>() && self.is_shared_root() {
&mut [] &mut []
} else { } else {
@ -667,9 +669,26 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
} }
} }
fn into_slices_mut(self) -> (&'a mut [K], &'a mut [V]) { fn into_slices_mut(mut self) -> (&'a mut [K], &'a mut [V]) {
let k = unsafe { ptr::read(&self) }; debug_assert!(!self.is_shared_root());
(k.into_key_slice_mut(), self.into_val_slice_mut()) // We cannot use the getters here, because calling the second one
// invalidates the reference returned by the first.
// More precisely, it is the call to `len` that is the culprit,
// because that creates a shared reference to the header, which *can*
// overlap with the keys (and even the values, for ZST keys).
unsafe {
let len = self.len();
let leaf = self.as_leaf_mut();
let keys = slice::from_raw_parts_mut(
MaybeUninit::first_ptr_mut(&mut (*leaf).keys),
len
);
let vals = slice::from_raw_parts_mut(
MaybeUninit::first_ptr_mut(&mut (*leaf).vals),
len
);
(keys, vals)
}
} }
} }

View file

@ -2170,12 +2170,29 @@ impl<'a, T> Iterator for Iter<'a, T> {
back.iter().fold(accum, &mut f) back.iter().fold(accum, &mut f)
} }
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> where
Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Ok = B>,
{ {
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); let (mut iter, final_res);
let accum = front.iter().try_fold(init, &mut f)?; if self.tail <= self.head {
back.iter().try_fold(accum, &mut f) // single slice self.ring[self.tail..self.head]
iter = self.ring[self.tail..self.head].iter();
final_res = iter.try_fold(init, &mut f);
} else {
// two slices: self.ring[self.tail..], self.ring[..self.head]
let (front, back) = self.ring.split_at(self.tail);
let mut back_iter = back.iter();
let res = back_iter.try_fold(init, &mut f);
let len = self.ring.len();
self.tail = (self.ring.len() - back_iter.len()) & (len - 1);
iter = front[..self.head].iter();
final_res = iter.try_fold(res?, &mut f);
}
self.tail = self.head - iter.len();
final_res
} }
} }
@ -2197,6 +2214,30 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
accum = back.iter().rfold(accum, &mut f); accum = back.iter().rfold(accum, &mut f);
front.iter().rfold(accum, &mut f) front.iter().rfold(accum, &mut f)
} }
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
where
Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Ok = B>,
{
let (mut iter, final_res);
if self.tail <= self.head {
// single slice self.ring[self.tail..self.head]
iter = self.ring[self.tail..self.head].iter();
final_res = iter.try_rfold(init, &mut f);
} else {
// two slices: self.ring[self.tail..], self.ring[..self.head]
let (front, back) = self.ring.split_at(self.tail);
let mut front_iter = front[..self.head].iter();
let res = front_iter.try_rfold(init, &mut f);
self.head = front_iter.len();
iter = back.iter();
final_res = iter.try_rfold(res?, &mut f);
}
self.head = self.tail + iter.len();
final_res
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]

View file

@ -1465,6 +1465,15 @@ fn test_try_fold_unit() {
assert_eq!(Some(()), v.into_iter().try_fold((), |(), ()| Some(()))); assert_eq!(Some(()), v.into_iter().try_fold((), |(), ()| Some(())));
} }
#[test]
fn test_try_fold_unit_none() {
let v: std::collections::VecDeque<()> = [(); 10].iter().cloned().collect();
let mut iter = v.into_iter();
assert!(iter.try_fold((), |_, _| None).is_none());
assert_eq!(iter.len(), 9);
}
#[test] #[test]
fn test_try_fold_rotated() { fn test_try_fold_rotated() {
let mut v: VecDeque<_> = (0..12).collect(); let mut v: VecDeque<_> = (0..12).collect();
@ -1477,3 +1486,58 @@ fn test_try_fold_rotated() {
assert_eq!(Ok::<_, ()>(66), v.iter().try_fold(0, |a, b| Ok(a + b))); assert_eq!(Ok::<_, ()>(66), v.iter().try_fold(0, |a, b| Ok(a + b)));
} }
} }
#[test]
fn test_try_fold_moves_iter() {
let v: VecDeque<_> = [10, 20, 30, 40, 100, 60, 70, 80, 90].iter().collect();
let mut iter = v.into_iter();
assert_eq!(iter.try_fold(0_i8, |acc, &x| acc.checked_add(x)), None);
assert_eq!(iter.next(), Some(&60));
}
#[test]
fn test_try_fold_exhaust_wrap() {
let mut v = VecDeque::with_capacity(7);
v.push_back(1);
v.push_back(1);
v.push_back(1);
v.pop_front();
v.pop_front();
let mut iter = v.iter();
let _ = iter.try_fold(0, |_, _| Some(1));
assert!(iter.is_empty());
}
#[test]
fn test_try_fold_wraparound() {
let mut v = VecDeque::with_capacity(8);
v.push_back(7);
v.push_back(8);
v.push_back(9);
v.push_front(2);
v.push_front(1);
let mut iter = v.iter();
let _ = iter.find(|&&x| x == 2);
assert_eq!(Some(&7), iter.next());
}
#[test]
fn test_try_rfold_rotated() {
let mut v: VecDeque<_> = (0..12).collect();
for n in 0..10 {
if n & 1 == 0 {
v.rotate_left(n);
} else {
v.rotate_right(n);
}
assert_eq!(Ok::<_, ()>(66), v.iter().try_rfold(0, |a, b| Ok(a + b)));
}
}
#[test]
fn test_try_rfold_moves_iter() {
let v : VecDeque<_> = [10, 20, 30, 40, 100, 60, 70, 80, 90].iter().collect();
let mut iter = v.into_iter();
assert_eq!(iter.try_rfold(0_i8, |acc, &x| acc.checked_add(x)), None);
assert_eq!(iter.next_back(), Some(&70));
}

View file

@ -1365,6 +1365,7 @@ impl<T: Default> Vec<T> {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// # #![allow(deprecated)]
/// #![feature(vec_resize_default)] /// #![feature(vec_resize_default)]
/// ///
/// let mut vec = vec![1, 2, 3]; /// let mut vec = vec![1, 2, 3];
@ -1381,6 +1382,9 @@ impl<T: Default> Vec<T> {
/// [`Default`]: ../../std/default/trait.Default.html /// [`Default`]: ../../std/default/trait.Default.html
/// [`Clone`]: ../../std/clone/trait.Clone.html /// [`Clone`]: ../../std/clone/trait.Clone.html
#[unstable(feature = "vec_resize_default", issue = "41758")] #[unstable(feature = "vec_resize_default", issue = "41758")]
#[rustc_deprecated(reason = "This is moving towards being removed in favor \
of `.resize_with(Default::default)`. If you disagree, please comment \
in the tracking issue.", since = "1.33.0")]
pub fn resize_default(&mut self, new_len: usize) { pub fn resize_default(&mut self, new_len: usize) {
let len = self.len(); let len = self.len();

View file

@ -24,6 +24,7 @@ use task::{Poll, Waker};
/// ///
/// When using a future, you generally won't call `poll` directly, but instead /// When using a future, you generally won't call `poll` directly, but instead
/// `await!` the value. /// `await!` the value.
#[doc(spotlight)]
#[must_use = "futures do nothing unless polled"] #[must_use = "futures do nothing unless polled"]
pub trait Future { pub trait Future {
/// The type of value produced on completion. /// The type of value produced on completion.

View file

@ -1545,20 +1545,22 @@ Erroneous code example:
```compile_fail,E0505 ```compile_fail,E0505
struct Value {} struct Value {}
fn borrow(val: &Value) {}
fn eat(val: Value) {} fn eat(val: Value) {}
fn main() { fn main() {
let x = Value{}; let x = Value{};
{ let _ref_to_val: &Value = &x;
let _ref_to_val: &Value = &x; eat(x);
eat(x); borrow(_ref_to_val);
}
} }
``` ```
Here, the function `eat` takes the ownership of `x`. However, Here, the function `eat` takes ownership of `x`. However,
`x` cannot be moved because it was borrowed to `_ref_to_val`. `x` cannot be moved because the borrow to `_ref_to_val`
To fix that you can do few different things: needs to last till the function `borrow`.
To fix that you can do a few different things:
* Try to avoid moving the variable. * Try to avoid moving the variable.
* Release borrow before move. * Release borrow before move.
@ -1569,14 +1571,15 @@ Examples:
``` ```
struct Value {} struct Value {}
fn borrow(val: &Value) {}
fn eat(val: &Value) {} fn eat(val: &Value) {}
fn main() { fn main() {
let x = Value{}; let x = Value{};
{ let _ref_to_val: &Value = &x;
let _ref_to_val: &Value = &x; eat(&x); // pass by reference, if it's possible
eat(&x); // pass by reference, if it's possible borrow(_ref_to_val);
}
} }
``` ```
@ -1585,12 +1588,15 @@ Or:
``` ```
struct Value {} struct Value {}
fn borrow(val: &Value) {}
fn eat(val: Value) {} fn eat(val: Value) {}
fn main() { fn main() {
let x = Value{}; let x = Value{};
{ {
let _ref_to_val: &Value = &x; let _ref_to_val: &Value = &x;
borrow(_ref_to_val);
} }
eat(x); // release borrow and then move it. eat(x); // release borrow and then move it.
} }
@ -1602,14 +1608,15 @@ Or:
#[derive(Clone, Copy)] // implement Copy trait #[derive(Clone, Copy)] // implement Copy trait
struct Value {} struct Value {}
fn borrow(val: &Value) {}
fn eat(val: Value) {} fn eat(val: Value) {}
fn main() { fn main() {
let x = Value{}; let x = Value{};
{ let _ref_to_val: &Value = &x;
let _ref_to_val: &Value = &x; eat(x); // it will be copied here.
eat(x); // it will be copied here. borrow(_ref_to_val);
}
} }
``` ```

View file

@ -326,6 +326,10 @@ where
let mplace = MemPlace { let mplace = MemPlace {
ptr: val.to_scalar_ptr()?, ptr: val.to_scalar_ptr()?,
// We could use the run-time alignment here. For now, we do not, because
// the point of tracking the alignment here is to make sure that the *static*
// alignment information emitted with the loads is correct. The run-time
// alignment can only be more restrictive.
align: layout.align.abi, align: layout.align.abi,
meta: val.to_meta()?, meta: val.to_meta()?,
}; };
@ -385,9 +389,11 @@ where
// above). In that case, all fields are equal. // above). In that case, all fields are equal.
let field_layout = base.layout.field(self, usize::try_from(field).unwrap_or(0))?; let field_layout = base.layout.field(self, usize::try_from(field).unwrap_or(0))?;
// Offset may need adjustment for unsized fields // Offset may need adjustment for unsized fields.
let (meta, offset) = if field_layout.is_unsized() { let (meta, offset) = if field_layout.is_unsized() {
// re-use parent metadata to determine dynamic field layout // Re-use parent metadata to determine dynamic field layout.
// With custom DSTS, this *will* execute user-defined code, but the same
// happens at run-time so that's okay.
let align = match self.size_and_align_of(base.meta, field_layout)? { let align = match self.size_and_align_of(base.meta, field_layout)? {
Some((_, align)) => align, Some((_, align)) => align,
None if offset == Size::ZERO => None if offset == Size::ZERO =>

View file

@ -259,6 +259,10 @@ impl<'a> Resolver<'a> {
format!("{}!", path_str), format!("{}!", path_str),
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
if path_str == "try" && span.rust_2015() {
err.note("if you want the `try` keyword, \
you need to be in the 2018 edition");
}
} }
(Def::TyAlias(..), PathSource::Trait(_)) => { (Def::TyAlias(..), PathSource::Trait(_)) => {
err.span_label(span, "type aliases cannot be used as traits"); err.span_label(span, "type aliases cannot be used as traits");

View file

@ -259,6 +259,11 @@ impl ToJson for MergeFunctions {
} }
} }
pub enum LoadTargetError {
BuiltinTargetNotFound(String),
Other(String),
}
pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<String>>; pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<String>>;
pub type TargetResult = Result<Target, String>; pub type TargetResult = Result<Target, String>;
@ -269,21 +274,24 @@ macro_rules! supported_targets {
/// List of supported targets /// List of supported targets
const TARGETS: &[&str] = &[$($triple),*]; const TARGETS: &[&str] = &[$($triple),*];
fn load_specific(target: &str) -> TargetResult { fn load_specific(target: &str) -> Result<Target, LoadTargetError> {
match target { match target {
$( $(
$triple => { $triple => {
let mut t = $module::target()?; let mut t = $module::target()
.map_err(LoadTargetError::Other)?;
t.options.is_builtin = true; t.options.is_builtin = true;
// round-trip through the JSON parser to ensure at // round-trip through the JSON parser to ensure at
// run-time that the parser works correctly // run-time that the parser works correctly
t = Target::from_json(t.to_json())?; t = Target::from_json(t.to_json())
.map_err(LoadTargetError::Other)?;
debug!("Got builtin target: {:?}", t); debug!("Got builtin target: {:?}", t);
Ok(t) Ok(t)
}, },
)+ )+
_ => Err(format!("Unable to find target: {}", target)) _ => Err(LoadTargetError::BuiltinTargetNotFound(
format!("Unable to find target: {}", target)))
} }
} }
@ -1176,8 +1184,10 @@ impl Target {
match *target_triple { match *target_triple {
TargetTriple::TargetTriple(ref target_triple) => { TargetTriple::TargetTriple(ref target_triple) => {
// check if triple is in list of supported targets // check if triple is in list of supported targets
if let Ok(t) = load_specific(target_triple) { match load_specific(target_triple) {
return Ok(t) Ok(t) => return Ok(t),
Err(LoadTargetError::BuiltinTargetNotFound(_)) => (),
Err(LoadTargetError::Other(e)) => return Err(e),
} }
// search for a file named `target_triple`.json in RUST_TARGET_PATH // search for a file named `target_triple`.json in RUST_TARGET_PATH

View file

@ -458,26 +458,18 @@ fn resolution_failure(
link_range: Option<Range<usize>>, link_range: Option<Range<usize>>,
) { ) {
let sp = span_of_attrs(attrs); let sp = span_of_attrs(attrs);
let msg = format!("`[{}]` cannot be resolved, ignoring it...", path_str);
let mut diag = if let Some(link_range) = link_range { let mut diag = cx.tcx.struct_span_lint_node(
lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
NodeId::from_u32(0),
sp,
&format!("`[{}]` cannot be resolved, ignoring it...", path_str),
);
if let Some(link_range) = link_range {
if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) { if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) {
let mut diag = cx.tcx.struct_span_lint_node( diag.set_span(sp);
lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
NodeId::from_u32(0),
sp,
&msg,
);
diag.span_label(sp, "cannot be resolved, ignoring"); diag.span_label(sp, "cannot be resolved, ignoring");
diag
} else { } else {
let mut diag = cx.tcx.struct_span_lint_node(
lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
NodeId::from_u32(0),
sp,
&msg,
);
// blah blah blah\nblah\nblah [blah] blah blah\nblah blah // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
// ^ ~~~~ // ^ ~~~~
// | link_range // | link_range
@ -494,13 +486,7 @@ fn resolution_failure(
before=link_range.start - last_new_line_offset, before=link_range.start - last_new_line_offset,
found=link_range.len(), found=link_range.len(),
)); ));
diag
} }
} else {
cx.tcx.struct_span_lint_node(lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
NodeId::from_u32(0),
sp,
&msg)
}; };
diag.help("to escape `[` and `]` characters, just add '\\' before them like \ diag.help("to escape `[` and `]` characters, just add '\\' before them like \
`\\[` or `\\]`"); `\\[` or `\\]`");

View file

@ -215,16 +215,22 @@
// std may use features in a platform-specific way // std may use features in a platform-specific way
#![allow(unused_features)] #![allow(unused_features)]
#![cfg_attr(test, feature(test, update_panic_count))]
#![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"),
feature(global_asm, range_contains, slice_index_methods,
decl_macro, coerce_unsized, sgx_platform, ptr_wrapping_offset_from))]
// std is implemented with unstable features, many of which are internal // std is implemented with unstable features, many of which are internal
// compiler details that will never be stable // compiler details that will never be stable
#![cfg_attr(test, feature(test, update_panic_count))] // NB: the following list is sorted to minimize merge conflicts.
#![feature(alloc)] #![feature(align_offset)]
#![feature(alloc_error_handler)] #![feature(alloc_error_handler)]
#![feature(alloc_layout_extra)]
#![feature(alloc)]
#![feature(allocator_api)] #![feature(allocator_api)]
#![feature(allocator_internals)] #![feature(allocator_internals)]
#![feature(allow_internal_unsafe)] #![feature(allow_internal_unsafe)]
#![feature(allow_internal_unstable)] #![feature(allow_internal_unstable)]
#![feature(align_offset)]
#![feature(arbitrary_self_types)] #![feature(arbitrary_self_types)]
#![feature(array_error_internals)] #![feature(array_error_internals)]
#![feature(asm)] #![feature(asm)]
@ -233,20 +239,28 @@
#![feature(cfg_target_has_atomic)] #![feature(cfg_target_has_atomic)]
#![feature(cfg_target_thread_local)] #![feature(cfg_target_thread_local)]
#![feature(char_error_internals)] #![feature(char_error_internals)]
#![feature(checked_duration_since)]
#![feature(compiler_builtins_lib)] #![feature(compiler_builtins_lib)]
#![feature(concat_idents)] #![feature(concat_idents)]
#![feature(const_raw_ptr_deref)]
#![feature(const_cstr_unchecked)] #![feature(const_cstr_unchecked)]
#![feature(const_raw_ptr_deref)]
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
#![feature(doc_alias)]
#![feature(doc_cfg)]
#![feature(doc_keyword)]
#![feature(doc_masked)]
#![feature(doc_spotlight)]
#![feature(dropck_eyepatch)] #![feature(dropck_eyepatch)]
#![feature(duration_constants)] #![feature(duration_constants)]
#![feature(exact_size_is_empty)] #![feature(exact_size_is_empty)]
#![feature(exhaustive_patterns)]
#![feature(external_doc)] #![feature(external_doc)]
#![feature(fixed_size_array)] #![feature(fixed_size_array)]
#![feature(fn_traits)] #![feature(fn_traits)]
#![feature(fnbox)] #![feature(fnbox)]
#![feature(futures_api)] #![feature(futures_api)]
#![feature(generator_trait)] #![feature(generator_trait)]
#![feature(hash_raw_entry)]
#![feature(hashmap_internals)] #![feature(hashmap_internals)]
#![feature(int_error_internals)] #![feature(int_error_internals)]
#![feature(integer_atomics)] #![feature(integer_atomics)]
@ -254,31 +268,32 @@
#![feature(libc)] #![feature(libc)]
#![feature(link_args)] #![feature(link_args)]
#![feature(linkage)] #![feature(linkage)]
#![feature(maybe_uninit)]
#![feature(needs_panic_runtime)] #![feature(needs_panic_runtime)]
#![feature(never_type)] #![feature(never_type)]
#![feature(nll)] #![feature(nll)]
#![feature(exhaustive_patterns)] #![feature(non_exhaustive)]
#![feature(on_unimplemented)] #![feature(on_unimplemented)]
#![feature(optin_builtin_traits)] #![feature(optin_builtin_traits)]
#![feature(panic_info_message)]
#![feature(panic_internals)] #![feature(panic_internals)]
#![feature(panic_unwind)] #![feature(panic_unwind)]
#![feature(prelude_import)] #![feature(prelude_import)]
#![feature(ptr_internals)] #![feature(ptr_internals)]
#![feature(raw)] #![feature(raw)]
#![feature(hash_raw_entry)] #![feature(renamed_spin_loop)]
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#![feature(rustc_const_unstable)] #![feature(rustc_const_unstable)]
#![feature(std_internals)] #![feature(rustc_private)]
#![feature(stdsimd)]
#![feature(shrink_to)] #![feature(shrink_to)]
#![feature(slice_concat_ext)] #![feature(slice_concat_ext)]
#![feature(slice_internals)] #![feature(slice_internals)]
#![feature(slice_patterns)] #![feature(slice_patterns)]
#![feature(staged_api)] #![feature(staged_api)]
#![feature(std_internals)]
#![feature(stdsimd)]
#![feature(stmt_expr_attributes)] #![feature(stmt_expr_attributes)]
#![feature(str_internals)] #![feature(str_internals)]
#![feature(renamed_spin_loop)]
#![feature(rustc_private)]
#![feature(thread_local)] #![feature(thread_local)]
#![feature(toowned_clone_into)] #![feature(toowned_clone_into)]
#![feature(try_from)] #![feature(try_from)]
@ -286,19 +301,7 @@
#![feature(unboxed_closures)] #![feature(unboxed_closures)]
#![feature(untagged_unions)] #![feature(untagged_unions)]
#![feature(unwind_attributes)] #![feature(unwind_attributes)]
#![feature(doc_cfg)] // NB: the above list is sorted to minimize merge conflicts.
#![feature(doc_masked)]
#![feature(doc_spotlight)]
#![feature(doc_alias)]
#![feature(doc_keyword)]
#![feature(panic_info_message)]
#![feature(non_exhaustive)]
#![feature(alloc_layout_extra)]
#![feature(maybe_uninit)]
#![feature(checked_duration_since)]
#![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"),
feature(global_asm, range_contains, slice_index_methods,
decl_macro, coerce_unsized, sgx_platform, ptr_wrapping_offset_from))]
#![default_lib_allocator] #![default_lib_allocator]

View file

@ -36,7 +36,7 @@ pub trait CommandExt {
/// will be called and the spawn operation will immediately return with a /// will be called and the spawn operation will immediately return with a
/// failure. /// failure.
/// ///
/// # Notes /// # Notes and Safety
/// ///
/// This closure will be run in the context of the child process after a /// This closure will be run in the context of the child process after a
/// `fork`. This primarily means that any modifications made to memory on /// `fork`. This primarily means that any modifications made to memory on
@ -45,13 +45,33 @@ pub trait CommandExt {
/// like `malloc` or acquiring a mutex are not guaranteed to work (due to /// like `malloc` or acquiring a mutex are not guaranteed to work (due to
/// other threads perhaps still running when the `fork` was run). /// other threads perhaps still running when the `fork` was run).
/// ///
/// This also means that all resources such as file descriptors and
/// memory-mapped regions got duplicated. It is your responsibility to make
/// sure that the closure does not violate library invariants by making
/// invalid use of these duplicates.
///
/// When this closure is run, aspects such as the stdio file descriptors and /// When this closure is run, aspects such as the stdio file descriptors and
/// working directory have successfully been changed, so output to these /// working directory have successfully been changed, so output to these
/// locations may not appear where intended. /// locations may not appear where intended.
#[stable(feature = "process_exec", since = "1.15.0")] #[stable(feature = "process_pre_exec", since = "1.34.0")]
fn before_exec<F>(&mut self, f: F) -> &mut process::Command unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command
where F: FnMut() -> io::Result<()> + Send + Sync + 'static; where F: FnMut() -> io::Result<()> + Send + Sync + 'static;
/// Schedules a closure to be run just before the `exec` function is
/// invoked.
///
/// This method is stable and usable, but it should be unsafe. To fix
/// that, it got deprecated in favor of the unsafe [`pre_exec`].
///
/// [`pre_exec`]: #tymethod.pre_exec
#[stable(feature = "process_exec", since = "1.15.0")]
#[rustc_deprecated(since = "1.37.0", reason = "should be unsafe, use `pre_exec` instead")]
fn before_exec<F>(&mut self, f: F) -> &mut process::Command
where F: FnMut() -> io::Result<()> + Send + Sync + 'static
{
unsafe { self.pre_exec(f) }
}
/// Performs all the required setup by this `Command`, followed by calling /// Performs all the required setup by this `Command`, followed by calling
/// the `execvp` syscall. /// the `execvp` syscall.
/// ///
@ -87,10 +107,10 @@ impl CommandExt for process::Command {
self self
} }
fn before_exec<F>(&mut self, f: F) -> &mut process::Command unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command
where F: FnMut() -> io::Result<()> + Send + Sync + 'static where F: FnMut() -> io::Result<()> + Send + Sync + 'static
{ {
self.as_inner_mut().before_exec(Box::new(f)); self.as_inner_mut().pre_exec(Box::new(f));
self self
} }

View file

@ -116,8 +116,10 @@ impl Command {
self.gid = Some(id); self.gid = Some(id);
} }
pub fn before_exec(&mut self, pub unsafe fn pre_exec(
f: Box<dyn FnMut() -> io::Result<()> + Send + Sync>) { &mut self,
f: Box<dyn FnMut() -> io::Result<()> + Send + Sync>,
) {
self.closures.push(f); self.closures.push(f);
} }

View file

@ -36,7 +36,7 @@ pub trait CommandExt {
/// will be called and the spawn operation will immediately return with a /// will be called and the spawn operation will immediately return with a
/// failure. /// failure.
/// ///
/// # Notes /// # Notes and Safety
/// ///
/// This closure will be run in the context of the child process after a /// This closure will be run in the context of the child process after a
/// `fork`. This primarily means that any modifications made to memory on /// `fork`. This primarily means that any modifications made to memory on
@ -45,13 +45,33 @@ pub trait CommandExt {
/// like `malloc` or acquiring a mutex are not guaranteed to work (due to /// like `malloc` or acquiring a mutex are not guaranteed to work (due to
/// other threads perhaps still running when the `fork` was run). /// other threads perhaps still running when the `fork` was run).
/// ///
/// This also means that all resources such as file descriptors and
/// memory-mapped regions got duplicated. It is your responsibility to make
/// sure that the closure does not violate library invariants by making
/// invalid use of these duplicates.
///
/// When this closure is run, aspects such as the stdio file descriptors and /// When this closure is run, aspects such as the stdio file descriptors and
/// working directory have successfully been changed, so output to these /// working directory have successfully been changed, so output to these
/// locations may not appear where intended. /// locations may not appear where intended.
#[stable(feature = "process_exec", since = "1.15.0")] #[stable(feature = "process_pre_exec", since = "1.34.0")]
fn before_exec<F>(&mut self, f: F) -> &mut process::Command unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command
where F: FnMut() -> io::Result<()> + Send + Sync + 'static; where F: FnMut() -> io::Result<()> + Send + Sync + 'static;
/// Schedules a closure to be run just before the `exec` function is
/// invoked.
///
/// This method is stable and usable, but it should be unsafe. To fix
/// that, it got deprecated in favor of the unsafe [`pre_exec`].
///
/// [`pre_exec`]: #tymethod.pre_exec
#[stable(feature = "process_exec", since = "1.15.0")]
#[rustc_deprecated(since = "1.37.0", reason = "should be unsafe, use `pre_exec` instead")]
fn before_exec<F>(&mut self, f: F) -> &mut process::Command
where F: FnMut() -> io::Result<()> + Send + Sync + 'static
{
unsafe { self.pre_exec(f) }
}
/// Performs all the required setup by this `Command`, followed by calling /// Performs all the required setup by this `Command`, followed by calling
/// the `execvp` syscall. /// the `execvp` syscall.
/// ///
@ -97,10 +117,10 @@ impl CommandExt for process::Command {
self self
} }
fn before_exec<F>(&mut self, f: F) -> &mut process::Command unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command
where F: FnMut() -> io::Result<()> + Send + Sync + 'static where F: FnMut() -> io::Result<()> + Send + Sync + 'static
{ {
self.as_inner_mut().before_exec(Box::new(f)); self.as_inner_mut().pre_exec(Box::new(f));
self self
} }

View file

@ -149,8 +149,10 @@ impl Command {
&mut self.closures &mut self.closures
} }
pub fn before_exec(&mut self, pub unsafe fn pre_exec(
f: Box<dyn FnMut() -> io::Result<()> + Send + Sync>) { &mut self,
f: Box<dyn FnMut() -> io::Result<()> + Send + Sync>,
) {
self.closures.push(f); self.closures.push(f);
} }

View file

@ -9,12 +9,6 @@ use crate::ThinVec;
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use syntax_pos::{Pos, Span, DUMMY_SP}; use syntax_pos::{Pos, Span, DUMMY_SP};
// Transitional re-exports so qquote can find the paths it is looking for
mod syntax {
pub use crate::ext;
pub use crate::parse;
}
pub trait AstBuilder { pub trait AstBuilder {
// paths // paths
fn path(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path; fn path(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path;

View file

@ -36,10 +36,8 @@ macro_rules! ast_fragments {
( (
$($Kind:ident($AstTy:ty) { $($Kind:ident($AstTy:ty) {
$kind_name:expr; $kind_name:expr;
// FIXME: HACK: this should be `$(one ...)?` and `$(many ...)?` but `?` macro $(one fn $mut_visit_ast:ident; fn $visit_ast:ident;)?
// repetition was removed from 2015 edition in #51587 because of ambiguities. $(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident;)?
$(one fn $mut_visit_ast:ident; fn $visit_ast:ident;)*
$(many fn $flat_map_ast_elt:ident; fn $visit_ast_elt:ident;)*
fn $make_ast:ident; fn $make_ast:ident;
})* })*
) => { ) => {

View file

@ -5503,6 +5503,7 @@ impl<'a> Parser<'a> {
if is_bound_start { if is_bound_start {
let lo = self.span; let lo = self.span;
let has_parens = self.eat(&token::OpenDelim(token::Paren)); let has_parens = self.eat(&token::OpenDelim(token::Paren));
let inner_lo = self.span;
let question = if self.eat(&token::Question) { Some(self.prev_span) } else { None }; let question = if self.eat(&token::Question) { Some(self.prev_span) } else { None };
if self.token.is_lifetime() { if self.token.is_lifetime() {
if let Some(question_span) = question { if let Some(question_span) = question {
@ -5511,9 +5512,21 @@ impl<'a> Parser<'a> {
} }
bounds.push(GenericBound::Outlives(self.expect_lifetime())); bounds.push(GenericBound::Outlives(self.expect_lifetime()));
if has_parens { if has_parens {
let inner_span = inner_lo.to(self.prev_span);
self.expect(&token::CloseDelim(token::Paren))?; self.expect(&token::CloseDelim(token::Paren))?;
self.span_err(self.prev_span, let mut err = self.struct_span_err(
"parenthesized lifetime bounds are not supported"); lo.to(self.prev_span),
"parenthesized lifetime bounds are not supported"
);
if let Ok(snippet) = self.sess.source_map().span_to_snippet(inner_span) {
err.span_suggestion_short(
lo.to(self.prev_span),
"remove the parentheses",
snippet.to_owned(),
Applicability::MachineApplicable
);
}
err.emit();
} }
} else { } else {
let lifetime_defs = self.parse_late_bound_lifetime_defs()?; let lifetime_defs = self.parse_late_bound_lifetime_defs()?;

View file

@ -1,83 +0,0 @@
#![allow(stable_features)]
// ignore-windows - this is a unix-specific test
// ignore-cloudabi no processes
// ignore-emscripten no processes
#![feature(process_exec, rustc_private)]
extern crate libc;
use std::env;
use std::io::Error;
use std::os::unix::process::CommandExt;
use std::process::Command;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
fn main() {
if let Some(arg) = env::args().nth(1) {
match &arg[..] {
"test1" => println!("hello2"),
"test2" => assert_eq!(env::var("FOO").unwrap(), "BAR"),
"test3" => assert_eq!(env::current_dir().unwrap()
.to_str().unwrap(), "/"),
"empty" => {}
_ => panic!("unknown argument: {}", arg),
}
return
}
let me = env::current_exe().unwrap();
let output = Command::new(&me).arg("test1").before_exec(|| {
println!("hello");
Ok(())
}).output().unwrap();
assert!(output.status.success());
assert!(output.stderr.is_empty());
assert_eq!(output.stdout, b"hello\nhello2\n");
let output = Command::new(&me).arg("test2").before_exec(|| {
env::set_var("FOO", "BAR");
Ok(())
}).output().unwrap();
assert!(output.status.success());
assert!(output.stderr.is_empty());
assert!(output.stdout.is_empty());
let output = Command::new(&me).arg("test3").before_exec(|| {
env::set_current_dir("/").unwrap();
Ok(())
}).output().unwrap();
assert!(output.status.success());
assert!(output.stderr.is_empty());
assert!(output.stdout.is_empty());
let output = Command::new(&me).arg("bad").before_exec(|| {
Err(Error::from_raw_os_error(102))
}).output().unwrap_err();
assert_eq!(output.raw_os_error(), Some(102));
let pid = unsafe { libc::getpid() };
assert!(pid >= 0);
let output = Command::new(&me).arg("empty").before_exec(move || {
let child = unsafe { libc::getpid() };
assert!(child >= 0);
assert!(pid != child);
Ok(())
}).output().unwrap();
assert!(output.status.success());
assert!(output.stderr.is_empty());
assert!(output.stdout.is_empty());
let mem = Arc::new(AtomicUsize::new(0));
let mem2 = mem.clone();
let output = Command::new(&me).arg("empty").before_exec(move || {
assert_eq!(mem2.fetch_add(1, Ordering::SeqCst), 0);
Ok(())
}).output().unwrap();
assert!(output.status.success());
assert!(output.stderr.is_empty());
assert!(output.stdout.is_empty());
assert_eq!(mem.load(Ordering::SeqCst), 0);
}

View file

@ -0,0 +1,115 @@
#![allow(stable_features)]
// ignore-windows - this is a unix-specific test
// ignore-cloudabi no processes
// ignore-emscripten no processes
#![feature(process_exec, rustc_private)]
extern crate libc;
use std::env;
use std::io::Error;
use std::os::unix::process::CommandExt;
use std::process::Command;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
fn main() {
if let Some(arg) = env::args().nth(1) {
match &arg[..] {
"test1" => println!("hello2"),
"test2" => assert_eq!(env::var("FOO").unwrap(), "BAR"),
"test3" => assert_eq!(env::current_dir().unwrap().to_str().unwrap(), "/"),
"empty" => {}
_ => panic!("unknown argument: {}", arg),
}
return;
}
let me = env::current_exe().unwrap();
let output = unsafe {
Command::new(&me)
.arg("test1")
.pre_exec(|| {
println!("hello");
Ok(())
})
.output()
.unwrap()
};
assert!(output.status.success());
assert!(output.stderr.is_empty());
assert_eq!(output.stdout, b"hello\nhello2\n");
let output = unsafe {
Command::new(&me)
.arg("test2")
.pre_exec(|| {
env::set_var("FOO", "BAR");
Ok(())
})
.output()
.unwrap()
};
assert!(output.status.success());
assert!(output.stderr.is_empty());
assert!(output.stdout.is_empty());
let output = unsafe {
Command::new(&me)
.arg("test3")
.pre_exec(|| {
env::set_current_dir("/").unwrap();
Ok(())
})
.output()
.unwrap()
};
assert!(output.status.success());
assert!(output.stderr.is_empty());
assert!(output.stdout.is_empty());
let output = unsafe {
Command::new(&me)
.arg("bad")
.pre_exec(|| Err(Error::from_raw_os_error(102)))
.output()
.unwrap_err()
};
assert_eq!(output.raw_os_error(), Some(102));
let pid = unsafe { libc::getpid() };
assert!(pid >= 0);
let output = unsafe {
Command::new(&me)
.arg("empty")
.pre_exec(move || {
let child = libc::getpid();
assert!(child >= 0);
assert!(pid != child);
Ok(())
})
.output()
.unwrap()
};
assert!(output.status.success());
assert!(output.stderr.is_empty());
assert!(output.stdout.is_empty());
let mem = Arc::new(AtomicUsize::new(0));
let mem2 = mem.clone();
let output = unsafe {
Command::new(&me)
.arg("empty")
.pre_exec(move || {
assert_eq!(mem2.fetch_add(1, Ordering::SeqCst), 0);
Ok(())
})
.output()
.unwrap()
};
assert!(output.status.success());
assert!(output.stderr.is_empty());
assert!(output.stdout.is_empty());
assert_eq!(mem.load(Ordering::SeqCst), 0);
}

View file

@ -1,14 +1,14 @@
error: parenthesized lifetime bounds are not supported error: parenthesized lifetime bounds are not supported
--> $DIR/trait-object-lifetime-parens.rs:5:24 --> $DIR/trait-object-lifetime-parens.rs:5:21
| |
LL | fn f<'a, T: Trait + ('a)>() {} //~ ERROR parenthesized lifetime bounds are not supported LL | fn f<'a, T: Trait + ('a)>() {} //~ ERROR parenthesized lifetime bounds are not supported
| ^ | ^^^^ help: remove the parentheses
error: parenthesized lifetime bounds are not supported error: parenthesized lifetime bounds are not supported
--> $DIR/trait-object-lifetime-parens.rs:8:27 --> $DIR/trait-object-lifetime-parens.rs:8:24
| |
LL | let _: Box<Trait + ('a)>; //~ ERROR parenthesized lifetime bounds are not supported LL | let _: Box<Trait + ('a)>; //~ ERROR parenthesized lifetime bounds are not supported
| ^ | ^^^^ help: remove the parentheses
error: expected type, found `'a` error: expected type, found `'a`
--> $DIR/trait-object-lifetime-parens.rs:9:17 --> $DIR/trait-object-lifetime-parens.rs:9:17

View file

@ -16,6 +16,8 @@ error[E0574]: expected struct, variant or union type, found macro `try`
| |
LL | let try_result: Option<_> = try { LL | let try_result: Option<_> = try {
| ^^^ help: use `!` to invoke the macro: `try!` | ^^^ help: use `!` to invoke the macro: `try!`
|
= note: if you want the `try` keyword, you need to be in the 2018 edition
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -25,7 +25,7 @@ MAINTAINERS = {
} }
REPOS = { REPOS = {
'miri': 'https://github.com/solson/miri', 'miri': 'https://github.com/rust-lang/miri',
'clippy-driver': 'https://github.com/rust-lang/rust-clippy', 'clippy-driver': 'https://github.com/rust-lang/rust-clippy',
'rls': 'https://github.com/rust-lang/rls', 'rls': 'https://github.com/rust-lang/rls',
'rustfmt': 'https://github.com/rust-lang/rustfmt', 'rustfmt': 'https://github.com/rust-lang/rustfmt',