Auto merge of #62407 - Centril:rollup-g0zmff7, r=Centril
Rollup of 10 pull requests Successful merges: - #62123 ( Remove needless lifetimes (std)) - #62150 (Implement mem::{zeroed,uninitialized} in terms of MaybeUninit.) - #62169 (Derive which queries to save using the proc macro) - #62238 (Fix code block information icon position) - #62292 (Move `async || ...` closures into `#![feature(async_closure)]`) - #62323 (Clarify unaligned fields in ptr::{read,write}_unaligned) - #62324 (Reduce reliance on `await!(...)` macro) - #62371 (Add tracking issue for Box::into_pin) - #62383 (Improve error span for async type inference error) - #62388 (Break out of the correct number of scopes in loops) Failed merges: r? @ghost
This commit is contained in:
commit
853f30052d
|
@ -320,7 +320,7 @@ impl<T: ?Sized> Box<T> {
|
||||||
/// This conversion does not allocate on the heap and happens in place.
|
/// This conversion does not allocate on the heap and happens in place.
|
||||||
///
|
///
|
||||||
/// This is also available via [`From`].
|
/// This is also available via [`From`].
|
||||||
#[unstable(feature = "box_into_pin", issue = "0")]
|
#[unstable(feature = "box_into_pin", issue = "62370")]
|
||||||
pub fn into_pin(boxed: Box<T>) -> Pin<Box<T>> {
|
pub fn into_pin(boxed: Box<T>) -> Pin<Box<T>> {
|
||||||
// It's not possible to move or replace the insides of a `Pin<Box<T>>`
|
// It's not possible to move or replace the insides of a `Pin<Box<T>>`
|
||||||
// when `T: !Unpin`, so it's safe to pin it directly without any
|
// when `T: !Unpin`, so it's safe to pin it directly without any
|
||||||
|
|
|
@ -2032,7 +2032,7 @@ impl<K, V> BTreeMap<K, V> {
|
||||||
/// assert_eq!(keys, [1, 2]);
|
/// assert_eq!(keys, [1, 2]);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
|
pub fn keys(&self) -> Keys<'_, K, V> {
|
||||||
Keys { inner: self.iter() }
|
Keys { inner: self.iter() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2053,7 +2053,7 @@ impl<K, V> BTreeMap<K, V> {
|
||||||
/// assert_eq!(values, ["hello", "goodbye"]);
|
/// assert_eq!(values, ["hello", "goodbye"]);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn values<'a>(&'a self) -> Values<'a, K, V> {
|
pub fn values(&self) -> Values<'_, K, V> {
|
||||||
Values { inner: self.iter() }
|
Values { inner: self.iter() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2557,8 +2557,8 @@ enum UnderflowResult<'a, K, V> {
|
||||||
Stole(NodeRef<marker::Mut<'a>, K, V, marker::Internal>),
|
Stole(NodeRef<marker::Mut<'a>, K, V, marker::Internal>),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_underfull_node<'a, K, V>(node: NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>)
|
fn handle_underfull_node<K, V>(node: NodeRef<marker::Mut<'_>, K, V, marker::LeafOrInternal>)
|
||||||
-> UnderflowResult<'a, K, V> {
|
-> UnderflowResult<'_, K, V> {
|
||||||
let parent = if let Ok(parent) = node.ascend() {
|
let parent = if let Ok(parent) = node.ascend() {
|
||||||
parent
|
parent
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -394,7 +394,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Temporarily takes out another, immutable reference to the same node.
|
/// Temporarily takes out another, immutable reference to the same node.
|
||||||
fn reborrow<'a>(&'a self) -> NodeRef<marker::Immut<'a>, K, V, Type> {
|
fn reborrow(&self) -> NodeRef<marker::Immut<'_>, K, V, Type> {
|
||||||
NodeRef {
|
NodeRef {
|
||||||
height: self.height,
|
height: self.height,
|
||||||
node: self.node,
|
node: self.node,
|
||||||
|
|
|
@ -552,7 +552,7 @@ impl String {
|
||||||
/// assert_eq!("Hello <20>World", output);
|
/// assert_eq!("Hello <20>World", output);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str> {
|
pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> {
|
||||||
let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks();
|
let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks();
|
||||||
|
|
||||||
let (first_valid, first_broken) = if let Some(chunk) = iter.next() {
|
let (first_valid, first_broken) = if let Some(chunk) = iter.next() {
|
||||||
|
|
|
@ -700,17 +700,15 @@ extern "rust-intrinsic" {
|
||||||
/// which is unsafe unless `T` is `Copy`. Also, even if T is
|
/// which is unsafe unless `T` is `Copy`. Also, even if T is
|
||||||
/// `Copy`, an all-zero value may not correspond to any legitimate
|
/// `Copy`, an all-zero value may not correspond to any legitimate
|
||||||
/// state for the type in question.
|
/// state for the type in question.
|
||||||
|
#[unstable(feature = "core_intrinsics",
|
||||||
|
reason = "intrinsics are unlikely to ever be stabilized, instead \
|
||||||
|
they should be used through stabilized interfaces \
|
||||||
|
in the rest of the standard library",
|
||||||
|
issue = "0")]
|
||||||
|
#[rustc_deprecated(reason = "no longer used by rustc, will be removed - use MaybeUnint instead",
|
||||||
|
since = "1.38.0")]
|
||||||
pub fn init<T>() -> T;
|
pub fn init<T>() -> T;
|
||||||
|
|
||||||
/// Creates an uninitialized value.
|
|
||||||
///
|
|
||||||
/// `uninit` is unsafe because there is no guarantee of what its
|
|
||||||
/// contents are. In particular its drop-flag may be set to any
|
|
||||||
/// state, which means it may claim either dropped or
|
|
||||||
/// undropped. In the general case one must use `ptr::write` to
|
|
||||||
/// initialize memory previous set to the result of `uninit`.
|
|
||||||
pub fn uninit<T>() -> T;
|
|
||||||
|
|
||||||
/// Moves a value out of scope without running drop glue.
|
/// Moves a value out of scope without running drop glue.
|
||||||
pub fn forget<T: ?Sized>(_: T);
|
pub fn forget<T: ?Sized>(_: T);
|
||||||
|
|
||||||
|
|
|
@ -498,7 +498,7 @@ macro_rules! impls{
|
||||||
/// # end: *const T,
|
/// # end: *const T,
|
||||||
/// # phantom: PhantomData<&'a T>,
|
/// # phantom: PhantomData<&'a T>,
|
||||||
/// # }
|
/// # }
|
||||||
/// fn borrow_vec<'a, T>(vec: &'a Vec<T>) -> Slice<'a, T> {
|
/// fn borrow_vec<T>(vec: &Vec<T>) -> Slice<'_, T> {
|
||||||
/// let ptr = vec.as_ptr();
|
/// let ptr = vec.as_ptr();
|
||||||
/// Slice {
|
/// Slice {
|
||||||
/// start: ptr,
|
/// start: ptr,
|
||||||
|
|
|
@ -450,8 +450,7 @@ pub const fn needs_drop<T>() -> bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub unsafe fn zeroed<T>() -> T {
|
pub unsafe fn zeroed<T>() -> T {
|
||||||
intrinsics::panic_if_uninhabited::<T>();
|
MaybeUninit::zeroed().assume_init()
|
||||||
intrinsics::init()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bypasses Rust's normal memory-initialization checks by pretending to
|
/// Bypasses Rust's normal memory-initialization checks by pretending to
|
||||||
|
@ -476,8 +475,7 @@ pub unsafe fn zeroed<T>() -> T {
|
||||||
#[rustc_deprecated(since = "1.38.0", reason = "use `mem::MaybeUninit` instead")]
|
#[rustc_deprecated(since = "1.38.0", reason = "use `mem::MaybeUninit` instead")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub unsafe fn uninitialized<T>() -> T {
|
pub unsafe fn uninitialized<T>() -> T {
|
||||||
intrinsics::panic_if_uninhabited::<T>();
|
MaybeUninit::uninit().assume_init()
|
||||||
intrinsics::uninit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Swaps the values at two mutable locations, without deinitializing either one.
|
/// Swaps the values at two mutable locations, without deinitializing either one.
|
||||||
|
|
|
@ -105,7 +105,7 @@ pub trait Index<Idx: ?Sized> {
|
||||||
/// impl Index<Side> for Balance {
|
/// impl Index<Side> for Balance {
|
||||||
/// type Output = Weight;
|
/// type Output = Weight;
|
||||||
///
|
///
|
||||||
/// fn index<'a>(&'a self, index: Side) -> &'a Self::Output {
|
/// fn index(&self, index: Side) -> &Self::Output {
|
||||||
/// println!("Accessing {:?}-side of balance immutably", index);
|
/// println!("Accessing {:?}-side of balance immutably", index);
|
||||||
/// match index {
|
/// match index {
|
||||||
/// Side::Left => &self.left,
|
/// Side::Left => &self.left,
|
||||||
|
@ -115,7 +115,7 @@ pub trait Index<Idx: ?Sized> {
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// impl IndexMut<Side> for Balance {
|
/// impl IndexMut<Side> for Balance {
|
||||||
/// fn index_mut<'a>(&'a mut self, index: Side) -> &'a mut Self::Output {
|
/// fn index_mut(&mut self, index: Side) -> &mut Self::Output {
|
||||||
/// println!("Accessing {:?}-side of balance mutably", index);
|
/// println!("Accessing {:?}-side of balance mutably", index);
|
||||||
/// match index {
|
/// match index {
|
||||||
/// Side::Left => &mut self.left,
|
/// Side::Left => &mut self.left,
|
||||||
|
|
|
@ -625,42 +625,50 @@ pub unsafe fn read<T>(src: *const T) -> T {
|
||||||
/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value
|
/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value
|
||||||
/// [valid]: ../ptr/index.html#safety
|
/// [valid]: ../ptr/index.html#safety
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// ## On `packed` structs
|
||||||
///
|
///
|
||||||
/// Access members of a packed struct by reference:
|
/// It is currently impossible to create raw pointers to unaligned fields
|
||||||
|
/// of a packed struct.
|
||||||
///
|
///
|
||||||
/// ```
|
/// Attempting to create a raw pointer to an `unaligned` struct field with
|
||||||
/// use std::ptr;
|
/// an expression such as `&packed.unaligned as *const FieldType` creates an
|
||||||
|
/// intermediate unaligned reference before converting that to a raw pointer.
|
||||||
|
/// That this reference is temporary and immediately cast is inconsequential
|
||||||
|
/// as the compiler always expects references to be properly aligned.
|
||||||
|
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
|
||||||
|
/// *undefined behavior* in your program.
|
||||||
///
|
///
|
||||||
|
/// An example of what not to do and how this relates to `read_unaligned` is:
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
/// #[repr(packed, C)]
|
/// #[repr(packed, C)]
|
||||||
/// struct Packed {
|
/// struct Packed {
|
||||||
/// _padding: u8,
|
/// _padding: u8,
|
||||||
/// unaligned: u32,
|
/// unaligned: u32,
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let x = Packed {
|
/// let packed = Packed {
|
||||||
/// _padding: 0x00,
|
/// _padding: 0x00,
|
||||||
/// unaligned: 0x01020304,
|
/// unaligned: 0x01020304,
|
||||||
/// };
|
/// };
|
||||||
///
|
///
|
||||||
/// let v = unsafe {
|
/// let v = unsafe {
|
||||||
/// // Take the address of a 32-bit integer which is not aligned.
|
/// // Here we attempt to take the address of a 32-bit integer which is not aligned.
|
||||||
/// // This must be done as a raw pointer; unaligned references are invalid.
|
/// let unaligned =
|
||||||
/// let unaligned = &x.unaligned as *const u32;
|
/// // A temporary unaligned reference is created here which results in
|
||||||
|
/// // undefined behavior regardless of whether the reference is used or not.
|
||||||
|
/// &packed.unaligned
|
||||||
|
/// // Casting to a raw pointer doesn't help; the mistake already happened.
|
||||||
|
/// as *const u32;
|
||||||
///
|
///
|
||||||
/// // Dereferencing normally will emit an aligned load instruction,
|
/// let v = std::ptr::read_unaligned(unaligned);
|
||||||
/// // causing undefined behavior.
|
|
||||||
/// // let v = *unaligned; // ERROR
|
|
||||||
///
|
|
||||||
/// // Instead, use `read_unaligned` to read improperly aligned values.
|
|
||||||
/// let v = ptr::read_unaligned(unaligned);
|
|
||||||
///
|
///
|
||||||
/// v
|
/// v
|
||||||
/// };
|
/// };
|
||||||
///
|
|
||||||
/// // Accessing unaligned values directly is safe.
|
|
||||||
/// assert!(x.unaligned == v);
|
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
|
||||||
|
// FIXME: Update docs based on outcome of RFC #2582 and friends.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
|
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
|
||||||
pub unsafe fn read_unaligned<T>(src: *const T) -> T {
|
pub unsafe fn read_unaligned<T>(src: *const T) -> T {
|
||||||
|
@ -789,38 +797,48 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
|
||||||
///
|
///
|
||||||
/// [valid]: ../ptr/index.html#safety
|
/// [valid]: ../ptr/index.html#safety
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// ## On `packed` structs
|
||||||
///
|
///
|
||||||
/// Access fields in a packed struct:
|
/// It is currently impossible to create raw pointers to unaligned fields
|
||||||
|
/// of a packed struct.
|
||||||
///
|
///
|
||||||
/// ```
|
/// Attempting to create a raw pointer to an `unaligned` struct field with
|
||||||
/// use std::{mem, ptr};
|
/// an expression such as `&packed.unaligned as *const FieldType` creates an
|
||||||
|
/// intermediate unaligned reference before converting that to a raw pointer.
|
||||||
|
/// That this reference is temporary and immediately cast is inconsequential
|
||||||
|
/// as the compiler always expects references to be properly aligned.
|
||||||
|
/// As a result, using `&packed.unaligned as *const FieldType` causes immediate
|
||||||
|
/// *undefined behavior* in your program.
|
||||||
///
|
///
|
||||||
|
/// An example of what not to do and how this relates to `write_unaligned` is:
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
/// #[repr(packed, C)]
|
/// #[repr(packed, C)]
|
||||||
/// #[derive(Default)]
|
|
||||||
/// struct Packed {
|
/// struct Packed {
|
||||||
/// _padding: u8,
|
/// _padding: u8,
|
||||||
/// unaligned: u32,
|
/// unaligned: u32,
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let v = 0x01020304;
|
/// let v = 0x01020304;
|
||||||
/// let mut x: Packed = unsafe { mem::zeroed() };
|
/// let mut packed: Packed = unsafe { std::mem::zeroed() };
|
||||||
///
|
///
|
||||||
/// unsafe {
|
/// let v = unsafe {
|
||||||
/// // Take a reference to a 32-bit integer which is not aligned.
|
/// // Here we attempt to take the address of a 32-bit integer which is not aligned.
|
||||||
/// let unaligned = &mut x.unaligned as *mut u32;
|
/// let unaligned =
|
||||||
|
/// // A temporary unaligned reference is created here which results in
|
||||||
|
/// // undefined behavior regardless of whether the reference is used or not.
|
||||||
|
/// &mut packed.unaligned
|
||||||
|
/// // Casting to a raw pointer doesn't help; the mistake already happened.
|
||||||
|
/// as *mut u32;
|
||||||
///
|
///
|
||||||
/// // Dereferencing normally will emit an aligned store instruction,
|
/// std::ptr::write_unaligned(unaligned, v);
|
||||||
/// // causing undefined behavior because the pointer is not aligned.
|
|
||||||
/// // *unaligned = v; // ERROR
|
|
||||||
///
|
///
|
||||||
/// // Instead, use `write_unaligned` to write improperly aligned values.
|
/// v
|
||||||
/// ptr::write_unaligned(unaligned, v);
|
/// };
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// // Accessing unaligned values directly is safe.
|
|
||||||
/// assert!(x.unaligned == v);
|
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// Accessing unaligned fields directly with e.g. `packed.unaligned` is safe however.
|
||||||
|
// FIXME: Update docs based on outcome of RFC #2582 and friends.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
|
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
|
||||||
pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
|
pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
|
||||||
|
|
|
@ -422,11 +422,6 @@ rustc_queries! {
|
||||||
"const-evaluating `{}`",
|
"const-evaluating `{}`",
|
||||||
tcx.def_path_str(key.value.instance.def.def_id())
|
tcx.def_path_str(key.value.instance.def.def_id())
|
||||||
}
|
}
|
||||||
cache_on_disk_if(_, opt_result) {
|
|
||||||
// Only store results without errors
|
|
||||||
// FIXME: We never store these
|
|
||||||
opt_result.map_or(true, |r| r.is_ok())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Results of evaluating const items or constants embedded in
|
/// Results of evaluating const items or constants embedded in
|
||||||
|
|
|
@ -201,28 +201,22 @@ impl<'sess> OnDiskCache<'sess> {
|
||||||
let mut query_result_index = EncodedQueryResultIndex::new();
|
let mut query_result_index = EncodedQueryResultIndex::new();
|
||||||
|
|
||||||
time(tcx.sess, "encode query results", || {
|
time(tcx.sess, "encode query results", || {
|
||||||
use crate::ty::query::queries::*;
|
|
||||||
let enc = &mut encoder;
|
let enc = &mut encoder;
|
||||||
let qri = &mut query_result_index;
|
let qri = &mut query_result_index;
|
||||||
|
|
||||||
encode_query_results::<type_of<'_>, _>(tcx, enc, qri)?;
|
macro_rules! encode_queries {
|
||||||
encode_query_results::<generics_of<'_>, _>(tcx, enc, qri)?;
|
($($query:ident,)*) => {
|
||||||
encode_query_results::<predicates_of<'_>, _>(tcx, enc, qri)?;
|
$(
|
||||||
encode_query_results::<used_trait_imports<'_>, _>(tcx, enc, qri)?;
|
encode_query_results::<ty::query::queries::$query<'_>, _>(
|
||||||
encode_query_results::<typeck_tables_of<'_>, _>(tcx, enc, qri)?;
|
tcx,
|
||||||
encode_query_results::<codegen_fulfill_obligation<'_>, _>(tcx, enc, qri)?;
|
enc,
|
||||||
encode_query_results::<optimized_mir<'_>, _>(tcx, enc, qri)?;
|
qri
|
||||||
encode_query_results::<unsafety_check_result<'_>, _>(tcx, enc, qri)?;
|
)?;
|
||||||
encode_query_results::<borrowck<'_>, _>(tcx, enc, qri)?;
|
)*
|
||||||
encode_query_results::<mir_borrowck<'_>, _>(tcx, enc, qri)?;
|
}
|
||||||
encode_query_results::<mir_const_qualif<'_>, _>(tcx, enc, qri)?;
|
}
|
||||||
encode_query_results::<const_is_rvalue_promotable_to_static<'_>, _>(tcx, enc, qri)?;
|
|
||||||
encode_query_results::<symbol_name<'_>, _>(tcx, enc, qri)?;
|
rustc_cached_queries!(encode_queries!);
|
||||||
encode_query_results::<check_match<'_>, _>(tcx, enc, qri)?;
|
|
||||||
encode_query_results::<codegen_fn_attrs<'_>, _>(tcx, enc, qri)?;
|
|
||||||
encode_query_results::<specialization_graph_of<'_>, _>(tcx, enc, qri)?;
|
|
||||||
encode_query_results::<const_eval<'_>, _>(tcx, enc, qri)?;
|
|
||||||
// FIXME: Include const_eval_raw?
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
|
|
@ -234,7 +234,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Effectively no-ops
|
// Effectively no-ops
|
||||||
"uninit" | "forget" => {
|
"forget" => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
"needs_drop" => {
|
"needs_drop" => {
|
||||||
|
|
|
@ -414,6 +414,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||||
let mut dep_node_force_stream = quote! {};
|
let mut dep_node_force_stream = quote! {};
|
||||||
let mut try_load_from_on_disk_cache_stream = quote! {};
|
let mut try_load_from_on_disk_cache_stream = quote! {};
|
||||||
let mut no_force_queries = Vec::new();
|
let mut no_force_queries = Vec::new();
|
||||||
|
let mut cached_queries = quote! {};
|
||||||
|
|
||||||
for group in groups.0 {
|
for group in groups.0 {
|
||||||
let mut group_stream = quote! {};
|
let mut group_stream = quote! {};
|
||||||
|
@ -427,6 +428,12 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||||
_ => quote! { #result_full },
|
_ => quote! { #result_full },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if modifiers.cache.is_some() {
|
||||||
|
cached_queries.extend(quote! {
|
||||||
|
#name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if modifiers.cache.is_some() && !modifiers.no_force {
|
if modifiers.cache.is_some() && !modifiers.no_force {
|
||||||
try_load_from_on_disk_cache_stream.extend(quote! {
|
try_load_from_on_disk_cache_stream.extend(quote! {
|
||||||
DepKind::#name => {
|
DepKind::#name => {
|
||||||
|
@ -549,6 +556,12 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
macro_rules! rustc_cached_queries {
|
||||||
|
($($macro:tt)*) => {
|
||||||
|
$($macro)*(#cached_queries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#query_description_stream
|
#query_description_stream
|
||||||
|
|
||||||
impl DepNode {
|
impl DepNode {
|
||||||
|
|
|
@ -228,10 +228,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 5. Create everything else: the guards and the arms.
|
// Step 5. Create everything else: the guards and the arms.
|
||||||
|
let match_scope = self.scopes.topmost();
|
||||||
|
|
||||||
let arm_end_blocks: Vec<_> = arm_candidates.into_iter().map(|(arm, mut candidates)| {
|
let arm_end_blocks: Vec<_> = arm_candidates.into_iter().map(|(arm, mut candidates)| {
|
||||||
let arm_source_info = self.source_info(arm.span);
|
let arm_source_info = self.source_info(arm.span);
|
||||||
let region_scope = (arm.scope, arm_source_info);
|
let arm_scope = (arm.scope, arm_source_info);
|
||||||
self.in_scope(region_scope, arm.lint_level, |this| {
|
self.in_scope(arm_scope, arm.lint_level, |this| {
|
||||||
let body = this.hir.mirror(arm.body.clone());
|
let body = this.hir.mirror(arm.body.clone());
|
||||||
let scope = this.declare_bindings(
|
let scope = this.declare_bindings(
|
||||||
None,
|
None,
|
||||||
|
@ -248,7 +250,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
arm.guard.clone(),
|
arm.guard.clone(),
|
||||||
&fake_borrow_temps,
|
&fake_borrow_temps,
|
||||||
scrutinee_span,
|
scrutinee_span,
|
||||||
region_scope,
|
match_scope,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
arm_block = this.cfg.start_new_block();
|
arm_block = this.cfg.start_new_block();
|
||||||
|
@ -259,7 +261,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
arm.guard.clone(),
|
arm.guard.clone(),
|
||||||
&fake_borrow_temps,
|
&fake_borrow_temps,
|
||||||
scrutinee_span,
|
scrutinee_span,
|
||||||
region_scope,
|
match_scope,
|
||||||
);
|
);
|
||||||
this.cfg.terminate(
|
this.cfg.terminate(
|
||||||
binding_end,
|
binding_end,
|
||||||
|
@ -1339,7 +1341,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
guard: Option<Guard<'tcx>>,
|
guard: Option<Guard<'tcx>>,
|
||||||
fake_borrows: &Vec<(&Place<'tcx>, Local)>,
|
fake_borrows: &Vec<(&Place<'tcx>, Local)>,
|
||||||
scrutinee_span: Span,
|
scrutinee_span: Span,
|
||||||
region_scope: (region::Scope, SourceInfo),
|
region_scope: region::Scope,
|
||||||
) -> BasicBlock {
|
) -> BasicBlock {
|
||||||
debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
|
debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
|
||||||
|
|
||||||
|
|
|
@ -604,9 +604,18 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
let arg_scope_s = (arg_scope, source_info);
|
let arg_scope_s = (arg_scope, source_info);
|
||||||
unpack!(block = builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
|
// `return_block` is called when we evaluate a `return` expression, so
|
||||||
builder.args_and_body(block, &arguments, arg_scope, &body.value)
|
// we just use `START_BLOCK` here.
|
||||||
}));
|
unpack!(block = builder.in_breakable_scope(
|
||||||
|
None,
|
||||||
|
START_BLOCK,
|
||||||
|
Place::RETURN_PLACE,
|
||||||
|
|builder| {
|
||||||
|
builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
|
||||||
|
builder.args_and_body(block, &arguments, arg_scope, &body.value)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
));
|
||||||
// Attribute epilogue to function's closing brace
|
// Attribute epilogue to function's closing brace
|
||||||
let fn_end = span.shrink_to_hi();
|
let fn_end = span.shrink_to_hi();
|
||||||
let source_info = builder.source_info(fn_end);
|
let source_info = builder.source_info(fn_end);
|
||||||
|
@ -860,11 +869,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = self.hir.mirror(ast_body);
|
let body = self.hir.mirror(ast_body);
|
||||||
// `return_block` is called when we evaluate a `return` expression, so
|
self.into(&Place::RETURN_PLACE, block, body)
|
||||||
// we just use `START_BLOCK` here.
|
|
||||||
self.in_breakable_scope(None, START_BLOCK, Place::RETURN_PLACE, |this| {
|
|
||||||
this.into(&Place::RETURN_PLACE, block, body)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_unit_temp(&mut self) -> Place<'tcx> {
|
fn get_unit_temp(&mut self) -> Place<'tcx> {
|
||||||
|
|
|
@ -332,9 +332,9 @@ impl<'tcx> Scopes<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn num_scopes_to(&self, region_scope: (region::Scope, SourceInfo), span: Span) -> usize {
|
fn num_scopes_above(&self, region_scope: region::Scope, span: Span) -> usize {
|
||||||
let scope_count = 1 + self.scopes.iter().rev()
|
let scope_count = self.scopes.iter().rev()
|
||||||
.position(|scope| scope.region_scope == region_scope.0)
|
.position(|scope| scope.region_scope == region_scope)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
span_bug!(span, "region_scope {:?} does not enclose", region_scope)
|
span_bug!(span, "region_scope {:?} does not enclose", region_scope)
|
||||||
});
|
});
|
||||||
|
@ -354,7 +354,7 @@ impl<'tcx> Scopes<'tcx> {
|
||||||
|
|
||||||
/// Returns the topmost active scope, which is known to be alive until
|
/// Returns the topmost active scope, which is known to be alive until
|
||||||
/// the next scope expression.
|
/// the next scope expression.
|
||||||
fn topmost(&self) -> region::Scope {
|
pub(super) fn topmost(&self) -> region::Scope {
|
||||||
self.scopes.last().expect("topmost_scope: no scopes present").region_scope
|
self.scopes.last().expect("topmost_scope: no scopes present").region_scope
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,7 +514,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
assert!(value.is_none(), "`return` and `break` should have a destination");
|
assert!(value.is_none(), "`return` and `break` should have a destination");
|
||||||
}
|
}
|
||||||
self.exit_scope(source_info.span, (region_scope, source_info), block, target_block);
|
self.exit_scope(source_info.span, region_scope, block, target_block);
|
||||||
self.cfg.start_new_block().unit()
|
self.cfg.start_new_block().unit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,12 +523,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// needed. See module comment for details.
|
/// needed. See module comment for details.
|
||||||
pub fn exit_scope(&mut self,
|
pub fn exit_scope(&mut self,
|
||||||
span: Span,
|
span: Span,
|
||||||
region_scope: (region::Scope, SourceInfo),
|
region_scope: region::Scope,
|
||||||
mut block: BasicBlock,
|
mut block: BasicBlock,
|
||||||
target: BasicBlock) {
|
target: BasicBlock) {
|
||||||
debug!("exit_scope(region_scope={:?}, block={:?}, target={:?})",
|
debug!("exit_scope(region_scope={:?}, block={:?}, target={:?})",
|
||||||
region_scope, block, target);
|
region_scope, block, target);
|
||||||
let scope_count = self.scopes.num_scopes_to(region_scope, span);
|
let scope_count = self.scopes.num_scopes_above(region_scope, span);
|
||||||
|
|
||||||
// If we are emitting a `drop` statement, we need to have the cached
|
// If we are emitting a `drop` statement, we need to have the cached
|
||||||
// diverge cleanup pads ready in case that drop panics.
|
// diverge cleanup pads ready in case that drop panics.
|
||||||
|
@ -545,7 +545,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let source_info = scope.source_info(span);
|
let source_info = scope.source_info(span);
|
||||||
block = match scope.cached_exits.entry((target, region_scope.0)) {
|
block = match scope.cached_exits.entry((target, region_scope)) {
|
||||||
Entry::Occupied(e) => {
|
Entry::Occupied(e) => {
|
||||||
self.cfg.terminate(block, source_info,
|
self.cfg.terminate(block, source_info,
|
||||||
TerminatorKind::Goto { target: *e.get() });
|
TerminatorKind::Goto { target: *e.get() });
|
||||||
|
|
|
@ -75,7 +75,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
|
||||||
// If unresolved type isn't a ty_var then unresolved_type_span is None
|
// If unresolved type isn't a ty_var then unresolved_type_span is None
|
||||||
self.fcx.need_type_info_err_in_generator(
|
self.fcx.need_type_info_err_in_generator(
|
||||||
self.kind,
|
self.kind,
|
||||||
unresolved_type_span.unwrap_or(yield_data.span),
|
unresolved_type_span.unwrap_or(source_span),
|
||||||
unresolved_type,
|
unresolved_type,
|
||||||
)
|
)
|
||||||
.span_note(yield_data.span, &*note)
|
.span_note(yield_data.span, &*note)
|
||||||
|
|
|
@ -145,7 +145,6 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
|
||||||
"rustc_peek" => (1, vec![param(0)], param(0)),
|
"rustc_peek" => (1, vec![param(0)], param(0)),
|
||||||
"panic_if_uninhabited" => (1, Vec::new(), tcx.mk_unit()),
|
"panic_if_uninhabited" => (1, Vec::new(), tcx.mk_unit()),
|
||||||
"init" => (1, Vec::new(), param(0)),
|
"init" => (1, Vec::new(), param(0)),
|
||||||
"uninit" => (1, Vec::new(), param(0)),
|
|
||||||
"forget" => (1, vec![param(0)], tcx.mk_unit()),
|
"forget" => (1, vec![param(0)], tcx.mk_unit()),
|
||||||
"transmute" => (2, vec![ param(0) ], param(1)),
|
"transmute" => (2, vec![ param(0) ], param(1)),
|
||||||
"move_val_init" => {
|
"move_val_init" => {
|
||||||
|
|
|
@ -392,7 +392,7 @@ impl fmt::Debug for Item {
|
||||||
impl Item {
|
impl Item {
|
||||||
/// Finds the `doc` attribute as a NameValue and returns the corresponding
|
/// Finds the `doc` attribute as a NameValue and returns the corresponding
|
||||||
/// value found.
|
/// value found.
|
||||||
pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
|
pub fn doc_value(&self) -> Option<&str> {
|
||||||
self.attrs.doc_value()
|
self.attrs.doc_value()
|
||||||
}
|
}
|
||||||
/// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
|
/// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
|
||||||
|
@ -699,11 +699,11 @@ impl<'a> Iterator for ListAttributesIter<'a> {
|
||||||
|
|
||||||
pub trait AttributesExt {
|
pub trait AttributesExt {
|
||||||
/// Finds an attribute as List and returns the list of attributes nested inside.
|
/// Finds an attribute as List and returns the list of attributes nested inside.
|
||||||
fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a>;
|
fn lists(&self, name: Symbol) -> ListAttributesIter<'_>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AttributesExt for [ast::Attribute] {
|
impl AttributesExt for [ast::Attribute] {
|
||||||
fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a> {
|
fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
|
||||||
ListAttributesIter {
|
ListAttributesIter {
|
||||||
attrs: self.iter(),
|
attrs: self.iter(),
|
||||||
current_list: Vec::new().into_iter(),
|
current_list: Vec::new().into_iter(),
|
||||||
|
@ -952,7 +952,7 @@ impl Attributes {
|
||||||
|
|
||||||
/// Finds the `doc` attribute as a NameValue and returns the corresponding
|
/// Finds the `doc` attribute as a NameValue and returns the corresponding
|
||||||
/// value found.
|
/// value found.
|
||||||
pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
|
pub fn doc_value(&self) -> Option<&str> {
|
||||||
self.doc_strings.first().map(|s| s.as_str())
|
self.doc_strings.first().map(|s| s.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1037,7 +1037,7 @@ impl Hash for Attributes {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AttributesExt for Attributes {
|
impl AttributesExt for Attributes {
|
||||||
fn lists<'a>(&'a self, name: Symbol) -> ListAttributesIter<'a> {
|
fn lists(&self, name: Symbol) -> ListAttributesIter<'_> {
|
||||||
self.other_attrs.lists(name)
|
self.other_attrs.lists(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2541,7 +2541,7 @@ fn full_path(cx: &Context, item: &clean::Item) -> String {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shorter<'a>(s: Option<&'a str>) -> String {
|
fn shorter(s: Option<&str>) -> String {
|
||||||
match s {
|
match s {
|
||||||
Some(s) => s.lines()
|
Some(s) => s.lines()
|
||||||
.skip_while(|s| s.chars().all(|c| c.is_whitespace()))
|
.skip_while(|s| s.chars().all(|c| c.is_whitespace()))
|
||||||
|
|
|
@ -146,6 +146,10 @@ img {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
.source .content {
|
.source .content {
|
||||||
margin-top: 50px;
|
margin-top: 50px;
|
||||||
max-width: none;
|
max-width: none;
|
||||||
|
|
|
@ -119,7 +119,7 @@ impl TocBuilder {
|
||||||
/// Push a level `level` heading into the appropriate place in the
|
/// Push a level `level` heading into the appropriate place in the
|
||||||
/// hierarchy, returning a string containing the section number in
|
/// hierarchy, returning a string containing the section number in
|
||||||
/// `<num>.<num>.<num>` format.
|
/// `<num>.<num>.<num>` format.
|
||||||
pub fn push<'a>(&'a mut self, level: u32, name: String, id: String) -> &'a str {
|
pub fn push(&mut self, level: u32, name: String, id: String) -> &str {
|
||||||
assert!(level >= 1);
|
assert!(level >= 1);
|
||||||
|
|
||||||
// collapse all previous sections into their parents until we
|
// collapse all previous sections into their parents until we
|
||||||
|
|
|
@ -17,7 +17,7 @@ use crate::html::markdown::{ErrorCodes, IdMap, Markdown, MarkdownWithToc, find_t
|
||||||
use crate::test::{TestOptions, Collector};
|
use crate::test::{TestOptions, Collector};
|
||||||
|
|
||||||
/// Separate any lines at the start of the file that begin with `# ` or `%`.
|
/// Separate any lines at the start of the file that begin with `# ` or `%`.
|
||||||
fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) {
|
fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
|
||||||
let mut metadata = Vec::new();
|
let mut metadata = Vec::new();
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
||||||
|
|
|
@ -1031,7 +1031,7 @@ impl Json {
|
||||||
|
|
||||||
/// If the Json value is an Object, returns the value associated with the provided key.
|
/// If the Json value is an Object, returns the value associated with the provided key.
|
||||||
/// Otherwise, returns None.
|
/// Otherwise, returns None.
|
||||||
pub fn find<'a>(&'a self, key: &str) -> Option<&'a Json>{
|
pub fn find(&self, key: &str) -> Option<&Json> {
|
||||||
match *self {
|
match *self {
|
||||||
Json::Object(ref map) => map.get(key),
|
Json::Object(ref map) => map.get(key),
|
||||||
_ => None
|
_ => None
|
||||||
|
@ -1052,7 +1052,7 @@ impl Json {
|
||||||
/// If the Json value is an Object, performs a depth-first search until
|
/// If the Json value is an Object, performs a depth-first search until
|
||||||
/// a value associated with the provided key is found. If no value is found
|
/// a value associated with the provided key is found. If no value is found
|
||||||
/// or the Json value is not an Object, returns `None`.
|
/// or the Json value is not an Object, returns `None`.
|
||||||
pub fn search<'a>(&'a self, key: &str) -> Option<&'a Json> {
|
pub fn search(&self, key: &str) -> Option<&Json> {
|
||||||
match self {
|
match self {
|
||||||
&Json::Object(ref map) => {
|
&Json::Object(ref map) => {
|
||||||
match map.get(key) {
|
match map.get(key) {
|
||||||
|
|
|
@ -140,7 +140,7 @@ fn wait_timeout_receiver<'a, 'b, T>(lock: &'a Mutex<State<T>>,
|
||||||
new_guard
|
new_guard
|
||||||
}
|
}
|
||||||
|
|
||||||
fn abort_selection<'a, T>(guard: &mut MutexGuard<'a , State<T>>) -> bool {
|
fn abort_selection<T>(guard: &mut MutexGuard<'_, State<T>>) -> bool {
|
||||||
match mem::replace(&mut guard.blocker, NoneBlocked) {
|
match mem::replace(&mut guard.blocker, NoneBlocked) {
|
||||||
NoneBlocked => true,
|
NoneBlocked => true,
|
||||||
BlockedSender(token) => {
|
BlockedSender(token) => {
|
||||||
|
|
|
@ -673,7 +673,7 @@ impl UnixListener {
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
#[stable(feature = "unix_socket_redox", since = "1.29.0")]
|
||||||
pub fn incoming<'a>(&'a self) -> Incoming<'a> {
|
pub fn incoming(&self) -> Incoming<'_> {
|
||||||
Incoming { listener: self }
|
Incoming { listener: self }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,7 +198,7 @@ impl SocketAddr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn address<'a>(&'a self) -> AddressKind<'a> {
|
fn address(&self) -> AddressKind<'_> {
|
||||||
let len = self.len as usize - sun_path_offset(&self.addr);
|
let len = self.len as usize - sun_path_offset(&self.addr);
|
||||||
let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
|
let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
|
||||||
|
|
||||||
|
@ -894,7 +894,7 @@ impl UnixListener {
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||||
pub fn incoming<'a>(&'a self) -> Incoming<'a> {
|
pub fn incoming(&self) -> Incoming<'_> {
|
||||||
Incoming { listener: self }
|
Incoming { listener: self }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,7 +195,7 @@ fn wide_char_to_multi_byte(code_page: u32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
|
pub fn truncate_utf16_at_nul(v: &[u16]) -> &[u16] {
|
||||||
match v.iter().position(|c| *c == 0) {
|
match v.iter().position(|c| *c == 0) {
|
||||||
// don't include the 0
|
// don't include the 0
|
||||||
Some(i) => &v[..i],
|
Some(i) => &v[..i],
|
||||||
|
|
|
@ -19,7 +19,7 @@ pub fn is_verbatim_sep(b: u8) -> bool {
|
||||||
b == b'\\'
|
b == b'\\'
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_prefix<'a>(path: &'a OsStr) -> Option<Prefix<'a>> {
|
pub fn parse_prefix(path: &OsStr) -> Option<Prefix<'_>> {
|
||||||
use crate::path::Prefix::*;
|
use crate::path::Prefix::*;
|
||||||
unsafe {
|
unsafe {
|
||||||
// The unsafety here stems from converting between &OsStr and &[u8]
|
// The unsafety here stems from converting between &OsStr and &[u8]
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub mod test {
|
||||||
p.join(path)
|
p.join(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn path<'a>(&'a self) -> &'a Path {
|
pub fn path(&self) -> &Path {
|
||||||
let TempDir(ref p) = *self;
|
let TempDir(ref p) = *self;
|
||||||
p
|
p
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ use crate::tokenstream::TokenTree;
|
||||||
|
|
||||||
use errors::{Applicability, DiagnosticBuilder, Handler};
|
use errors::{Applicability, DiagnosticBuilder, Handler};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
use rustc_data_structures::sync::Lock;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
|
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
@ -573,6 +574,9 @@ declare_features! (
|
||||||
// Allows `impl Trait` with multiple unrelated lifetimes.
|
// Allows `impl Trait` with multiple unrelated lifetimes.
|
||||||
(active, member_constraints, "1.37.0", Some(61977), None),
|
(active, member_constraints, "1.37.0", Some(61977), None),
|
||||||
|
|
||||||
|
// Allows `async || body` closures.
|
||||||
|
(active, async_closure, "1.37.0", Some(62290), None),
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// feature-group-end: actual feature gates
|
// feature-group-end: actual feature gates
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
@ -2191,9 +2195,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||||
"labels on blocks are unstable");
|
"labels on blocks are unstable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Closure(_, ast::IsAsync::Async { .. }, ..) => {
|
|
||||||
gate_feature_post!(&self, async_await, e.span, "async closures are unstable");
|
|
||||||
}
|
|
||||||
ast::ExprKind::Async(..) => {
|
ast::ExprKind::Async(..) => {
|
||||||
gate_feature_post!(&self, async_await, e.span, "async blocks are unstable");
|
gate_feature_post!(&self, async_await, e.span, "async blocks are unstable");
|
||||||
}
|
}
|
||||||
|
@ -2527,6 +2528,10 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
|
||||||
features
|
features
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn for_each_in_lock<T>(vec: &Lock<Vec<T>>, f: impl Fn(&T)) {
|
||||||
|
vec.borrow().iter().for_each(f);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn check_crate(krate: &ast::Crate,
|
pub fn check_crate(krate: &ast::Crate,
|
||||||
sess: &ParseSess,
|
sess: &ParseSess,
|
||||||
features: &Features,
|
features: &Features,
|
||||||
|
@ -2539,27 +2544,26 @@ pub fn check_crate(krate: &ast::Crate,
|
||||||
plugin_attributes,
|
plugin_attributes,
|
||||||
};
|
};
|
||||||
|
|
||||||
sess
|
for_each_in_lock(&sess.param_attr_spans, |span| gate_feature!(
|
||||||
.param_attr_spans
|
&ctx,
|
||||||
.borrow()
|
param_attrs,
|
||||||
.iter()
|
*span,
|
||||||
.for_each(|span| gate_feature!(
|
"attributes on function parameters are unstable"
|
||||||
&ctx,
|
));
|
||||||
param_attrs,
|
|
||||||
*span,
|
|
||||||
"attributes on function parameters are unstable"
|
|
||||||
));
|
|
||||||
|
|
||||||
sess
|
for_each_in_lock(&sess.let_chains_spans, |span| gate_feature!(
|
||||||
.let_chains_spans
|
&ctx,
|
||||||
.borrow()
|
let_chains,
|
||||||
.iter()
|
*span,
|
||||||
.for_each(|span| gate_feature!(
|
"`let` expressions in this position are experimental"
|
||||||
&ctx,
|
));
|
||||||
let_chains,
|
|
||||||
*span,
|
for_each_in_lock(&sess.async_closure_spans, |span| gate_feature!(
|
||||||
"`let` expressions in this position are experimental"
|
&ctx,
|
||||||
));
|
async_closure,
|
||||||
|
*span,
|
||||||
|
"async closures are unstable"
|
||||||
|
));
|
||||||
|
|
||||||
let visitor = &mut PostExpansionVisitor {
|
let visitor = &mut PostExpansionVisitor {
|
||||||
context: &ctx,
|
context: &ctx,
|
||||||
|
|
|
@ -1452,6 +1452,7 @@ mod tests {
|
||||||
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
||||||
param_attr_spans: Lock::new(Vec::new()),
|
param_attr_spans: Lock::new(Vec::new()),
|
||||||
let_chains_spans: Lock::new(Vec::new()),
|
let_chains_spans: Lock::new(Vec::new()),
|
||||||
|
async_closure_spans: Lock::new(Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,8 @@ pub struct ParseSess {
|
||||||
pub param_attr_spans: Lock<Vec<Span>>,
|
pub param_attr_spans: Lock<Vec<Span>>,
|
||||||
// Places where `let` exprs were used and should be feature gated according to `let_chains`.
|
// Places where `let` exprs were used and should be feature gated according to `let_chains`.
|
||||||
pub let_chains_spans: Lock<Vec<Span>>,
|
pub let_chains_spans: Lock<Vec<Span>>,
|
||||||
|
// Places where `async || ..` exprs were used and should be feature gated.
|
||||||
|
pub async_closure_spans: Lock<Vec<Span>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseSess {
|
impl ParseSess {
|
||||||
|
@ -84,6 +86,7 @@ impl ParseSess {
|
||||||
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
||||||
param_attr_spans: Lock::new(Vec::new()),
|
param_attr_spans: Lock::new(Vec::new()),
|
||||||
let_chains_spans: Lock::new(Vec::new()),
|
let_chains_spans: Lock::new(Vec::new()),
|
||||||
|
async_closure_spans: Lock::new(Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3221,21 +3221,24 @@ impl<'a> Parser<'a> {
|
||||||
-> PResult<'a, P<Expr>>
|
-> PResult<'a, P<Expr>>
|
||||||
{
|
{
|
||||||
let lo = self.token.span;
|
let lo = self.token.span;
|
||||||
|
|
||||||
let movability = if self.eat_keyword(kw::Static) {
|
let movability = if self.eat_keyword(kw::Static) {
|
||||||
Movability::Static
|
Movability::Static
|
||||||
} else {
|
} else {
|
||||||
Movability::Movable
|
Movability::Movable
|
||||||
};
|
};
|
||||||
|
|
||||||
let asyncness = if self.token.span.rust_2018() {
|
let asyncness = if self.token.span.rust_2018() {
|
||||||
self.parse_asyncness()
|
self.parse_asyncness()
|
||||||
} else {
|
} else {
|
||||||
IsAsync::NotAsync
|
IsAsync::NotAsync
|
||||||
};
|
};
|
||||||
let capture_clause = if self.eat_keyword(kw::Move) {
|
if asyncness.is_async() {
|
||||||
CaptureBy::Value
|
// Feature gate `async ||` closures.
|
||||||
} else {
|
self.sess.async_closure_spans.borrow_mut().push(self.prev_span);
|
||||||
CaptureBy::Ref
|
}
|
||||||
};
|
|
||||||
|
let capture_clause = self.parse_capture_clause();
|
||||||
let decl = self.parse_fn_block_decl()?;
|
let decl = self.parse_fn_block_decl()?;
|
||||||
let decl_hi = self.prev_span;
|
let decl_hi = self.prev_span;
|
||||||
let body = match decl.output {
|
let body = match decl.output {
|
||||||
|
@ -3257,7 +3260,7 @@ impl<'a> Parser<'a> {
|
||||||
attrs))
|
attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
// `else` token already eaten
|
/// `else` token already eaten
|
||||||
fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
|
fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
|
||||||
if self.eat_keyword(kw::If) {
|
if self.eat_keyword(kw::If) {
|
||||||
return self.parse_if_expr(ThinVec::new());
|
return self.parse_if_expr(ThinVec::new());
|
||||||
|
@ -3306,7 +3309,7 @@ impl<'a> Parser<'a> {
|
||||||
Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs))
|
Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse `loop {...}`, `loop` token already eaten
|
/// Parse `loop {...}`, `loop` token already eaten.
|
||||||
fn parse_loop_expr(&mut self, opt_label: Option<Label>,
|
fn parse_loop_expr(&mut self, opt_label: Option<Label>,
|
||||||
span_lo: Span,
|
span_lo: Span,
|
||||||
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
||||||
|
@ -3316,17 +3319,20 @@ impl<'a> Parser<'a> {
|
||||||
Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs))
|
Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses an `async move {...}` expression.
|
/// Parse an optional `move` prefix to a closure lke construct.
|
||||||
pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>)
|
fn parse_capture_clause(&mut self) -> CaptureBy {
|
||||||
-> PResult<'a, P<Expr>>
|
if self.eat_keyword(kw::Move) {
|
||||||
{
|
|
||||||
let span_lo = self.token.span;
|
|
||||||
self.expect_keyword(kw::Async)?;
|
|
||||||
let capture_clause = if self.eat_keyword(kw::Move) {
|
|
||||||
CaptureBy::Value
|
CaptureBy::Value
|
||||||
} else {
|
} else {
|
||||||
CaptureBy::Ref
|
CaptureBy::Ref
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses an `async move? {...}` expression.
|
||||||
|
pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
|
||||||
|
let span_lo = self.token.span;
|
||||||
|
self.expect_keyword(kw::Async)?;
|
||||||
|
let capture_clause = self.parse_capture_clause();
|
||||||
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
||||||
attrs.extend(iattrs);
|
attrs.extend(iattrs);
|
||||||
Ok(self.mk_expr(
|
Ok(self.mk_expr(
|
||||||
|
|
|
@ -146,6 +146,7 @@ symbols! {
|
||||||
associated_type_defaults,
|
associated_type_defaults,
|
||||||
associated_types,
|
associated_types,
|
||||||
async_await,
|
async_await,
|
||||||
|
async_closure,
|
||||||
attr,
|
attr,
|
||||||
attributes,
|
attributes,
|
||||||
attr_literals,
|
attr_literals,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await)]
|
||||||
|
|
||||||
#[path = "../auxiliary/arc_wake.rs"]
|
#[path = "../auxiliary/arc_wake.rs"]
|
||||||
mod arc_wake;
|
mod arc_wake;
|
||||||
|
@ -58,31 +58,31 @@ fn wait(fut: impl Future<Output = u8>) -> u8 {
|
||||||
fn base() -> WakeOnceThenComplete { WakeOnceThenComplete(false, 1) }
|
fn base() -> WakeOnceThenComplete { WakeOnceThenComplete(false, 1) }
|
||||||
|
|
||||||
async fn await1_level1() -> u8 {
|
async fn await1_level1() -> u8 {
|
||||||
await!(base())
|
base().await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn await2_level1() -> u8 {
|
async fn await2_level1() -> u8 {
|
||||||
await!(base()) + await!(base())
|
base().await + base().await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn await3_level1() -> u8 {
|
async fn await3_level1() -> u8 {
|
||||||
await!(base()) + await!(base()) + await!(base())
|
base().await + base().await + base().await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn await3_level2() -> u8 {
|
async fn await3_level2() -> u8 {
|
||||||
await!(await3_level1()) + await!(await3_level1()) + await!(await3_level1())
|
await3_level1().await + await3_level1().await + await3_level1().await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn await3_level3() -> u8 {
|
async fn await3_level3() -> u8 {
|
||||||
await!(await3_level2()) + await!(await3_level2()) + await!(await3_level2())
|
await3_level2().await + await3_level2().await + await3_level2().await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn await3_level4() -> u8 {
|
async fn await3_level4() -> u8 {
|
||||||
await!(await3_level3()) + await!(await3_level3()) + await!(await3_level3())
|
await3_level3().await + await3_level3().await + await3_level3().await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn await3_level5() -> u8 {
|
async fn await3_level5() -> u8 {
|
||||||
await!(await3_level4()) + await!(await3_level4()) + await!(await3_level4())
|
await3_level4().await + await3_level4().await + await3_level4().await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// handled incorrectly in generators.
|
// handled incorrectly in generators.
|
||||||
// compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018
|
// compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018
|
||||||
|
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await)]
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
@ -22,7 +22,7 @@ impl Future for Never {
|
||||||
fn main() {
|
fn main() {
|
||||||
let fut = async {
|
let fut = async {
|
||||||
let _rc = Rc::new(()); // Also crashes with Arc
|
let _rc = Rc::new(()); // Also crashes with Arc
|
||||||
await!(Never());
|
Never().await;
|
||||||
};
|
};
|
||||||
let _bla = fut; // Moving the future is required.
|
let _bla = fut; // Moving the future is required.
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
// run-pass
|
|
||||||
// pretty-expanded FIXME #23616
|
|
||||||
|
|
||||||
#![feature(intrinsics)]
|
|
||||||
|
|
||||||
mod rusti {
|
|
||||||
extern "rust-intrinsic" {
|
|
||||||
pub fn uninit<T>() -> T;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn main() {
|
|
||||||
let _a : isize = unsafe {rusti::uninit()};
|
|
||||||
}
|
|
|
@ -70,13 +70,6 @@ fn async_nonmove_block(x: u8) -> impl Future<Output = u8> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn async_closure(x: u8) -> impl Future<Output = u8> {
|
|
||||||
(async move |x: u8| -> u8 {
|
|
||||||
wake_and_yield_once().await;
|
|
||||||
x
|
|
||||||
})(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn async_fn(x: u8) -> u8 {
|
async fn async_fn(x: u8) -> u8 {
|
||||||
wake_and_yield_once().await;
|
wake_and_yield_once().await;
|
||||||
x
|
x
|
||||||
|
@ -180,7 +173,6 @@ fn main() {
|
||||||
test! {
|
test! {
|
||||||
async_block,
|
async_block,
|
||||||
async_nonmove_block,
|
async_nonmove_block,
|
||||||
async_closure,
|
|
||||||
async_fn,
|
async_fn,
|
||||||
generic_async_fn,
|
generic_async_fn,
|
||||||
async_fn_with_internal_borrow,
|
async_fn_with_internal_borrow,
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
// compile-pass
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
#![feature(async_await, async_closure)]
|
||||||
|
|
||||||
|
macro_rules! match_expr {
|
||||||
|
($x:expr) => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match_expr!(async || {});
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
// run-pass
|
||||||
|
|
||||||
|
// edition:2018
|
||||||
|
// aux-build:arc_wake.rs
|
||||||
|
|
||||||
|
#![feature(async_await, async_closure)]
|
||||||
|
|
||||||
|
extern crate arc_wake;
|
||||||
|
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::future::Future;
|
||||||
|
use std::sync::{
|
||||||
|
Arc,
|
||||||
|
atomic::{self, AtomicUsize},
|
||||||
|
};
|
||||||
|
use std::task::{Context, Poll};
|
||||||
|
use arc_wake::ArcWake;
|
||||||
|
|
||||||
|
struct Counter {
|
||||||
|
wakes: AtomicUsize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArcWake for Counter {
|
||||||
|
fn wake(self: Arc<Self>) {
|
||||||
|
Self::wake_by_ref(&self)
|
||||||
|
}
|
||||||
|
fn wake_by_ref(arc_self: &Arc<Self>) {
|
||||||
|
arc_self.wakes.fetch_add(1, atomic::Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WakeOnceThenComplete(bool);
|
||||||
|
|
||||||
|
fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) }
|
||||||
|
|
||||||
|
impl Future for WakeOnceThenComplete {
|
||||||
|
type Output = ();
|
||||||
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
|
||||||
|
if self.0 {
|
||||||
|
Poll::Ready(())
|
||||||
|
} else {
|
||||||
|
cx.waker().wake_by_ref();
|
||||||
|
self.0 = true;
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn async_closure(x: u8) -> impl Future<Output = u8> {
|
||||||
|
(async move |x: u8| -> u8 {
|
||||||
|
wake_and_yield_once().await;
|
||||||
|
x
|
||||||
|
})(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_future_yields_once_then_returns<F, Fut>(f: F)
|
||||||
|
where
|
||||||
|
F: FnOnce(u8) -> Fut,
|
||||||
|
Fut: Future<Output = u8>,
|
||||||
|
{
|
||||||
|
let mut fut = Box::pin(f(9));
|
||||||
|
let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) });
|
||||||
|
let waker = ArcWake::into_waker(counter.clone());
|
||||||
|
let mut cx = Context::from_waker(&waker);
|
||||||
|
assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst));
|
||||||
|
assert_eq!(Poll::Pending, fut.as_mut().poll(&mut cx));
|
||||||
|
assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst));
|
||||||
|
assert_eq!(Poll::Ready(9), fut.as_mut().poll(&mut cx));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
macro_rules! test {
|
||||||
|
($($fn_name:expr,)*) => { $(
|
||||||
|
test_future_yields_once_then_returns($fn_name);
|
||||||
|
)* }
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
async_closure,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
// edition:2018
|
||||||
|
#![feature(async_await)]
|
||||||
|
|
||||||
|
// Regression test for issue #62382
|
||||||
|
|
||||||
|
use std::future::Future;
|
||||||
|
|
||||||
|
fn get_future() -> impl Future<Output = ()> {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn foo() {
|
||||||
|
let a; //~ ERROR type inside `async` object must be known in this context
|
||||||
|
get_future().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0698]: type inside `async` object must be known in this context
|
||||||
|
--> $DIR/async-error-span.rs:13:9
|
||||||
|
|
|
||||||
|
LL | let a;
|
||||||
|
| ^ cannot infer type
|
||||||
|
|
|
||||||
|
note: the type is part of the `async` object because of this `await`
|
||||||
|
--> $DIR/async-error-span.rs:14:5
|
||||||
|
|
|
||||||
|
LL | get_future().await;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0698`.
|
|
@ -1,6 +1,6 @@
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
struct HasLifetime<'a>(&'a bool);
|
struct HasLifetime<'a>(&'a bool);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// build-pass (FIXME(62277): could be check-pass?)
|
// build-pass (FIXME(62277): could be check-pass?)
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await)]
|
||||||
|
|
||||||
macro_rules! match_expr {
|
macro_rules! match_expr {
|
||||||
($x:expr) => {}
|
($x:expr) => {}
|
||||||
|
@ -9,5 +9,4 @@ macro_rules! match_expr {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match_expr!(async {});
|
match_expr!(async {});
|
||||||
match_expr!(async || {});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// build-pass (FIXME(62277): could be check-pass?)
|
// build-pass (FIXME(62277): could be check-pass?)
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await)]
|
||||||
|
|
||||||
trait MyClosure {
|
trait MyClosure {
|
||||||
type Args;
|
type Args;
|
||||||
|
@ -20,7 +20,7 @@ async fn get_future<C: ?Sized + MyClosure>(_stream: MyStream<C>) {}
|
||||||
|
|
||||||
async fn f() {
|
async fn f() {
|
||||||
let messages: MyStream<dyn FnMut()> = unimplemented!();
|
let messages: MyStream<dyn FnMut()> = unimplemented!();
|
||||||
await!(get_future(messages));
|
get_future(messages).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await)]
|
||||||
|
|
||||||
mod outer_mod {
|
mod outer_mod {
|
||||||
pub mod await { //~ ERROR expected identifier, found reserved keyword `await`
|
pub mod await { //~ ERROR expected identifier, found reserved keyword `await`
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// edition:2018
|
// edition:2018
|
||||||
// aux-build:arc_wake.rs
|
// aux-build:arc_wake.rs
|
||||||
|
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await, async_closure, await_macro)]
|
||||||
|
|
||||||
extern crate arc_wake;
|
extern crate arc_wake;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Regression test for #62312
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
#![feature(async_await)]
|
||||||
|
|
||||||
|
async fn make_boxed_object() -> Box<dyn Send> {
|
||||||
|
Box::new(()) as _
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn await_object() {
|
||||||
|
let _ = make_boxed_object().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -3,7 +3,7 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await)]
|
||||||
|
|
||||||
// Test that the drop order for parameters in a fn and async fn matches up. Also test that
|
// Test that the drop order for parameters in a fn and async fn matches up. Also test that
|
||||||
// parameters (used or unused) are not dropped until the async fn completes execution.
|
// parameters (used or unused) are not dropped until the async fn completes execution.
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await)]
|
||||||
|
|
||||||
// Test that the drop order for parameters in a fn and async fn matches up. Also test that
|
// Test that the drop order for parameters in a fn and async fn matches up. Also test that
|
||||||
// parameters (used or unused) are not dropped until the async fn completes execution.
|
// parameters (used or unused) are not dropped until the async fn completes execution.
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
// edition:2018
|
||||||
|
// gate-test-async_closure
|
||||||
|
|
||||||
|
fn f() {
|
||||||
|
let _ = async || {}; //~ ERROR async closures are unstable
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,12 @@
|
||||||
|
error[E0658]: async closures are unstable
|
||||||
|
--> $DIR/feature-async-closure.rs:5:13
|
||||||
|
|
|
||||||
|
LL | let _ = async || {};
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
= note: for more information, see https://github.com/rust-lang/rust/issues/62290
|
||||||
|
= help: add #![feature(async_closure)] to the crate attributes to enable
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
|
@ -1,7 +1,7 @@
|
||||||
// build-pass (FIXME(62277): could be check-pass?)
|
// build-pass (FIXME(62277): could be check-pass?)
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
#![feature(arbitrary_self_types, async_await, await_macro)]
|
#![feature(arbitrary_self_types, async_await)]
|
||||||
|
|
||||||
use std::task::{self, Poll};
|
use std::task::{self, Poll};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
@ -37,11 +37,11 @@ impl<R, F> Future for Lazy<F>
|
||||||
async fn __receive<WantFn, Fut>(want: WantFn) -> ()
|
async fn __receive<WantFn, Fut>(want: WantFn) -> ()
|
||||||
where Fut: Future<Output = ()>, WantFn: Fn(&Box<dyn Send + 'static>) -> Fut,
|
where Fut: Future<Output = ()>, WantFn: Fn(&Box<dyn Send + 'static>) -> Fut,
|
||||||
{
|
{
|
||||||
await!(lazy(|_| ()));
|
lazy(|_| ()).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn basic_spawn_receive() {
|
pub fn basic_spawn_receive() {
|
||||||
async { await!(__receive(|_| async { () })) };
|
async { __receive(|_| async { () }).await };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// build-pass (FIXME(62277): could be check-pass?)
|
// build-pass (FIXME(62277): could be check-pass?)
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await)]
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
// build-pass (FIXME(62277): could be check-pass?)
|
// build-pass (FIXME(62277): could be check-pass?)
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await)]
|
||||||
|
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
async fn foo<F: Future<Output = i32>>(x: &i32, future: F) -> i32 {
|
async fn foo<F: Future<Output = i32>>(x: &i32, future: F) -> i32 {
|
||||||
let y = await!(future);
|
let y = future.await;
|
||||||
*x + y
|
*x + y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// build-pass (FIXME(62277): could be check-pass?)
|
// build-pass (FIXME(62277): could be check-pass?)
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await)]
|
||||||
|
|
||||||
struct Xyz {
|
struct Xyz {
|
||||||
a: u64,
|
a: u64,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// build-pass (FIXME(62277): could be check-pass?)
|
// build-pass (FIXME(62277): could be check-pass?)
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await)]
|
||||||
|
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
// compile-flags: --edition=2018
|
// compile-flags: --edition=2018
|
||||||
|
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await)]
|
||||||
|
|
||||||
pub enum Uninhabited { }
|
pub enum Uninhabited { }
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ async fn noop() { }
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
async fn contains_never() {
|
async fn contains_never() {
|
||||||
let error = uninhabited_async();
|
let error = uninhabited_async();
|
||||||
await!(noop());
|
noop().await;
|
||||||
let error2 = error;
|
let error2 = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@ fn main() {
|
||||||
//~^ ERROR `await` is only allowed inside `async` functions and blocks
|
//~^ ERROR `await` is only allowed inside `async` functions and blocks
|
||||||
let task1 = print_dur().await;
|
let task1 = print_dur().await;
|
||||||
}.await;
|
}.await;
|
||||||
(async || 2333)().await;
|
|
||||||
//~^ ERROR `await` is only allowed inside `async` functions and blocks
|
|
||||||
(|_| 2333).await;
|
(|_| 2333).await;
|
||||||
//~^ ERROR `await` is only allowed inside `async` functions and blocks
|
//~^ ERROR `await` is only allowed inside `async` functions and blocks
|
||||||
//~^^ ERROR
|
//~^^ ERROR
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/issue-62009.rs:8:5
|
--> $DIR/issue-62009-1.rs:8:5
|
||||||
|
|
|
|
||||||
LL | fn main() {
|
LL | fn main() {
|
||||||
| ---- this is not `async`
|
| ---- this is not `async`
|
||||||
|
@ -7,7 +7,7 @@ LL | async { let (); }.await;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
| ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/issue-62009.rs:10:5
|
--> $DIR/issue-62009-1.rs:10:5
|
||||||
|
|
|
|
||||||
LL | fn main() {
|
LL | fn main() {
|
||||||
| ---- this is not `async`
|
| ---- this is not `async`
|
||||||
|
@ -19,16 +19,7 @@ LL | | }.await;
|
||||||
| |___________^ only allowed inside `async` functions and blocks
|
| |___________^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/issue-62009.rs:14:5
|
--> $DIR/issue-62009-1.rs:14:5
|
||||||
|
|
|
||||||
LL | fn main() {
|
|
||||||
| ---- this is not `async`
|
|
||||||
...
|
|
||||||
LL | (async || 2333)().await;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
|
||||||
--> $DIR/issue-62009.rs:16:5
|
|
||||||
|
|
|
|
||||||
LL | fn main() {
|
LL | fn main() {
|
||||||
| ---- this is not `async`
|
| ---- this is not `async`
|
||||||
|
@ -36,14 +27,14 @@ LL | fn main() {
|
||||||
LL | (|_| 2333).await;
|
LL | (|_| 2333).await;
|
||||||
| ^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
| ^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
error[E0277]: the trait bound `[closure@$DIR/issue-62009.rs:16:5: 16:15]: std::future::Future` is not satisfied
|
error[E0277]: the trait bound `[closure@$DIR/issue-62009-1.rs:14:5: 14:15]: std::future::Future` is not satisfied
|
||||||
--> $DIR/issue-62009.rs:16:5
|
--> $DIR/issue-62009-1.rs:14:5
|
||||||
|
|
|
|
||||||
LL | (|_| 2333).await;
|
LL | (|_| 2333).await;
|
||||||
| ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009.rs:16:5: 16:15]`
|
| ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:14:5: 14:15]`
|
||||||
|
|
|
|
||||||
= note: required by `std::future::poll_with_tls_context`
|
= note: required by `std::future::poll_with_tls_context`
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -0,0 +1,10 @@
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
#![feature(async_await, async_closure)]
|
||||||
|
|
||||||
|
async fn print_dur() {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
(async || 2333)().await;
|
||||||
|
//~^ ERROR `await` is only allowed inside `async` functions and blocks
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
|
--> $DIR/issue-62009-2.rs:8:5
|
||||||
|
|
|
||||||
|
LL | fn main() {
|
||||||
|
| ---- this is not `async`
|
||||||
|
LL | (async || 2333)().await;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
// Test that we can use async fns with multiple arbitrary lifetimes.
|
// Test that we can use async fns with multiple arbitrary lifetimes.
|
||||||
|
|
||||||
#![feature(arbitrary_self_types, async_await, await_macro)]
|
#![feature(async_await)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// edition:2018
|
// edition:2018
|
||||||
|
|
||||||
#![feature(async_await, await_macro)]
|
#![feature(async_await, async_closure)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _ = async |x: u8| {};
|
let _ = async |x: u8| {};
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
// Test that impl trait does not allow creating recursive types that are
|
// Test that impl trait does not allow creating recursive types that are
|
||||||
// otherwise forbidden when using `async` and `await`.
|
// otherwise forbidden when using `async` and `await`.
|
||||||
|
|
||||||
#![feature(await_macro, async_await, generators)]
|
#![feature(async_await)]
|
||||||
|
|
||||||
async fn recursive_async_function() -> () { //~ ERROR
|
async fn recursive_async_function() -> () { //~ ERROR
|
||||||
await!(recursive_async_function());
|
recursive_async_function().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
// edition:2018
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![feature(async_await, async_closure)]
|
||||||
|
|
||||||
|
fn take_u32(_x: u32) {}
|
||||||
|
|
||||||
|
async fn make_u32() -> u32 {
|
||||||
|
22
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
async fn suggest_await_in_async_closure() {
|
||||||
|
async || {
|
||||||
|
let x = make_u32();
|
||||||
|
take_u32(x.await)
|
||||||
|
//~^ ERROR mismatched types [E0308]
|
||||||
|
//~| HELP consider using `.await` here
|
||||||
|
//~| SUGGESTION x.await
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,23 @@
|
||||||
|
// edition:2018
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![feature(async_await, async_closure)]
|
||||||
|
|
||||||
|
fn take_u32(_x: u32) {}
|
||||||
|
|
||||||
|
async fn make_u32() -> u32 {
|
||||||
|
22
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
async fn suggest_await_in_async_closure() {
|
||||||
|
async || {
|
||||||
|
let x = make_u32();
|
||||||
|
take_u32(x)
|
||||||
|
//~^ ERROR mismatched types [E0308]
|
||||||
|
//~| HELP consider using `.await` here
|
||||||
|
//~| SUGGESTION x.await
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-missing-await-closure.rs:16:18
|
||||||
|
|
|
||||||
|
LL | take_u32(x)
|
||||||
|
| ^
|
||||||
|
| |
|
||||||
|
| expected u32, found opaque type
|
||||||
|
| help: consider using `.await` here: `x.await`
|
||||||
|
|
|
||||||
|
= note: expected type `u32`
|
||||||
|
found type `impl std::future::Future`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
|
@ -18,15 +18,4 @@ async fn suggest_await_in_async_fn() {
|
||||||
//~| SUGGESTION x.await
|
//~| SUGGESTION x.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
async fn suggest_await_in_async_closure() {
|
|
||||||
async || {
|
|
||||||
let x = make_u32();
|
|
||||||
take_u32(x.await)
|
|
||||||
//~^ ERROR mismatched types [E0308]
|
|
||||||
//~| HELP consider using `.await` here
|
|
||||||
//~| SUGGESTION x.await
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -18,15 +18,4 @@ async fn suggest_await_in_async_fn() {
|
||||||
//~| SUGGESTION x.await
|
//~| SUGGESTION x.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
async fn suggest_await_in_async_closure() {
|
|
||||||
async || {
|
|
||||||
let x = make_u32();
|
|
||||||
take_u32(x)
|
|
||||||
//~^ ERROR mismatched types [E0308]
|
|
||||||
//~| HELP consider using `.await` here
|
|
||||||
//~| SUGGESTION x.await
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -10,18 +10,6 @@ LL | take_u32(x)
|
||||||
= note: expected type `u32`
|
= note: expected type `u32`
|
||||||
found type `impl std::future::Future`
|
found type `impl std::future::Future`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error: aborting due to previous error
|
||||||
--> $DIR/suggest-missing-await.rs:25:18
|
|
||||||
|
|
|
||||||
LL | take_u32(x)
|
|
||||||
| ^
|
|
||||||
| |
|
|
||||||
| expected u32, found opaque type
|
|
||||||
| help: consider using `.await` here: `x.await`
|
|
||||||
|
|
|
||||||
= note: expected type `u32`
|
|
||||||
found type `impl std::future::Future`
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -15,5 +15,4 @@ async fn foo() {} //~ ERROR async fn is unstable
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _ = async {}; //~ ERROR async blocks are unstable
|
let _ = async {}; //~ ERROR async blocks are unstable
|
||||||
let _ = async || {}; //~ ERROR async closures are unstable
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,15 +40,6 @@ LL | let _ = async {};
|
||||||
= note: for more information, see https://github.com/rust-lang/rust/issues/50547
|
= note: for more information, see https://github.com/rust-lang/rust/issues/50547
|
||||||
= help: add #![feature(async_await)] to the crate attributes to enable
|
= help: add #![feature(async_await)] to the crate attributes to enable
|
||||||
|
|
||||||
error[E0658]: async closures are unstable
|
error: aborting due to 5 previous errors
|
||||||
--> $DIR/feature-gate-async-await.rs:18:13
|
|
||||||
|
|
|
||||||
LL | let _ = async || {};
|
|
||||||
| ^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: for more information, see https://github.com/rust-lang/rust/issues/50547
|
|
||||||
= help: add #![feature(async_await)] to the crate attributes to enable
|
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![allow(deprecated)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
|
|
||||||
use std::intrinsics::{init};
|
use std::intrinsics::{init};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
|
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
|
||||||
--> $DIR/init-unsafe.rs:7:17
|
--> $DIR/init-unsafe.rs:8:17
|
||||||
|
|
|
|
||||||
LL | let stuff = init::<isize>();
|
LL | let stuff = init::<isize>();
|
||||||
| ^^^^^^^^^^^^^^^ call to unsafe function
|
| ^^^^^^^^^^^^^^^ call to unsafe function
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
// Regression test for #62312
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = loop {
|
||||||
|
break Box::new(()) as Box<dyn Send>;
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue