Auto merge of #91691 - matthiaskrgr:rollup-wfommdr, r=matthiaskrgr

Rollup of 5 pull requests

Successful merges:

 - #91042 (Use Vec extend instead of repeated pushes on several places)
 - #91476 (Improve 'cannot contain emoji' error.)
 - #91568 (Pretty print break and continue without redundant space)
 - #91645 (Implement `core::future::join!`)
 - #91666 (update Miri)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-12-09 04:04:01 +00:00
commit e250777041
19 changed files with 291 additions and 39 deletions

View File

@ -2135,22 +2135,20 @@ impl<'a> State<'a> {
ast::ExprKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, true),
ast::ExprKind::Break(opt_label, ref opt_expr) => {
self.word("break");
self.space();
if let Some(label) = opt_label {
self.print_ident(label.ident);
self.space();
self.print_ident(label.ident);
}
if let Some(ref expr) = *opt_expr {
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
self.space();
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
}
ast::ExprKind::Continue(opt_label) => {
self.word("continue");
self.space();
if let Some(label) = opt_label {
self.space();
self.print_ident(label.ident);
self.space()
}
}
ast::ExprKind::Ret(ref result) => {

View File

@ -1543,22 +1543,20 @@ impl<'a> State<'a> {
hir::ExprKind::Path(ref qpath) => self.print_qpath(qpath, true),
hir::ExprKind::Break(destination, ref opt_expr) => {
self.word("break");
self.space();
if let Some(label) = destination.label {
self.print_ident(label.ident);
self.space();
self.print_ident(label.ident);
}
if let Some(ref expr) = *opt_expr {
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
self.space();
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
}
hir::ExprKind::Continue(destination) => {
self.word("continue");
self.space();
if let Some(label) = destination.label {
self.space();
self.print_ident(label.ident);
self.space()
}
}
hir::ExprKind::Ret(ref result) => {

View File

@ -10,7 +10,7 @@ use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::parallel;
use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_errors::{ErrorReported, PResult};
use rustc_errors::{Applicability, ErrorReported, PResult};
use rustc_expand::base::ExtCtxt;
use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
use rustc_hir::Crate;
@ -456,11 +456,27 @@ pub fn configure_and_expand(
identifiers.sort_by_key(|&(key, _)| key);
for (ident, mut spans) in identifiers.into_iter() {
spans.sort();
if ident == sym::ferris {
let first_span = spans[0];
sess.diagnostic()
.struct_span_err(
MultiSpan::from(spans),
"Ferris cannot be used as an identifier",
)
.span_suggestion(
first_span,
"try using their name instead",
"ferris".to_string(),
Applicability::MaybeIncorrect,
)
.emit();
} else {
sess.diagnostic().span_err(
MultiSpan::from(spans),
&format!("identifiers cannot contain emoji: `{}`", ident),
);
}
}
});
Ok(krate)

View File

@ -329,9 +329,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
fn mir_to_initial_sorted_coverage_spans(&self) -> Vec<CoverageSpan> {
let mut initial_spans = Vec::<CoverageSpan>::with_capacity(self.mir_body.num_nodes() * 2);
for (bcb, bcb_data) in self.basic_coverage_blocks.iter_enumerated() {
for coverage_span in self.bcb_to_initial_coverage_spans(bcb, bcb_data) {
initial_spans.push(coverage_span);
}
initial_spans.extend(self.bcb_to_initial_coverage_spans(bcb, bcb_data));
}
if initial_spans.is_empty() {

View File

@ -630,6 +630,7 @@ symbols! {
fdiv_fast,
feature,
fence,
ferris: "🦀",
fetch_update,
ffi,
ffi_const,

View File

@ -498,9 +498,7 @@ fn orphan_check_trait_ref<'tcx>(
return Err(OrphanCheckErr::UncoveredTy(input_ty, local_type));
}
for input_ty in non_local_tys {
non_local_spans.push((input_ty, i == 0));
}
non_local_spans.extend(non_local_tys.into_iter().map(|input_ty| (input_ty, i == 0)));
}
// If we exit above loop, never found a local type.
debug!("orphan_check_trait_ref: no local type");

View File

@ -362,9 +362,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.infcx
.probe(|_| self.match_projection_obligation_against_definition_bounds(obligation));
for predicate_index in result {
candidates.vec.push(ProjectionCandidate(predicate_index));
}
candidates.vec.extend(result.into_iter().map(ProjectionCandidate));
}
/// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller

View File

@ -686,9 +686,8 @@ fn bounds_from_generic_predicates<'tcx>(
};
let mut where_clauses = vec![];
for (ty, bounds) in types {
for bound in &bounds {
where_clauses.push(format!("{}: {}", ty, tcx.def_path_str(*bound)));
}
where_clauses
.extend(bounds.into_iter().map(|bound| format!("{}: {}", ty, tcx.def_path_str(bound))));
}
for projection in &projections {
let p = projection.skip_binder();

View File

@ -904,10 +904,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> MigrationWarningReason {
let mut reasons = MigrationWarningReason::default();
for auto_trait in auto_trait_reasons {
reasons.auto_traits.push(auto_trait);
}
reasons.auto_traits.extend(auto_trait_reasons);
reasons.drop_order = drop_order;
reasons

View File

@ -0,0 +1,147 @@
#![allow(unused_imports)] // items are used by the macro
use crate::cell::UnsafeCell;
use crate::future::{poll_fn, Future};
use crate::mem;
use crate::pin::Pin;
use crate::task::{Context, Poll};
/// Polls multiple futures simultaneously, returning a tuple
/// of all results once complete.
///
/// While `join!(a, b)` is similar to `(a.await, b.await)`,
/// `join!` polls both futures concurrently and is therefore more efficient.
///
/// # Examples
///
/// ```
/// #![feature(future_join, future_poll_fn)]
///
/// use std::future::join;
///
/// async fn one() -> usize { 1 }
/// async fn two() -> usize { 2 }
///
/// # let _ = async {
/// let x = join!(one(), two()).await;
/// assert_eq!(x, (1, 2));
/// # };
/// ```
///
/// `join!` is variadic, so you can pass any number of futures:
///
/// ```
/// #![feature(future_join, future_poll_fn)]
///
/// use std::future::join;
///
/// async fn one() -> usize { 1 }
/// async fn two() -> usize { 2 }
/// async fn three() -> usize { 3 }
///
/// # let _ = async {
/// let x = join!(one(), two(), three()).await;
/// assert_eq!(x, (1, 2, 3));
/// # };
/// ```
#[unstable(feature = "future_join", issue = "91642")]
pub macro join {
( $($fut:expr),* $(,)?) => {
join! { @count: (), @futures: {}, @rest: ($($fut,)*) }
},
// Recurse until we have the position of each future in the tuple
(
// A token for each future that has been expanded: "_ _ _"
@count: ($($count:tt)*),
// Futures and their positions in the tuple: "{ a => (_), b => (_ _)) }"
@futures: { $($fut:tt)* },
// Take a future from @rest to expand
@rest: ($current:expr, $($rest:tt)*)
) => {
join! {
@count: ($($count)* _),
@futures: { $($fut)* $current => ($($count)*), },
@rest: ($($rest)*)
}
},
// Now generate the output future
(
@count: ($($count:tt)*),
@futures: {
$( $(@$f:tt)? $fut:expr => ( $($pos:tt)* ), )*
},
@rest: ()
) => {
async move {
let mut futures = ( $( MaybeDone::Future($fut), )* );
poll_fn(move |cx| {
let mut done = true;
$(
let ( $($pos,)* fut, .. ) = &mut futures;
// SAFETY: The futures are never moved
done &= unsafe { Pin::new_unchecked(fut).poll(cx).is_ready() };
)*
if done {
// Extract all the outputs
Poll::Ready(($({
let ( $($pos,)* fut, .. ) = &mut futures;
fut.take_output().unwrap()
}),*))
} else {
Poll::Pending
}
}).await
}
}
}
/// Future used by `join!` that stores it's output to
/// be later taken and doesn't panic when polled after ready.
///
/// This type is public in a private module for use by the macro.
#[allow(missing_debug_implementations)]
#[unstable(feature = "future_join", issue = "91642")]
pub enum MaybeDone<F: Future> {
Future(F),
Done(F::Output),
Took,
}
#[unstable(feature = "future_join", issue = "91642")]
impl<F: Future> MaybeDone<F> {
pub fn take_output(&mut self) -> Option<F::Output> {
match &*self {
MaybeDone::Done(_) => match mem::replace(self, Self::Took) {
MaybeDone::Done(val) => Some(val),
_ => unreachable!(),
},
_ => None,
}
}
}
#[unstable(feature = "future_join", issue = "91642")]
impl<F: Future> Future for MaybeDone<F> {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// SAFETY: pinning in structural for `f`
unsafe {
match self.as_mut().get_unchecked_mut() {
MaybeDone::Future(f) => match Pin::new_unchecked(f).poll(cx) {
Poll::Ready(val) => self.set(Self::Done(val)),
Poll::Pending => return Poll::Pending,
},
MaybeDone::Done(_) => {}
MaybeDone::Took => unreachable!(),
}
}
Poll::Ready(())
}
}

View File

@ -11,6 +11,7 @@ use crate::{
mod future;
mod into_future;
mod join;
mod pending;
mod poll_fn;
mod ready;
@ -18,6 +19,9 @@ mod ready;
#[stable(feature = "futures_api", since = "1.36.0")]
pub use self::future::Future;
#[unstable(feature = "future_join", issue = "91642")]
pub use self::join::join;
#[unstable(feature = "into_future", issue = "67644")]
pub use into_future::IntoFuture;

View File

@ -0,0 +1,85 @@
use std::future::{join, Future};
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll, Wake};
use std::thread;
struct PollN {
val: usize,
polled: usize,
num: usize,
}
impl Future for PollN {
type Output = usize;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.polled += 1;
if self.polled == self.num {
return Poll::Ready(self.val);
}
cx.waker().wake_by_ref();
Poll::Pending
}
}
fn poll_n(val: usize, num: usize) -> PollN {
PollN { val, num, polled: 0 }
}
#[test]
fn test_join() {
block_on(async move {
let x = join!(async { 0 }).await;
assert_eq!(x, 0);
let x = join!(async { 0 }, async { 1 }).await;
assert_eq!(x, (0, 1));
let x = join!(async { 0 }, async { 1 }, async { 2 }).await;
assert_eq!(x, (0, 1, 2));
let x = join!(
poll_n(0, 1),
poll_n(1, 5),
poll_n(2, 2),
poll_n(3, 1),
poll_n(4, 2),
poll_n(5, 3),
poll_n(6, 4),
poll_n(7, 1)
)
.await;
assert_eq!(x, (0, 1, 2, 3, 4, 5, 6, 7));
let y = String::new();
let x = join!(async {
println!("{}", &y);
1
})
.await;
assert_eq!(x, 1);
});
}
fn block_on(fut: impl Future) {
struct Waker;
impl Wake for Waker {
fn wake(self: Arc<Self>) {
thread::current().unpark()
}
}
let waker = Arc::new(Waker).into();
let mut cx = Context::from_waker(&waker);
let mut fut = Box::pin(fut);
loop {
match fut.as_mut().poll(&mut cx) {
Poll::Ready(_) => break,
Poll::Pending => thread::park(),
}
}
}

View File

@ -29,6 +29,8 @@
#![feature(flt2dec)]
#![feature(fmt_internals)]
#![feature(float_minimum_maximum)]
#![feature(future_join)]
#![feature(future_poll_fn)]
#![feature(array_from_fn)]
#![feature(hashmap_internals)]
#![feature(try_find)]
@ -94,6 +96,7 @@ mod clone;
mod cmp;
mod const_ptr;
mod fmt;
mod future;
mod hash;
mod intrinsics;
mod iter;

View File

@ -110,8 +110,8 @@ fn syntax() {
let _ = #[attr] &mut 0;
let _ = #[attr] &#[attr] 0;
let _ = #[attr] &mut #[attr] 0;
let _ = #[attr] break ;
let _ = #[attr] continue ;
let _ = #[attr] break;
let _ = #[attr] continue;
let _ = #[attr] return;
let _ = #[attr] foo!();
let _ = #[attr] foo!(#! [attr]);

View File

@ -6,4 +6,4 @@ extern crate std;
// pretty-mode:hir
// pp-exact:hir-pretty-loop.pp
pub fn foo() { loop { break ; } }
pub fn foo() { loop { break; } }

View File

@ -229,9 +229,8 @@ fn _11() {
let _ = #[rustc_dummy] &mut 0;
let _ = #[rustc_dummy] &#[rustc_dummy] 0;
let _ = #[rustc_dummy] &mut #[rustc_dummy] 0;
// FIXME: pp bug, extra space after keyword?
while false { let _ = #[rustc_dummy] continue ; }
while true { let _ = #[rustc_dummy] break ; }
while false { let _ = #[rustc_dummy] continue; }
while true { let _ = #[rustc_dummy] break; }
|| #[rustc_dummy] return;
let _ = #[rustc_dummy] expr_mac!();
let _ = #[rustc_dummy] expr_mac![];

View File

@ -13,4 +13,7 @@ fn main() {
let _ = i_like_to_😄_a_lot() 4; //~ ERROR cannot find function `i_like_to_😄_a_lot` in this scope
//~^ ERROR identifiers cannot contain emoji
//~| ERROR unknown start of token: \u{2796}
let 🦀 = 1;//~ ERROR Ferris cannot be used as an identifier
dbg!(🦀);
}

View File

@ -18,6 +18,14 @@ LL | fn i_like_to_😅_a_lot() -> 👀 {
LL | let _ = i_like_to_😄_a_lot() 4;
| ^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `i_like_to_😅_a_lot`
error: Ferris cannot be used as an identifier
--> $DIR/emoji-identifiers.rs:17:9
|
LL | let 🦀 = 1;
| ^^ help: try using their name instead: `ferris`
LL | dbg!(🦀);
| ^^
error: identifiers cannot contain emoji: `ABig👩👩👧👧Family`
--> $DIR/emoji-identifiers.rs:1:8
|
@ -77,7 +85,7 @@ LL | 👀::full_of✨()
| function or associated item not found in `👀`
| help: there is an associated function with a similar name: `full_of_✨`
error: aborting due to 9 previous errors
error: aborting due to 10 previous errors
Some errors have detailed explanations: E0425, E0599.
For more information about an error, try `rustc --explain E0425`.

@ -1 +1 @@
Subproject commit 81e59e6b92cf1729aabbbbf09b81a81a03775d64
Subproject commit dadcbebfbd017aac2358cf652a4bd71a91694edc