mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
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:
commit
e250777041
@ -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) => {
|
||||
|
@ -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) => {
|
||||
|
@ -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)
|
||||
|
@ -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() {
|
||||
|
@ -630,6 +630,7 @@ symbols! {
|
||||
fdiv_fast,
|
||||
feature,
|
||||
fence,
|
||||
ferris: "🦀",
|
||||
fetch_update,
|
||||
ffi,
|
||||
ffi_const,
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
147
library/core/src/future/join.rs
Normal file
147
library/core/src/future/join.rs
Normal 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(())
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
|
85
library/core/tests/future.rs
Normal file
85
library/core/tests/future.rs
Normal 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(),
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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]);
|
||||
|
@ -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; } }
|
||||
|
@ -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![];
|
||||
|
@ -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!(🦀);
|
||||
}
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user