Auto merge of #62192 - Centril:rollup-kssnlta, r=Centril

Rollup of 16 pull requests

Successful merges:

 - #61878 (improve pinning projection docs)
 - #62043 (Remove `FnBox`)
 - #62067 (Add suggestion for missing `.await` keyword)
 - #62076 (Updated RELEASES.md for 1.36.0)
 - #62102 (call out explicitly that general read needs to be called with an initialized buffer)
 - #62106 (Add more tests for async/await)
 - #62124 (refactor lexer to use idiomatic borrowing)
 - #62131 (libsyntax: Fix some Clippy warnings)
 - #62152 (Don't ICE on item in `.await` expression)
 - #62154 (Remove old fixme)
 - #62155 (Add regression test for MIR drop generation in async loops)
 - #62156 (Update books)
 - #62160 (Remove outdated question_mark_macro_sep lint)
 - #62164 (save-analysis: use buffered writes)
 - #62171 (rustc: Retry SIGILL linker invocations)
 - #62176 (Update RLS)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-06-28 14:08:07 +00:00
commit 433a467815
68 changed files with 1114 additions and 420 deletions

View File

@ -1,3 +1,104 @@
Version 1.36.0 (2019-07-04)
==========================
Language
--------
- [Non-Lexical Lifetimes are now enabled on the 2015 edition.][59114]
- [The order of traits in trait objects no longer affects the semantics of that
object.][59445] e.g. `dyn Send + fmt::Debug` is now equivalent to
`dyn fmt::Debug + Send`, where this was previously not the case.
Libraries
---------
- [`HashMap`'s implementation has been replaced with `hashbrown::HashMap` implementation.][58623]
- [`TryFromSliceError` now implements `From<Infallible>`.][60318]
- [`mem::needs_drop` is now available as a const fn.][60364]
- [`alloc::Layout::from_size_align_unchecked` is now available as a const fn.][60370]
- [`String` now implements `BorrowMut<str>`.][60404]
- [`io::Cursor` now implements `Default`.][60234]
- [Both `NonNull::{dangling, cast}` are now const fns.][60244]
- [The `alloc` crate is now stable.][59675] `alloc` allows you to use a subset
of `std` (e.g. `Vec`, `Box`, `Arc`) in `#![no_std]` environments if the
environment has access to heap memory allocation.
- [`String` now implements `From<&String>`.][59825]
- [You can now pass multiple arguments to the `dbg!` macro.][59826] `dbg!` will
return a tuple of each argument when there is multiple arguments.
- [`Result::{is_err, is_ok}` are now `#[must_use]` and will produce a warning if
not used.][59648]
Stabilized APIs
---------------
- [`VecDeque::rotate_left`]
- [`VecDeque::rotate_right`]
- [`Iterator::copied`]
- [`io::IoSlice`]
- [`io::IoSliceMut`]
- [`Read::read_vectored`]
- [`Write::write_vectored`]
- [`str::as_mut_ptr`]
- [`mem::MaybeUninit`]
- [`pointer::align_offset`]
- [`future::Future`]
- [`task::Context`]
- [`task::RawWaker`]
- [`task::RawWakerVTable`]
- [`task::Waker`]
- [`task::Poll`]
Cargo
-----
- [Cargo will now produce an error if you attempt to use the name of a required dependency as a feature.][cargo/6860]
- [You can now pass the `--offline` flag to run cargo without accessing the network.][cargo/6934]
You can find further change's in [Cargo's 1.36.0 release notes][cargo-1-36-0].
Clippy
------
There have been numerous additions and fixes to clippy, see [Clippy's 1.36.0 release notes][clippy-1-36-0] for more details.
Misc
----
Compatibility Notes
-------------------
- With the stabilisation of `mem::MaybeUninit`, `mem::uninitialized` use is no
longer recommended, and will be deprecated in 1.38.0.
[60318]: https://github.com/rust-lang/rust/pull/60318/
[60364]: https://github.com/rust-lang/rust/pull/60364/
[60370]: https://github.com/rust-lang/rust/pull/60370/
[60404]: https://github.com/rust-lang/rust/pull/60404/
[60234]: https://github.com/rust-lang/rust/pull/60234/
[60244]: https://github.com/rust-lang/rust/pull/60244/
[58623]: https://github.com/rust-lang/rust/pull/58623/
[59648]: https://github.com/rust-lang/rust/pull/59648/
[59675]: https://github.com/rust-lang/rust/pull/59675/
[59825]: https://github.com/rust-lang/rust/pull/59825/
[59826]: https://github.com/rust-lang/rust/pull/59826/
[59445]: https://github.com/rust-lang/rust/pull/59445/
[59114]: https://github.com/rust-lang/rust/pull/59114/
[cargo/6860]: https://github.com/rust-lang/cargo/pull/6860/
[cargo/6934]: https://github.com/rust-lang/cargo/pull/6934/
[`VecDeque::rotate_left`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.rotate_left
[`VecDeque::rotate_right`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.rotate_right
[`Iterator::copied`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.copied
[`io::IoSlice`]: https://doc.rust-lang.org/std/io/struct.IoSlice.html
[`io::IoSliceMut`]: https://doc.rust-lang.org/std/io/struct.IoSliceMut.html
[`Read::read_vectored`]: https://doc.rust-lang.org/std/io/trait.Read.html#method.read_vectored
[`Write::write_vectored`]: https://doc.rust-lang.org/std/io/trait.Write.html#method.write_vectored
[`str::as_mut_ptr`]: https://doc.rust-lang.org/std/primitive.str.html#method.as_mut_ptr
[`mem::MaybeUninit`]: https://doc.rust-lang.org/std/mem/union.MaybeUninit.html
[`pointer::align_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.align_offset
[`future::Future`]: https://doc.rust-lang.org/std/future/trait.Future.html
[`task::Context`]: https://doc.rust-lang.org/beta/std/task/struct.Context.html
[`task::RawWaker`]: https://doc.rust-lang.org/beta/std/task/struct.RawWaker.html
[`task::RawWakerVTable`]: https://doc.rust-lang.org/beta/std/task/struct.RawWakerVTable.html
[`task::Waker`]: https://doc.rust-lang.org/beta/std/task/struct.Waker.html
[`task::Poll`]: https://doc.rust-lang.org/beta/std/task/enum.Poll.html
[clippy-1-36-0]: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md#rust-136
[cargo-1-36-0]: https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-136-2019-07-04
Version 1.35.0 (2019-05-23)
==========================

@ -1 +1 @@
Subproject commit 9aacfcc4c5b102c8cda195932addefd32fe955d2
Subproject commit 6c0d83499c8e77e06a71d28c5e1adccec278d4f3

@ -1 +1 @@
Subproject commit c656171b749b7307f21371dd0d3278efee5573b8
Subproject commit 341c221116a8b9f1010cf1eece952b80c5ec7f54

@ -1 +1 @@
Subproject commit 08ae27a4921ca53967656a7391c82f6c0ddd1ccc
Subproject commit 7a5aab5fd50d6290679beb4cf42fa5f46ed22aec

@ -1 +1 @@
Subproject commit b27472962986e85c94f4183b1a6d2207660d3ed6
Subproject commit 62b3ff2cb44dd8b648c3ef2a9347c3706d148014

@ -1 +1 @@
Subproject commit f55e97c145cf37fd664db2e0e2f2d05df328bf4f
Subproject commit abf512fc9cc969dcbea69aa15b44586bbeb13c2d

View File

@ -117,9 +117,7 @@ fn main () {
}
```
One of the objectives of this feature is to allow `Box<dyn FnOnce>`, instead of `Box<dyn FnBox>` in the future. See [#28796] for details.
[#28796]: https://github.com/rust-lang/rust/issues/28796
One of the objectives of this feature is to allow `Box<dyn FnOnce>`.
## Variable length arrays

View File

@ -1,32 +0,0 @@
# `fnbox`
The tracking issue for this feature is [#28796]
[#28796]: https://github.com/rust-lang/rust/issues/28796
------------------------
This had been a temporary alternative to the following impls:
```rust,ignore
impl<A, F> FnOnce for Box<F> where F: FnOnce<A> + ?Sized {}
impl<A, F> FnMut for Box<F> where F: FnMut<A> + ?Sized {}
impl<A, F> Fn for Box<F> where F: Fn<A> + ?Sized {}
```
The impls are parallel to these (relatively old) impls:
```rust,ignore
impl<A, F> FnOnce for &mut F where F: FnMut<A> + ?Sized {}
impl<A, F> FnMut for &mut F where F: FnMut<A> + ?Sized {}
impl<A, F> Fn for &mut F where F: Fn<A> + ?Sized {}
impl<A, F> FnOnce for &F where F: Fn<A> + ?Sized {}
impl<A, F> FnMut for &F where F: Fn<A> + ?Sized {}
impl<A, F> Fn for &F where F: Fn<A> + ?Sized {}
```
Before the introduction of [`unsized_locals`][unsized_locals], we had been unable to provide the former impls. That means, unlike `&dyn Fn()` or `&mut dyn FnMut()` we could not use `Box<dyn FnOnce()>` at that time.
[unsized_locals]: ../language-features/unsized-locals.md
`FnBox()` is an alternative approach to `Box<dyn FnBox()>` is delegated to `FnBox::call_box` which doesn't need unsized locals. As we now have `Box<dyn FnOnce()>` working, the `fnbox` feature is going to be removed.

View File

@ -761,85 +761,6 @@ impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> {
}
}
/// `FnBox` is deprecated and will be removed.
/// `Box<dyn FnOnce()>` can be called directly, since Rust 1.35.0.
///
/// `FnBox` is a version of the `FnOnce` intended for use with boxed
/// closure objects. The idea was that where one would normally store a
/// `Box<dyn FnOnce()>` in a data structure, you whould use
/// `Box<dyn FnBox()>`. The two traits behave essentially the same, except
/// that a `FnBox` closure can only be called if it is boxed.
///
/// # Examples
///
/// Here is a snippet of code which creates a hashmap full of boxed
/// once closures and then removes them one by one, calling each
/// closure as it is removed. Note that the type of the closures
/// stored in the map is `Box<dyn FnBox() -> i32>` and not `Box<dyn FnOnce()
/// -> i32>`.
///
/// ```
/// #![feature(fnbox)]
/// #![allow(deprecated)]
///
/// use std::boxed::FnBox;
/// use std::collections::HashMap;
///
/// fn make_map() -> HashMap<i32, Box<dyn FnBox() -> i32>> {
/// let mut map: HashMap<i32, Box<dyn FnBox() -> i32>> = HashMap::new();
/// map.insert(1, Box::new(|| 22));
/// map.insert(2, Box::new(|| 44));
/// map
/// }
///
/// fn main() {
/// let mut map = make_map();
/// for i in &[1, 2] {
/// let f = map.remove(&i).unwrap();
/// assert_eq!(f(), i * 22);
/// }
/// }
/// ```
///
/// In Rust 1.35.0 or later, use `FnOnce`, `FnMut`, or `Fn` instead:
///
/// ```
/// use std::collections::HashMap;
///
/// fn make_map() -> HashMap<i32, Box<dyn FnOnce() -> i32>> {
/// let mut map: HashMap<i32, Box<dyn FnOnce() -> i32>> = HashMap::new();
/// map.insert(1, Box::new(|| 22));
/// map.insert(2, Box::new(|| 44));
/// map
/// }
///
/// fn main() {
/// let mut map = make_map();
/// for i in &[1, 2] {
/// let f = map.remove(&i).unwrap();
/// assert_eq!(f(), i * 22);
/// }
/// }
/// ```
#[rustc_paren_sugar]
#[unstable(feature = "fnbox", issue = "28796")]
#[rustc_deprecated(reason = "use `FnOnce`, `FnMut`, or `Fn` instead", since = "1.37.0")]
pub trait FnBox<A>: FnOnce<A> {
/// Performs the call operation.
fn call_box(self: Box<Self>, args: A) -> Self::Output;
}
#[unstable(feature = "fnbox", issue = "28796")]
#[rustc_deprecated(reason = "use `FnOnce`, `FnMut`, or `Fn` instead", since = "1.37.0")]
#[allow(deprecated, deprecated_in_future)]
impl<A, F> FnBox<A> for F
where F: FnOnce<A>
{
fn call_box(self: Box<F>, args: A) -> F::Output {
self.call_once(args)
}
}
#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}

View File

@ -25,6 +25,7 @@ use crate::task::{Context, Poll};
#[doc(spotlight)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[stable(feature = "futures_api", since = "1.36.0")]
#[cfg_attr(not(bootstrap), lang = "future_trait")]
pub trait Future {
/// The type of value produced on completion.
#[stable(feature = "futures_api", since = "1.36.0")]

View File

@ -138,10 +138,11 @@
//! To make this work, not just moving the data is restricted; deallocating, repurposing, or
//! otherwise invalidating the memory used to store the data is restricted, too.
//! Concretely, for pinned data you have to maintain the invariant
//! that *its memory will not get invalidated from the moment it gets pinned until
//! that *its memory will not get invalidated or repurposed from the moment it gets pinned until
//! when `drop` is called*. Memory can be invalidated by deallocation, but also by
//! replacing a [`Some(v)`] by [`None`], or calling [`Vec::set_len`] to "kill" some elements
//! off of a vector.
//! off of a vector. It can be repurposed by using [`ptr::write`] to overwrite it without
//! calling the destructor first.
//!
//! This is exactly the kind of guarantee that the intrusive linked list from the previous
//! section needs to function correctly.
@ -166,57 +167,130 @@
//! implementation as well: if an element of your type could have been pinned,
//! you must treat Drop as implicitly taking `Pin<&mut Self>`.
//!
//! In particular, if your type is `#[repr(packed)]`, the compiler will automatically
//! For example, you could implement `Drop` as follows:
//! ```rust,no_run
//! # use std::pin::Pin;
//! # struct Type { }
//! impl Drop for Type {
//! fn drop(&mut self) {
//! // `new_unchecked` is okay because we know this value is never used
//! // again after being dropped.
//! inner_drop(unsafe { Pin::new_unchecked(self)});
//! fn inner_drop(this: Pin<&mut Type>) {
//! // Actual drop code goes here.
//! }
//! }
//! }
//! ```
//! The function `inner_drop` has the type that `drop` *should* have, so this makes sure that
//! you do not accidentally use `self`/`this` in a way that is in conflict with pinning.
//!
//! Moreover, if your type is `#[repr(packed)]`, the compiler will automatically
//! move fields around to be able to drop them. As a consequence, you cannot use
//! pinning with a `#[repr(packed)]` type.
//!
//! # Projections and Structural Pinning
//!
//! One interesting question arises when considering the interaction of pinning
//! and the fields of a struct. When can a struct have a "pinning projection",
//! i.e., an operation with type `fn(Pin<&Struct>) -> Pin<&Field>`? In a
//! similar vein, when can a generic wrapper type (such as `Vec<T>`, `Box<T>`,
//! or `RefCell<T>`) have an operation with type `fn(Pin<&Wrapper<T>>) ->
//! Pin<&T>`?
//! When working with pinned structs, the question arises how one can access the
//! fields of that struct in a method that takes just `Pin<&mut Struct>`.
//! The usual approach is to write helper methods (so called *projections*)
//! that turn `Pin<&mut Struct>` into a reference to the field, but what
//! type should that reference have? Is it `Pin<&mut Field>` or `&mut Field`?
//! The same question arises with the fields of an `enum`, and also when considering
//! container/wrapper types such as [`Vec<T>`], [`Box<T>`], or [`RefCell<T>`].
//! (This question applies to both mutable and shared references, we just
//! use the more common case of mutable references here for illustration.)
//!
//! Note: For the entirety of this discussion, the same applies for mutable references as it
//! does for shared references.
//! It turns out that it is actually up to the author of the data structure
//! to decide whether the pinned projection for a particular field turns
//! `Pin<&mut Struct>` into `Pin<&mut Field>` or `&mut Field`. There are some
//! constraints though, and the most important constraint is *consistency*:
//! every field can be *either* projected to a pinned reference, *or* have
//! pinning removed as part of the projection. If both are done for the same field,
//! that will likely be unsound!
//!
//! Having a pinning projection for some field means that pinning is "structural":
//! when the wrapper is pinned, the field must be considered pinned, too.
//! After all, the pinning projection lets us get a `Pin<&Field>`.
//! As the author of a data structure you get to decide for each field whether pinning
//! "propagates" to this field or not. Pinning that propagates is also called "structural",
//! because it follows the structure of the type.
//! In the following subsections, we describe the considerations that have to be made
//! for either choice.
//!
//! However, structural pinning comes with a few extra requirements, so not all
//! wrappers can be structural and hence not all wrappers can offer pinning projections:
//! ## Pinning *is not* structural for `field`
//!
//! 1. The wrapper must only be [`Unpin`] if all the structural fields are
//! It may seem counter-intuitive that the field of a pinned struct might not be pinned,
//! but that is actually the easiest choice: if a `Pin<&mut Field>` is never created,
//! nothing can go wrong! So, if you decide that some field does not have structural pinning,
//! all you have to ensure is that you never create a pinned reference to that field.
//!
//! Fields without structural pinning may have a projection method that turns
//! `Pin<&mut Struct>` into `&mut Field`:
//! ```rust,no_run
//! # use std::pin::Pin;
//! # type Field = i32;
//! # struct Struct { field: Field }
//! impl Struct {
//! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> &'a mut Field {
//! // This is okay because `field` is never considered pinned.
//! unsafe { &mut self.get_unchecked_mut().field }
//! }
//! }
//! ```
//!
//! You may also `impl Unpin for Struct` *even if* the type of `field`
//! is not `Unpin`. What that type thinks about pinning is not relevant
//! when no `Pin<&mut Field>` is ever created.
//!
//! ## Pinning *is* structural for `field`
//!
//! The other option is to decide that pinning is "structural" for `field`,
//! meaning that if the struct is pinned then so is the field.
//!
//! This allows writing a projection that creates a `Pin<&mut Field>`, thus
//! witnessing that the field is pinned:
//! ```rust,no_run
//! # use std::pin::Pin;
//! # type Field = i32;
//! # struct Struct { field: Field }
//! impl Struct {
//! fn pin_get_field<'a>(self: Pin<&'a mut Self>) -> Pin<&'a mut Field> {
//! // This is okay because `field` is pinned when `self` is.
//! unsafe { self.map_unchecked_mut(|s| &mut s.field) }
//! }
//! }
//! ```
//!
//! However, structural pinning comes with a few extra requirements:
//!
//! 1. The struct must only be [`Unpin`] if all the structural fields are
//! `Unpin`. This is the default, but `Unpin` is a safe trait, so as the author of
//! the wrapper it is your responsibility *not* to add something like
//! `impl<T> Unpin for Wrapper<T>`. (Notice that adding a projection operation
//! the struct it is your responsibility *not* to add something like
//! `impl<T> Unpin for Struct<T>`. (Notice that adding a projection operation
//! requires unsafe code, so the fact that `Unpin` is a safe trait does not break
//! the principle that you only have to worry about any of this if you use `unsafe`.)
//! 2. The destructor of the wrapper must not move structural fields out of its argument. This
//! 2. The destructor of the struct must not move structural fields out of its argument. This
//! is the exact point that was raised in the [previous section][drop-impl]: `drop` takes
//! `&mut self`, but the wrapper (and hence its fields) might have been pinned before.
//! `&mut self`, but the struct (and hence its fields) might have been pinned before.
//! You have to guarantee that you do not move a field inside your `Drop` implementation.
//! In particular, as explained previously, this means that your wrapper type must *not*
//! In particular, as explained previously, this means that your struct must *not*
//! be `#[repr(packed)]`.
//! See that section for how to write `drop` in a way that the compiler can help you
//! not accidentally break pinning.
//! 3. You must make sure that you uphold the [`Drop` guarantee][drop-guarantee]:
//! once your wrapper is pinned, the memory that contains the
//! once your struct is pinned, the memory that contains the
//! content is not overwritten or deallocated without calling the content's destructors.
//! This can be tricky, as witnessed by `VecDeque<T>`: the destructor of `VecDeque<T>` can fail
//! to call `drop` on all elements if one of the destructors panics. This violates the
//! This can be tricky, as witnessed by [`VecDeque<T>`]: the destructor of `VecDeque<T>`
//! can fail to call `drop` on all elements if one of the destructors panics. This violates the
//! `Drop` guarantee, because it can lead to elements being deallocated without
//! their destructor being called. (`VecDeque` has no pinning projections, so this
//! does not cause unsoundness.)
//! 4. You must not offer any other operations that could lead to data being moved out of
//! the fields when your type is pinned. For example, if the wrapper contains an
//! the structural fields when your type is pinned. For example, if the struct contains an
//! `Option<T>` and there is a `take`-like operation with type
//! `fn(Pin<&mut Wrapper<T>>) -> Option<T>`,
//! that operation can be used to move a `T` out of a pinned `Wrapper<T>` -- which means
//! pinning cannot be structural.
//! `fn(Pin<&mut Struct<T>>) -> Option<T>`,
//! that operation can be used to move a `T` out of a pinned `Struct<T>` -- which means
//! pinning cannot be structural for the field holding this data.
//!
//! For a more complex example of moving data out of a pinned type, imagine if `RefCell<T>`
//! For a more complex example of moving data out of a pinned type, imagine if [`RefCell<T>`]
//! had a method `fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>`.
//! Then we could do the following:
//! ```compile_fail
@ -231,13 +305,16 @@
//! (using `RefCell::get_pin_mut`) and then move that content using the mutable
//! reference we got later.
//!
//! For a type like `Vec<T>`, both possibilites (structural pinning or not) make sense,
//! and the choice is up to the author. A `Vec<T>` with structural pinning could
//! have `get_pin`/`get_pin_mut` projections. However, it could *not* allow calling
//! ## Examples
//!
//! For a type like [`Vec<T>`], both possibilites (structural pinning or not) make sense.
//! A `Vec<T>` with structural pinning could have `get_pin`/`get_pin_mut` methods to get
//! pinned references to elements. However, it could *not* allow calling
//! `pop` on a pinned `Vec<T>` because that would move the (structurally pinned) contents!
//! Nor could it allow `push`, which might reallocate and thus also move the contents.
//! A `Vec<T>` without structural pinning could `impl<T> Unpin for Vec<T>`, because the contents
//! are never pinned and the `Vec<T>` itself is fine with being moved as well.
//! At that point pinning just has no effect on the vector at all.
//!
//! In the standard library, pointer types generally do not have structural pinning,
//! and thus they do not offer pinning projections. This is why `Box<T>: Unpin` holds for all `T`.
@ -249,16 +326,28 @@
//! whether the content is pinned is entirely independent of whether the pointer is
//! pinned, meaning pinning is *not* structural.
//!
//! When implementing a [`Future`] combinator, you will usually need structural pinning
//! for the nested futures, as you need to get pinned references to them to call `poll`.
//! But if your combinator contains any other data that does not need to be pinned,
//! you can make those fields not structural and hence freely access them with a
//! mutable reference even when you just have `Pin<&mut Self>` (such as in your own
//! `poll` implementation).
//!
//! [`Pin<P>`]: struct.Pin.html
//! [`Unpin`]: ../../std/marker/trait.Unpin.html
//! [`Deref`]: ../../std/ops/trait.Deref.html
//! [`DerefMut`]: ../../std/ops/trait.DerefMut.html
//! [`mem::swap`]: ../../std/mem/fn.swap.html
//! [`mem::forget`]: ../../std/mem/fn.forget.html
//! [`Unpin`]: ../marker/trait.Unpin.html
//! [`Deref`]: ../ops/trait.Deref.html
//! [`DerefMut`]: ../ops/trait.DerefMut.html
//! [`mem::swap`]: ../mem/fn.swap.html
//! [`mem::forget`]: ../mem/fn.forget.html
//! [`Box<T>`]: ../../std/boxed/struct.Box.html
//! [`Vec<T>`]: ../../std/vec/struct.Vec.html
//! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len
//! [`None`]: ../../std/option/enum.Option.html#variant.None
//! [`Some(v)`]: ../../std/option/enum.Option.html#variant.Some
//! [`VecDeque<T>`]: ../../std/collections/struct.VecDeque.html
//! [`RefCell<T>`]: ../cell/struct.RefCell.html
//! [`None`]: ../option/enum.Option.html#variant.None
//! [`Some(v)`]: ../option/enum.Option.html#variant.Some
//! [`ptr::write`]: ../ptr/fn.write.html
//! [`Future`]: ../future/trait.Future.html
//! [drop-impl]: #drop-implementation
//! [drop-guarantee]: #drop-guarantee

View File

@ -5795,7 +5795,6 @@ impl<'a> LoweringContext<'a> {
err.span_label(item_sp, "this is not `async`");
}
err.emit();
return hir::ExprKind::Err;
}
}
let span = self.mark_span_with_reason(

View File

@ -1713,7 +1713,7 @@ pub enum GeneratorMovability {
}
/// The yield kind that caused an `ExprKind::Yield`.
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable, HashStable)]
pub enum YieldSource {
/// An `<expr>.await`.
Await,

View File

@ -348,12 +348,6 @@ declare_lint! {
/// Some lints that are buffered from `libsyntax`. See `syntax::early_buffered_lints`.
pub mod parser {
declare_lint! {
pub QUESTION_MARK_MACRO_SEP,
Allow,
"detects the use of `?` as a macro separator"
}
declare_lint! {
pub ILL_FORMED_ATTRIBUTE_INPUT,
Warn,
@ -444,7 +438,6 @@ declare_lint_pass! {
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
MACRO_USE_EXTERN_CRATE,
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
parser::QUESTION_MARK_MACRO_SEP,
parser::ILL_FORMED_ATTRIBUTE_INPUT,
DEPRECATED_IN_FUTURE,
AMBIGUOUS_ASSOCIATED_ITEMS,

View File

@ -27,7 +27,7 @@ use crate::hir::def_id::{CrateNum, LOCAL_CRATE};
use crate::hir::intravisit;
use crate::hir;
use crate::lint::builtin::BuiltinLintDiagnostics;
use crate::lint::builtin::parser::{QUESTION_MARK_MACRO_SEP, ILL_FORMED_ATTRIBUTE_INPUT};
use crate::lint::builtin::parser::ILL_FORMED_ATTRIBUTE_INPUT;
use crate::session::{Session, DiagnosticMessageId};
use crate::ty::TyCtxt;
use crate::ty::query::Providers;
@ -80,7 +80,6 @@ impl Lint {
/// Returns the `rust::lint::Lint` for a `syntax::early_buffered_lints::BufferedEarlyLintId`.
pub fn from_parser_lint_id(lint_id: BufferedEarlyLintId) -> &'static Self {
match lint_id {
BufferedEarlyLintId::QuestionMarkMacroSep => QUESTION_MARK_MACRO_SEP,
BufferedEarlyLintId::IllFormedAttributeInput => ILL_FORMED_ATTRIBUTE_INPUT,
}
}

View File

@ -320,6 +320,7 @@ language_item_table! {
FnMutTraitLangItem, "fn_mut", fn_mut_trait, Target::Trait;
FnOnceTraitLangItem, "fn_once", fn_once_trait, Target::Trait;
FutureTraitLangItem, "future_trait", future_trait, Target::Trait;
GeneratorStateLangItem, "generator_state", gen_state, Target::Enum;
GeneratorTraitLangItem, "generator", gen_trait, Target::Trait;
UnpinTraitLangItem, "unpin", unpin_trait, Target::Trait;

View File

@ -29,7 +29,7 @@ use std::fmt;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};
use std::process::{Output, Stdio};
use std::process::{Output, Stdio, ExitStatus};
use std::str;
use std::env;
@ -510,21 +510,6 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
sess.abort_if_errors();
// Invoke the system linker
//
// Note that there's a terribly awful hack that really shouldn't be present
// in any compiler. Here an environment variable is supported to
// automatically retry the linker invocation if the linker looks like it
// segfaulted.
//
// Gee that seems odd, normally segfaults are things we want to know about!
// Unfortunately though in rust-lang/rust#38878 we're experiencing the
// linker segfaulting on Travis quite a bit which is causing quite a bit of
// pain to land PRs when they spuriously fail due to a segfault.
//
// The issue #38878 has some more debugging information on it as well, but
// this unfortunately looks like it's just a race condition in macOS's linker
// with some thread pool working in the background. It seems that no one
// currently knows a fix for this so in the meantime we're left with this...
info!("{:?}", &cmd);
let retry_on_segfault = env::var("RUSTC_RETRY_LINKER_ON_SEGFAULT").is_ok();
let mut prog;
@ -567,21 +552,59 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
info!("{:?}", &cmd);
continue;
}
// Here's a terribly awful hack that really shouldn't be present in any
// compiler. Here an environment variable is supported to automatically
// retry the linker invocation if the linker looks like it segfaulted.
//
// Gee that seems odd, normally segfaults are things we want to know
// about! Unfortunately though in rust-lang/rust#38878 we're
// experiencing the linker segfaulting on Travis quite a bit which is
// causing quite a bit of pain to land PRs when they spuriously fail
// due to a segfault.
//
// The issue #38878 has some more debugging information on it as well,
// but this unfortunately looks like it's just a race condition in
// macOS's linker with some thread pool working in the background. It
// seems that no one currently knows a fix for this so in the meantime
// we're left with this...
if !retry_on_segfault || i > 3 {
break
}
let msg_segv = "clang: error: unable to execute command: Segmentation fault: 11";
let msg_bus = "clang: error: unable to execute command: Bus error: 10";
if !(out.contains(msg_segv) || out.contains(msg_bus)) {
break
if out.contains(msg_segv) || out.contains(msg_bus) {
warn!(
"looks like the linker segfaulted when we tried to call it, \
automatically retrying again. cmd = {:?}, out = {}.",
cmd,
out,
);
continue;
}
warn!(
"looks like the linker segfaulted when we tried to call it, \
automatically retrying again. cmd = {:?}, out = {}.",
cmd,
out,
);
if is_illegal_instruction(&output.status) {
warn!(
"looks like the linker hit an illegal instruction when we \
tried to call it, automatically retrying again. cmd = {:?}, ]\
out = {}, status = {}.",
cmd,
out,
output.status,
);
continue;
}
#[cfg(unix)]
fn is_illegal_instruction(status: &ExitStatus) -> bool {
use std::os::unix::prelude::*;
status.signal() == Some(libc::SIGILL)
}
#[cfg(windows)]
fn is_illegal_instruction(_status: &ExitStatus) -> bool {
false
}
}
match prog {

View File

@ -39,8 +39,8 @@ impl Fingerprint {
// you want.
#[inline]
pub fn combine_commutative(self, other: Fingerprint) -> Fingerprint {
let a = (self.1 as u128) << 64 | self.0 as u128;
let b = (other.1 as u128) << 64 | other.0 as u128;
let a = u128::from(self.1) << 64 | u128::from(self.0);
let b = u128::from(other.1) << 64 | u128::from(other.0);
let c = a.wrapping_add(b);

View File

@ -263,7 +263,7 @@ impl<O: ForestObligation> ObligationForest<O> {
done_cache: Default::default(),
waiting_cache: Default::default(),
scratch: Some(vec![]),
obligation_tree_id_generator: (0..).map(|i| ObligationTreeId(i)),
obligation_tree_id_generator: (0..).map(ObligationTreeId),
error_cache: Default::default(),
}
}

View File

@ -70,15 +70,15 @@ unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
let mut i = 0; // current byte index (from LSB) in the output u64
let mut out = 0;
if i + 3 < len {
out = load_int_le!(buf, start + i, u32) as u64;
out = u64::from(load_int_le!(buf, start + i, u32));
i += 4;
}
if i + 1 < len {
out |= (load_int_le!(buf, start + i, u16) as u64) << (i * 8);
out |= u64::from(load_int_le!(buf, start + i, u16)) << (i * 8);
i += 2
}
if i < len {
out |= (*buf.get_unchecked(start + i) as u64) << (i * 8);
out |= u64::from(*buf.get_unchecked(start + i)) << (i * 8);
i += 1;
}
debug_assert_eq!(i, len);
@ -237,7 +237,7 @@ impl Hasher for SipHasher128 {
if self.ntail != 0 {
needed = 8 - self.ntail;
self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << 8 * self.ntail;
self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << (8 * self.ntail);
if length < needed {
self.ntail += length;
return

View File

@ -44,7 +44,7 @@ impl<W: StableHasherResult> StableHasher<W> {
impl StableHasherResult for u128 {
fn finish(hasher: StableHasher<Self>) -> Self {
let (_0, _1) = hasher.finalize();
(_0 as u128) | ((_1 as u128) << 64)
u128::from(_0) | (u128::from(_1) << 64)
}
}

View File

@ -8,7 +8,7 @@ where
Ls: Links,
{
VecLinkedListIterator {
links: links,
links,
current: first,
}
}

View File

@ -94,7 +94,7 @@ impl<'a> DiagnosticConverter<'a> {
annotation_type: Self::annotation_type_for_level(self.level),
}),
footer: vec![],
slices: slices,
slices,
})
} else {
// FIXME(#59346): Is it ok to return None if there's no source_map?

View File

@ -388,7 +388,7 @@ impl Diagnostic {
}],
msg: msg.to_owned(),
style: SuggestionStyle::CompletelyHidden,
applicability: applicability,
applicability,
});
self
}

View File

@ -1339,7 +1339,7 @@ impl EmitterWriter {
}
let mut dst = self.dst.writable();
match write!(dst, "\n") {
match writeln!(dst) {
Err(e) => panic!("failed to emit error: {}", e),
_ => {
match dst.flush() {
@ -1598,7 +1598,7 @@ fn emit_to_destination(rendered_buffer: &[Vec<StyledString>],
dst.reset()?;
}
if !short_message && (!lvl.is_failure_note() || pos != rendered_buffer.len() - 1) {
write!(dst, "\n")?;
writeln!(dst)?;
}
}
dst.flush()?;

View File

@ -42,7 +42,6 @@ use rustc::lint::builtin::{
INTRA_DOC_LINK_RESOLUTION_FAILURE,
MISSING_DOC_CODE_EXAMPLES,
PRIVATE_DOC_TESTS,
parser::QUESTION_MARK_MACRO_SEP,
parser::ILL_FORMED_ATTRIBUTE_INPUT,
};
use rustc::session;
@ -404,11 +403,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
reference: "issue #50504 <https://github.com/rust-lang/rust/issues/50504>",
edition: None,
},
FutureIncompatibleInfo {
id: LintId::of(QUESTION_MARK_MACRO_SEP),
reference: "issue #48075 <https://github.com/rust-lang/rust/issues/48075>",
edition: Some(Edition::Edition2018),
},
FutureIncompatibleInfo {
id: LintId::of(MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS),
reference: "issue #52234 <https://github.com/rust-lang/rust/issues/52234>",

View File

@ -29,6 +29,7 @@ use std::cell::Cell;
use std::default::Default;
use std::env;
use std::fs::File;
use std::io::BufWriter;
use std::path::{Path, PathBuf};
use syntax::ast::{self, Attribute, DUMMY_NODE_ID, NodeId, PatKind};
@ -1025,7 +1026,7 @@ impl<'a> DumpHandler<'a> {
}
}
fn output_file(&self, ctx: &SaveContext<'_, '_>) -> (File, PathBuf) {
fn output_file(&self, ctx: &SaveContext<'_, '_>) -> (BufWriter<File>, PathBuf) {
let sess = &ctx.tcx.sess;
let file_name = match ctx.config.output_file {
Some(ref s) => PathBuf::from(s),
@ -1059,9 +1060,9 @@ impl<'a> DumpHandler<'a> {
info!("Writing output to {}", file_name.display());
let output_file = File::create(&file_name).unwrap_or_else(
let output_file = BufWriter::new(File::create(&file_name).unwrap_or_else(
|e| sess.fatal(&format!("Could not open {}: {}", file_name.display(), e)),
);
));
(output_file, file_name)
}

View File

@ -19,7 +19,7 @@ pub fn opts() -> TargetOptions {
is_like_fuchsia: true,
linker_is_gnu: true,
has_rpath: false,
pre_link_args: pre_link_args,
pre_link_args,
pre_link_objects_exe: vec![
"Scrt1.o".to_string()
],

View File

@ -127,6 +127,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.suggest_compatible_variants(&mut err, expr, expected, expr_ty);
self.suggest_ref_or_into(&mut err, expr, expected, expr_ty);
self.suggest_missing_await(&mut err, expr, expected, expr_ty);
(expected, Some(err))
}

View File

@ -295,8 +295,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ExprKind::Index(ref base, ref idx) => {
self.check_expr_index(base, idx, needs, expr)
}
ExprKind::Yield(ref value, _) => {
self.check_expr_yield(value, expr)
ExprKind::Yield(ref value, ref src) => {
self.check_expr_yield(value, expr, src)
}
hir::ExprKind::Err => {
tcx.types.err
@ -1541,12 +1541,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
fn check_expr_yield(&self, value: &'tcx hir::Expr, expr: &'tcx hir::Expr) -> Ty<'tcx> {
fn check_expr_yield(
&self,
value: &'tcx hir::Expr,
expr: &'tcx hir::Expr,
src: &'tcx hir::YieldSource
) -> Ty<'tcx> {
match self.yield_ty {
Some(ty) => {
self.check_expr_coercable_to_type(&value, ty);
}
None => {
// Given that this `yield` expression was generated as a result of lowering a `.await`,
// we know that the yield type must be `()`; however, the context won't contain this
// information. Hence, we check the source of the yield expression here and check its
// value's type against `()` (this check should always hold).
None if src == &hir::YieldSource::Await => {
self.check_expr_coercable_to_type(&value, self.tcx.mk_unit());
}
_ => {
struct_span_err!(self.tcx.sess, expr.span, E0627,
"yield statement outside of generator literal").emit();
}

View File

@ -3932,6 +3932,72 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
/// A possible error is to forget to add `.await` when using futures:
///
/// ```
/// #![feature(async_await)]
///
/// async fn make_u32() -> u32 {
/// 22
/// }
///
/// fn take_u32(x: u32) {}
///
/// async fn foo() {
/// let x = make_u32();
/// take_u32(x);
/// }
/// ```
///
/// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
/// expected type. If this is the case, and we are inside of an async body, it suggests adding
/// `.await` to the tail of the expression.
fn suggest_missing_await(
&self,
err: &mut DiagnosticBuilder<'tcx>,
expr: &hir::Expr,
expected: Ty<'tcx>,
found: Ty<'tcx>,
) {
// `.await` is not permitted outside of `async` bodies, so don't bother to suggest if the
// body isn't `async`.
let item_id = self.tcx().hir().get_parent_node(self.body_id);
if let Some(body_id) = self.tcx().hir().maybe_body_owned_by(item_id) {
let body = self.tcx().hir().body(body_id);
if let Some(hir::GeneratorKind::Async) = body.generator_kind {
let sp = expr.span;
// Check for `Future` implementations by constructing a predicate to
// prove: `<T as Future>::Output == U`
let future_trait = self.tcx.lang_items().future_trait().unwrap();
let item_def_id = self.tcx.associated_items(future_trait).next().unwrap().def_id;
let predicate = ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate {
// `<T as Future>::Output`
projection_ty: ty::ProjectionTy {
// `T`
substs: self.tcx.mk_substs_trait(
found,
self.fresh_substs_for_item(sp, item_def_id)
),
// `Future::Output`
item_def_id,
},
ty: expected,
}));
let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
if self.infcx.predicate_may_hold(&obligation) {
if let Ok(code) = self.sess().source_map().span_to_snippet(sp) {
err.span_suggestion(
sp,
"consider using `.await` here",
format!("{}.await", code),
Applicability::MaybeIncorrect,
);
}
}
}
}
}
/// A common error is to add an extra semicolon:
///
/// ```

View File

@ -461,7 +461,7 @@ impl<'a> Encoder<'a> {
/// Creates a new JSON encoder whose output will be written to the writer
/// specified.
pub fn new(writer: &'a mut dyn fmt::Write) -> Encoder<'a> {
Encoder { writer: writer, is_emitting_map_key: false, }
Encoder { writer, is_emitting_map_key: false, }
}
}
@ -513,7 +513,7 @@ impl<'a> crate::Encoder for Encoder<'a> {
emit_enquoted_if_mapkey!(self, fmt_number_or_null(v))
}
fn emit_f32(&mut self, v: f32) -> EncodeResult {
self.emit_f64(v as f64)
self.emit_f64(f64::from(v))
}
fn emit_char(&mut self, v: char) -> EncodeResult {
@ -763,7 +763,7 @@ impl<'a> crate::Encoder for PrettyEncoder<'a> {
emit_enquoted_if_mapkey!(self, fmt_number_or_null(v))
}
fn emit_f32(&mut self, v: f32) -> EncodeResult {
self.emit_f64(v as f64)
self.emit_f64(f64::from(v))
}
fn emit_char(&mut self, v: char) -> EncodeResult {
@ -1698,12 +1698,12 @@ impl<T: Iterator<Item=char>> Parser<T> {
if n2 < 0xDC00 || n2 > 0xDFFF {
return self.error(LoneLeadingSurrogateInHexEscape)
}
let c = (((n1 - 0xD800) as u32) << 10 |
(n2 - 0xDC00) as u32) + 0x1_0000;
let c = (u32::from(n1 - 0xD800) << 10 |
u32::from(n2 - 0xDC00)) + 0x1_0000;
res.push(char::from_u32(c).unwrap());
}
n => match char::from_u32(n as u32) {
n => match char::from_u32(u32::from(n)) {
Some(c) => res.push(c),
None => return self.error(InvalidUnicodeCodePoint),
},
@ -2405,7 +2405,7 @@ impl ToJson for Json {
}
impl ToJson for f32 {
fn to_json(&self) -> Json { (*self as f64).to_json() }
fn to_json(&self) -> Json { f64::from(*self).to_json() }
}
impl ToJson for f64 {

View File

@ -123,7 +123,7 @@ pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i128, usize) {
loop {
byte = data[position];
position += 1;
result |= ((byte & 0x7F) as i128) << shift;
result |= i128::from(byte & 0x7F) << shift;
shift += 7;
if (byte & 0x80) == 0 {

View File

@ -296,13 +296,13 @@ impl<'a> serialize::Decoder for Decoder<'a> {
#[inline]
fn read_f64(&mut self) -> Result<f64, Self::Error> {
let bits = self.read_u64()?;
Ok(unsafe { ::std::mem::transmute(bits) })
Ok(f64::from_bits(bits))
}
#[inline]
fn read_f32(&mut self) -> Result<f32, Self::Error> {
let bits = self.read_u32()?;
Ok(unsafe { ::std::mem::transmute(bits) })
Ok(f32::from_bits(bits))
}
#[inline]

View File

@ -506,9 +506,18 @@ pub trait Read {
///
/// No guarantees are provided about the contents of `buf` when this
/// function is called, implementations cannot rely on any property of the
/// contents of `buf` being true. It is recommended that implementations
/// contents of `buf` being true. It is recommended that *implementations*
/// only write data to `buf` instead of reading its contents.
///
/// Correspondingly, however, *callers* of this method may not assume any guarantees
/// about how the implementation uses `buf`. The trait is safe to implement,
// so it is possible that the code that's supposed to write to the buffer might also read
// from it. It is your responsibility to make sure that `buf` is initialized
/// before calling `read`. Calling `read` with an uninitialized `buf` (of the kind one
/// obtains via [`MaybeUninit<T>`]) is not safe, and can lead to undefined behavior.
///
/// [`MaybeUninit<T>`]: ../mem/union.MaybeUninit.html
///
/// # Errors
///
/// If this function encounters any form of I/O or other error, an error

View File

@ -262,7 +262,6 @@
#![feature(exhaustive_patterns)]
#![feature(external_doc)]
#![feature(fn_traits)]
#![feature(fnbox)]
#![feature(generator_trait)]
#![feature(hash_raw_entry)]
#![feature(hashmap_internals)]

View File

@ -1832,7 +1832,7 @@ impl Arg {
lt,
MutTy {
ty: infer_ty,
mutbl: mutbl,
mutbl,
},
),
span,
@ -2120,7 +2120,7 @@ impl PolyTraitRef {
PolyTraitRef {
bound_generic_params: generic_params,
trait_ref: TraitRef {
path: path,
path,
ref_id: DUMMY_NODE_ID,
},
span,

View File

@ -9,8 +9,6 @@ use syntax_pos::MultiSpan;
/// Since we cannot import `LintId`s from `rustc::lint`, we define some Ids here which can later be
/// passed to `rustc::lint::Lint::from_parser_lint_id` to get a `rustc::lint::Lint`.
pub enum BufferedEarlyLintId {
/// Usage of `?` as a macro separator is deprecated.
QuestionMarkMacroSep,
IllFormedAttributeInput,
}

View File

@ -815,7 +815,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
fn pat(&self, span: Span, pat: PatKind) -> P<ast::Pat> {
P(ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, span: span })
P(ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, span })
}
fn pat_wild(&self, span: Span) -> P<ast::Pat> {
self.pat(span, PatKind::Wild)

View File

@ -231,7 +231,7 @@ pub struct MacroExpander<'a, 'b> {
impl<'a, 'b> MacroExpander<'a, 'b> {
pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
MacroExpander { cx: cx, monotonic: monotonic }
MacroExpander { cx, monotonic }
}
pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
@ -377,7 +377,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
_ => item.clone(),
};
invocations.push(Invocation {
kind: InvocationKind::Derive { path: path.clone(), item: item },
kind: InvocationKind::Derive { path: path.clone(), item },
fragment_kind: invoc.fragment_kind,
expansion_data: ExpansionData {
mark,
@ -944,7 +944,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
}
fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
self.collect(kind, InvocationKind::Bang { mac, ident: None, span })
}
fn collect_attr(&mut self,

View File

@ -319,7 +319,7 @@ fn parse_tree(
tokenstream::TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited(
span,
Lrc::new(Delimited {
delim: delim,
delim,
tts: parse(
tts.into(),
expect_matchers,

View File

@ -23,8 +23,8 @@ enum Frame {
impl Frame {
/// Construct a new frame around the delimited set of tokens.
fn new(tts: Vec<quoted::TokenTree>) -> Frame {
let forest = Lrc::new(quoted::Delimited { delim: token::NoDelim, tts: tts });
Frame::Delimited { forest: forest, idx: 0, span: DelimSpan::dummy() }
let forest = Lrc::new(quoted::Delimited { delim: token::NoDelim, tts });
Frame::Delimited { forest, idx: 0, span: DelimSpan::dummy() }
}
}
@ -248,7 +248,7 @@ pub fn transcribe(
// the previous results (from outside the Delimited).
quoted::TokenTree::Delimited(mut span, delimited) => {
span = span.apply_mark(cx.current_expansion.mark);
stack.push(Frame::Delimited { forest: delimited, idx: 0, span: span });
stack.push(Frame::Delimited { forest: delimited, idx: 0, span });
result_stack.push(mem::replace(&mut result, Vec::new()));
}

View File

@ -1665,7 +1665,7 @@ impl<'a> Context<'a> {
}
pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) {
let cx = Context { features: features, parse_sess: parse_sess, plugin_attributes: &[] };
let cx = Context { features, parse_sess, plugin_attributes: &[] };
cx.check_attribute(
attr,
attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name).map(|a| *a)),

View File

@ -942,7 +942,7 @@ impl<'a> Parser<'a> {
// {foo(bar {}}
// - ^
// | |
// | help: `)` may belong here (FIXME: #58270)
// | help: `)` may belong here
// |
// unclosed delimiter
if let Some(sp) = unmatched.unclosed_span {

View File

@ -1,4 +1,3 @@
use crate::ast;
use crate::parse::ParseSess;
use crate::parse::token::{self, Token, TokenKind};
use crate::symbol::{sym, Symbol};
@ -321,33 +320,29 @@ impl<'a> StringReader<'a> {
(pos - self.source_file.start_pos).to_usize()
}
/// Calls `f` with a string slice of the source text spanning from `start`
/// up to but excluding `self.pos`, meaning the slice does not include
/// the character `self.ch`.
fn with_str_from<T, F>(&self, start: BytePos, f: F) -> T
where F: FnOnce(&str) -> T
/// Slice of the source text from `start` up to but excluding `self.pos`,
/// meaning the slice does not include the character `self.ch`.
fn str_from(&self, start: BytePos) -> &str
{
self.with_str_from_to(start, self.pos, f)
self.str_from_to(start, self.pos)
}
/// Creates a Name from a given offset to the current offset.
fn name_from(&self, start: BytePos) -> ast::Name {
/// Creates a Symbol from a given offset to the current offset.
fn symbol_from(&self, start: BytePos) -> Symbol {
debug!("taking an ident from {:?} to {:?}", start, self.pos);
self.with_str_from(start, Symbol::intern)
Symbol::intern(self.str_from(start))
}
/// As name_from, with an explicit endpoint.
fn name_from_to(&self, start: BytePos, end: BytePos) -> ast::Name {
/// As symbol_from, with an explicit endpoint.
fn symbol_from_to(&self, start: BytePos, end: BytePos) -> Symbol {
debug!("taking an ident from {:?} to {:?}", start, end);
self.with_str_from_to(start, end, Symbol::intern)
Symbol::intern(self.str_from_to(start, end))
}
/// Calls `f` with a string slice of the source text spanning from `start`
/// up to but excluding `end`.
fn with_str_from_to<T, F>(&self, start: BytePos, end: BytePos, f: F) -> T
where F: FnOnce(&str) -> T
/// Slice of the source text spanning from `start` up to but excluding `end`.
fn str_from_to(&self, start: BytePos, end: BytePos) -> &str
{
f(&self.src[self.src_index(start)..self.src_index(end)])
&self.src[self.src_index(start)..self.src_index(end)]
}
/// Converts CRLF to LF in the given string, raising an error on bare CR.
@ -444,7 +439,7 @@ impl<'a> StringReader<'a> {
}
/// Eats <XID_start><XID_continue>*, if possible.
fn scan_optional_raw_name(&mut self) -> Option<ast::Name> {
fn scan_optional_raw_name(&mut self) -> Option<Symbol> {
if !ident_start(self.ch) {
return None;
}
@ -456,8 +451,8 @@ impl<'a> StringReader<'a> {
self.bump();
}
self.with_str_from(start, |string| {
if string == "_" {
match self.str_from(start) {
"_" => {
self.sess.span_diagnostic
.struct_span_warn(self.mk_sp(start, self.pos),
"underscore literal suffix is not allowed")
@ -468,10 +463,9 @@ impl<'a> StringReader<'a> {
<https://github.com/rust-lang/rust/issues/42326>")
.emit();
None
} else {
Some(Symbol::intern(string))
}
})
name => Some(Symbol::intern(name))
}
}
/// PRECONDITION: self.ch is not whitespace
@ -513,9 +507,7 @@ impl<'a> StringReader<'a> {
}
let kind = if doc_comment {
self.with_str_from(start_bpos, |string| {
token::DocComment(Symbol::intern(string))
})
token::DocComment(self.symbol_from(start_bpos))
} else {
token::Comment
};
@ -544,7 +536,7 @@ impl<'a> StringReader<'a> {
self.bump();
}
return Some(Token::new(
token::Shebang(self.name_from(start)),
token::Shebang(self.symbol_from(start)),
self.mk_sp(start, self.pos),
));
}
@ -615,23 +607,22 @@ impl<'a> StringReader<'a> {
self.bump();
}
self.with_str_from(start_bpos, |string| {
// but comments with only "*"s between two "/"s are not
let kind = if is_block_doc_comment(string) {
let string = if has_cr {
self.translate_crlf(start_bpos,
string,
"bare CR not allowed in block doc-comment")
} else {
string.into()
};
token::DocComment(Symbol::intern(&string[..]))
let string = self.str_from(start_bpos);
// but comments with only "*"s between two "/"s are not
let kind = if is_block_doc_comment(string) {
let string = if has_cr {
self.translate_crlf(start_bpos,
string,
"bare CR not allowed in block doc-comment")
} else {
token::Comment
string.into()
};
token::DocComment(Symbol::intern(&string[..]))
} else {
token::Comment
};
Some(Token::new(kind, self.mk_sp(start_bpos, self.pos)))
})
Some(Token::new(kind, self.mk_sp(start_bpos, self.pos)))
}
/// Scan through any digits (base `scan_radix`) or underscores,
@ -727,17 +718,17 @@ impl<'a> StringReader<'a> {
let pos = self.pos;
self.check_float_base(start_bpos, pos, base);
(token::Float, self.name_from(start_bpos))
(token::Float, self.symbol_from(start_bpos))
} else {
// it might be a float if it has an exponent
if self.ch_is('e') || self.ch_is('E') {
self.scan_float_exponent();
let pos = self.pos;
self.check_float_base(start_bpos, pos, base);
return (token::Float, self.name_from(start_bpos));
return (token::Float, self.symbol_from(start_bpos));
}
// but we certainly have an integer!
(token::Integer, self.name_from(start_bpos))
(token::Integer, self.symbol_from(start_bpos))
}
}
@ -838,20 +829,17 @@ impl<'a> StringReader<'a> {
self.bump();
}
return Ok(self.with_str_from(start, |string| {
// FIXME: perform NFKC normalization here. (Issue #2253)
let name = ast::Name::intern(string);
if is_raw_ident {
let span = self.mk_sp(raw_start, self.pos);
if !name.can_be_raw() {
self.err_span(span, &format!("`{}` cannot be a raw identifier", name));
}
self.sess.raw_identifier_spans.borrow_mut().push(span);
// FIXME: perform NFKC normalization here. (Issue #2253)
let name = self.symbol_from(start);
if is_raw_ident {
let span = self.mk_sp(raw_start, self.pos);
if !name.can_be_raw() {
self.err_span(span, &format!("`{}` cannot be a raw identifier", name));
}
self.sess.raw_identifier_spans.borrow_mut().push(span);
}
token::Ident(name, is_raw_ident)
}));
return Ok(token::Ident(name, is_raw_ident));
}
}
@ -1017,7 +1005,7 @@ impl<'a> StringReader<'a> {
// lifetimes shouldn't end with a single quote
// if we find one, then this is an invalid character literal
if self.ch_is('\'') {
let symbol = self.name_from(start);
let symbol = self.symbol_from(start);
self.bump();
self.validate_char_escape(start_with_quote);
return Ok(TokenKind::lit(token::Char, symbol, None));
@ -1035,7 +1023,7 @@ impl<'a> StringReader<'a> {
// Include the leading `'` in the real identifier, for macro
// expansion purposes. See #12512 for the gory details of why
// this is necessary.
return Ok(token::Lifetime(self.name_from(start_with_quote)));
return Ok(token::Lifetime(self.symbol_from(start_with_quote)));
}
let msg = "unterminated character literal";
let symbol = self.scan_single_quoted_string(start_with_quote, msg);
@ -1063,7 +1051,7 @@ impl<'a> StringReader<'a> {
},
Some('r') => {
let (start, end, hash_count) = self.scan_raw_string();
let symbol = self.name_from_to(start, end);
let symbol = self.symbol_from_to(start, end);
self.validate_raw_byte_str_escape(start, end);
(token::ByteStrRaw(hash_count), symbol)
@ -1084,7 +1072,7 @@ impl<'a> StringReader<'a> {
}
'r' => {
let (start, end, hash_count) = self.scan_raw_string();
let symbol = self.name_from_to(start, end);
let symbol = self.symbol_from_to(start, end);
self.validate_raw_str_escape(start, end);
let suffix = self.scan_optional_raw_name();
@ -1185,7 +1173,7 @@ impl<'a> StringReader<'a> {
fn scan_single_quoted_string(&mut self,
start_with_quote: BytePos,
unterminated_msg: &str) -> ast::Name {
unterminated_msg: &str) -> Symbol {
// assumes that first `'` is consumed
let start = self.pos;
// lex `'''` as a single char, for recovery
@ -1217,12 +1205,12 @@ impl<'a> StringReader<'a> {
}
}
let id = self.name_from(start);
let id = self.symbol_from(start);
self.bump();
id
}
fn scan_double_quoted_string(&mut self, unterminated_msg: &str) -> ast::Name {
fn scan_double_quoted_string(&mut self, unterminated_msg: &str) -> Symbol {
debug_assert!(self.ch_is('\"'));
let start_with_quote = self.pos;
self.bump();
@ -1237,7 +1225,7 @@ impl<'a> StringReader<'a> {
}
self.bump();
}
let id = self.name_from(start);
let id = self.symbol_from(start);
self.bump();
id
}
@ -1300,101 +1288,95 @@ impl<'a> StringReader<'a> {
}
fn validate_char_escape(&self, start_with_quote: BytePos) {
self.with_str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1), |lit| {
if let Err((off, err)) = unescape::unescape_char(lit) {
emit_unescape_error(
&self.sess.span_diagnostic,
lit,
self.mk_sp(start_with_quote, self.pos),
unescape::Mode::Char,
0..off,
err,
)
}
});
let lit = self.str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1));
if let Err((off, err)) = unescape::unescape_char(lit) {
emit_unescape_error(
&self.sess.span_diagnostic,
lit,
self.mk_sp(start_with_quote, self.pos),
unescape::Mode::Char,
0..off,
err,
)
}
}
fn validate_byte_escape(&self, start_with_quote: BytePos) {
self.with_str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1), |lit| {
if let Err((off, err)) = unescape::unescape_byte(lit) {
let lit = self.str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1));
if let Err((off, err)) = unescape::unescape_byte(lit) {
emit_unescape_error(
&self.sess.span_diagnostic,
lit,
self.mk_sp(start_with_quote, self.pos),
unescape::Mode::Byte,
0..off,
err,
)
}
}
fn validate_str_escape(&self, start_with_quote: BytePos) {
let lit = self.str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1));
unescape::unescape_str(lit, &mut |range, c| {
if let Err(err) = c {
emit_unescape_error(
&self.sess.span_diagnostic,
lit,
self.mk_sp(start_with_quote, self.pos),
unescape::Mode::Byte,
0..off,
unescape::Mode::Str,
range,
err,
)
}
});
}
fn validate_str_escape(&self, start_with_quote: BytePos) {
self.with_str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1), |lit| {
unescape::unescape_str(lit, &mut |range, c| {
if let Err(err) = c {
emit_unescape_error(
&self.sess.span_diagnostic,
lit,
self.mk_sp(start_with_quote, self.pos),
unescape::Mode::Str,
range,
err,
)
}
})
});
})
}
fn validate_raw_str_escape(&self, content_start: BytePos, content_end: BytePos) {
self.with_str_from_to(content_start, content_end, |lit: &str| {
unescape::unescape_raw_str(lit, &mut |range, c| {
if let Err(err) = c {
emit_unescape_error(
&self.sess.span_diagnostic,
lit,
self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)),
unescape::Mode::Str,
range,
err,
)
}
})
});
let lit = self.str_from_to(content_start, content_end);
unescape::unescape_raw_str(lit, &mut |range, c| {
if let Err(err) = c {
emit_unescape_error(
&self.sess.span_diagnostic,
lit,
self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)),
unescape::Mode::Str,
range,
err,
)
}
})
}
fn validate_raw_byte_str_escape(&self, content_start: BytePos, content_end: BytePos) {
self.with_str_from_to(content_start, content_end, |lit: &str| {
unescape::unescape_raw_byte_str(lit, &mut |range, c| {
if let Err(err) = c {
emit_unescape_error(
&self.sess.span_diagnostic,
lit,
self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)),
unescape::Mode::ByteStr,
range,
err,
)
}
})
});
let lit = self.str_from_to(content_start, content_end);
unescape::unescape_raw_byte_str(lit, &mut |range, c| {
if let Err(err) = c {
emit_unescape_error(
&self.sess.span_diagnostic,
lit,
self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)),
unescape::Mode::ByteStr,
range,
err,
)
}
})
}
fn validate_byte_str_escape(&self, start_with_quote: BytePos) {
self.with_str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1), |lit| {
unescape::unescape_byte_str(lit, &mut |range, c| {
if let Err(err) = c {
emit_unescape_error(
&self.sess.span_diagnostic,
lit,
self.mk_sp(start_with_quote, self.pos),
unescape::Mode::ByteStr,
range,
err,
)
}
})
});
let lit = self.str_from_to(start_with_quote + BytePos(1), self.pos - BytePos(1));
unescape::unescape_byte_str(lit, &mut |range, c| {
if let Err(err) = c {
emit_unescape_error(
&self.sess.span_diagnostic,
lit,
self.mk_sp(start_with_quote, self.pos),
unescape::Mode::ByteStr,
range,
err,
)
}
})
}
}

View File

@ -290,10 +290,10 @@ crate enum LastToken {
}
impl TokenCursorFrame {
fn new(sp: DelimSpan, delim: DelimToken, tts: &TokenStream) -> Self {
fn new(span: DelimSpan, delim: DelimToken, tts: &TokenStream) -> Self {
TokenCursorFrame {
delim: delim,
span: sp,
delim,
span,
open_delim: delim == token::NoDelim,
tree_cursor: tts.clone().into_trees(),
close_delim: delim == token::NoDelim,
@ -1449,7 +1449,7 @@ impl<'a> Parser<'a> {
let opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
let mutbl = self.parse_mutability();
let ty = self.parse_ty_no_plus()?;
return Ok(TyKind::Rptr(opt_lifetime, MutTy { ty: ty, mutbl: mutbl }));
return Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }));
}
fn parse_ptr(&mut self) -> PResult<'a, MutTy> {
@ -1467,7 +1467,7 @@ impl<'a> Parser<'a> {
Mutability::Immutable
};
let t = self.parse_ty_no_plus()?;
Ok(MutTy { ty: t, mutbl: mutbl })
Ok(MutTy { ty: t, mutbl })
}
fn is_named_argument(&self) -> bool {
@ -4366,7 +4366,7 @@ impl<'a> Parser<'a> {
self.report_invalid_macro_expansion_item();
}
(ident, ast::MacroDef { tokens: tokens, legacy: true })
(ident, ast::MacroDef { tokens, legacy: true })
}
_ => return Ok(None),
};
@ -6789,12 +6789,12 @@ impl<'a> Parser<'a> {
let hi = self.token.span;
self.expect(&token::Semi)?;
Ok(ast::ForeignItem {
ident: ident,
attrs: attrs,
ident,
attrs,
node: ForeignItemKind::Ty,
id: ast::DUMMY_NODE_ID,
span: lo.to(hi),
vis: vis
vis
})
}

View File

@ -497,7 +497,7 @@ impl<'a> Printer<'a> {
pub fn print_newline(&mut self, amount: isize) -> io::Result<()> {
debug!("NEWLINE {}", amount);
let ret = write!(self.out, "\n");
let ret = writeln!(self.out);
self.pending_indentation = 0;
self.indent(amount);
ret

View File

@ -150,7 +150,7 @@ impl SourceMap {
-> SourceMap {
SourceMap {
files: Default::default(),
file_loader: file_loader,
file_loader,
path_mapping,
}
}
@ -396,7 +396,7 @@ impl SourceMap {
let f = (*self.files.borrow().source_files)[idx].clone();
match f.lookup_line(pos) {
Some(line) => Ok(SourceFileAndLine { sf: f, line: line }),
Some(line) => Ok(SourceFileAndLine { sf: f, line }),
None => Err(f)
}
}
@ -511,7 +511,7 @@ impl SourceMap {
start_col,
end_col: hi.col });
Ok(FileLines {file: lo.file, lines: lines})
Ok(FileLines {file: lo.file, lines})
}
/// Extracts the source surrounding the given `Span` using the `extract_source` function. The
@ -820,7 +820,7 @@ impl SourceMap {
let idx = self.lookup_source_file_idx(bpos);
let sf = (*self.files.borrow().source_files)[idx].clone();
let offset = bpos - sf.start_pos;
SourceFileAndBytePos {sf: sf, pos: offset}
SourceFileAndBytePos {sf, pos: offset}
}
/// Converts an absolute BytePos to a CharPos relative to the source_file.

View File

@ -1,13 +0,0 @@
#![feature(fnbox)]
#![allow(deprecated, deprecated_in_future)]
use std::boxed::FnBox;
fn call_it<T>(f: Box<dyn FnBox() -> T>) -> T {
f()
}
fn main() {
let s = "hello".to_owned();
assert_eq!(&call_it(Box::new(|| s)) as &str, "hello");
}

View File

@ -0,0 +1,59 @@
// compile-fail
// edition:2018
// compile-flags: --crate-type lib
#![feature(async_await)]
use std::{
cell::RefCell,
fmt::Debug,
rc::Rc,
};
fn non_sync() -> impl Debug { RefCell::new(()) }
fn non_send() -> impl Debug { Rc::new(()) }
fn take_ref<T>(_: &T) {}
async fn fut() {}
async fn fut_arg<T>(_: T) {}
async fn local_dropped_before_await() {
// FIXME: it'd be nice for this to be allowed in a `Send` `async fn`
let x = non_send();
drop(x);
fut().await;
}
async fn non_send_temporary_in_match() {
// We could theoretically make this work as well (produce a `Send` future)
// for scrutinees / temporaries that can or will
// be dropped prior to the match body
// (e.g. `Copy` types).
match Some(non_send()) {
Some(_) => fut().await,
None => {}
}
}
async fn non_sync_with_method_call() {
// FIXME: it'd be nice for this to work.
let f: &mut std::fmt::Formatter = panic!();
if non_sync().fmt(f).unwrap() == () {
fut().await;
}
}
fn assert_send(_: impl Send) {}
pub fn pass_assert() {
assert_send(local_dropped_before_await());
//~^ ERROR `std::rc::Rc<()>` cannot be sent between threads safely
assert_send(non_send_temporary_in_match());
//~^ ERROR `std::rc::Rc<()>` cannot be sent between threads safely
assert_send(non_sync_with_method_call());
//~^ ERROR `dyn std::fmt::Write` cannot be sent between threads safely
//~^^ ERROR `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
}

View File

@ -0,0 +1,87 @@
error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely
--> $DIR/async-fn-nonsend.rs:52:5
|
LL | assert_send(local_dropped_before_await());
| ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely
|
= help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>`
= note: required because it appears within the type `impl std::fmt::Debug`
= note: required because it appears within the type `{impl std::fmt::Debug, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:23:39: 28:2 {impl std::fmt::Debug, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:23:39: 28:2 {impl std::fmt::Debug, impl std::future::Future, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
note: required by `assert_send`
--> $DIR/async-fn-nonsend.rs:49:1
|
LL | fn assert_send(_: impl Send) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely
--> $DIR/async-fn-nonsend.rs:54:5
|
LL | assert_send(non_send_temporary_in_match());
| ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely
|
= help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>`
= note: required because it appears within the type `impl std::fmt::Debug`
= note: required because it appears within the type `{fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:30:40: 39:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:30:40: 39:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
note: required by `assert_send`
--> $DIR/async-fn-nonsend.rs:49:1
|
LL | fn assert_send(_: impl Send) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: `dyn std::fmt::Write` cannot be sent between threads safely
--> $DIR/async-fn-nonsend.rs:56:5
|
LL | assert_send(non_sync_with_method_call());
| ^^^^^^^^^^^ `dyn std::fmt::Write` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `dyn std::fmt::Write`
= note: required because of the requirements on the impl of `std::marker::Send` for `&mut dyn std::fmt::Write`
= note: required because it appears within the type `std::fmt::Formatter<'_>`
= note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>`
= note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
note: required by `assert_send`
--> $DIR/async-fn-nonsend.rs:49:1
|
LL | fn assert_send(_: impl Send) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
--> $DIR/async-fn-nonsend.rs:56:5
|
LL | assert_send(non_sync_with_method_call());
| ^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
|
= help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
= note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>`
= note: required because it appears within the type `core::fmt::Void`
= note: required because it appears within the type `&core::fmt::Void`
= note: required because it appears within the type `std::fmt::ArgumentV1<'_>`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::slice::Iter<'_, std::fmt::ArgumentV1<'_>>`
= note: required because it appears within the type `std::fmt::Formatter<'_>`
= note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>`
= note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}`
= note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>`
= note: required because it appears within the type `impl std::future::Future`
= note: required because it appears within the type `impl std::future::Future`
note: required by `assert_send`
--> $DIR/async-fn-nonsend.rs:49:1
|
LL | fn assert_send(_: impl Send) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,59 @@
// compile-pass
// edition:2018
// compile-flags: --crate-type lib
#![feature(async_await)]
use std::{
cell::RefCell,
fmt::Debug,
rc::Rc,
};
fn non_sync() -> impl Debug { RefCell::new(()) }
fn non_send() -> impl Debug { Rc::new(()) }
fn take_ref<T>(_: &T) {}
async fn fut() {}
async fn fut_arg<T>(_: T) {}
async fn still_send() {
fut().await;
println!("{:?} {:?}", non_send(), non_sync());
fut().await;
drop(non_send());
drop(non_sync());
fut().await;
fut_arg(non_sync()).await;
// Note: all temporaries in `if let` and `match` scrutinee
// are dropped at the *end* of the blocks, so using `non_send()`
// in either of those positions with an await in the middle will
// cause a `!Send` future. It might be nice in the future to allow
// this for `Copy` types, since they can be "dropped" early without
// affecting the end user.
if let Some(_) = Some(non_sync()) {
fut().await;
}
match Some(non_sync()) {
Some(_) => fut().await,
None => fut().await,
}
let _ = non_send();
fut().await;
{
let _x = non_send();
}
fut().await;
}
fn assert_send(_: impl Send) {}
pub fn pass_assert() {
assert_send(still_send());
}

View File

@ -0,0 +1,21 @@
// edition:2018
// This test ensures we don't make the suggestion in bodies that aren't `async`.
#![feature(async_await)]
fn take_u32(x: u32) {}
async fn make_u32() -> u32 {
22
}
async fn dont_suggest_await_in_closure() {
|| {
let x = make_u32();
take_u32(x)
//~^ ERROR mismatched types [E0308]
};
}
fn main() {}

View File

@ -0,0 +1,12 @@
error[E0308]: mismatched types
--> $DIR/dont-suggest-missing-await.rs:16:18
|
LL | take_u32(x)
| ^ expected u32, found opaque type
|
= 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`.

View File

@ -0,0 +1,90 @@
// compile-pass
// edition:2018
// compile-flags: --crate-type lib
#![feature(async_await)]
use std::future::Future;
pub async fn simple_generic<T>() {}
pub trait Foo {
fn foo(&self) {}
}
struct FooType;
impl Foo for FooType {}
pub async fn call_generic_bound<F: Foo>(f: F) {
f.foo()
}
pub async fn call_where_clause<F>(f: F)
where
F: Foo,
{
f.foo()
}
pub async fn call_impl_trait(f: impl Foo) {
f.foo()
}
pub async fn call_with_ref(f: &impl Foo) {
f.foo()
}
pub fn async_fn_with_same_generic_params_unifies() {
let mut a = call_generic_bound(FooType);
a = call_generic_bound(FooType);
let mut b = call_where_clause(FooType);
b = call_where_clause(FooType);
let mut c = call_impl_trait(FooType);
c = call_impl_trait(FooType);
let f_one = FooType;
let f_two = FooType;
let mut d = call_with_ref(&f_one);
d = call_with_ref(&f_two);
}
pub fn simple_generic_block<T>() -> impl Future<Output = ()> {
async move {}
}
pub fn call_generic_bound_block<F: Foo>(f: F) -> impl Future<Output = ()> {
async move { f.foo() }
}
pub fn call_where_clause_block<F>(f: F) -> impl Future<Output = ()>
where
F: Foo,
{
async move { f.foo() }
}
pub fn call_impl_trait_block(f: impl Foo) -> impl Future<Output = ()> {
async move { f.foo() }
}
pub fn call_with_ref_block<'a>(f: &'a (impl Foo + 'a)) -> impl Future<Output = ()> + 'a {
async move { f.foo() }
}
pub fn async_block_with_same_generic_params_unifies() {
let mut a = call_generic_bound_block(FooType);
a = call_generic_bound_block(FooType);
let mut b = call_where_clause_block(FooType);
b = call_where_clause_block(FooType);
let mut c = call_impl_trait_block(FooType);
c = call_impl_trait_block(FooType);
let f_one = FooType;
let f_two = FooType;
let mut d = call_with_ref_block(&f_one);
d = call_with_ref_block(&f_two);
}

View File

@ -7,7 +7,8 @@
async fn foo() {}
fn make_generator() {
let _gen = || foo.await; //~ ERROR `await` is only allowed inside `async` functions and blocks
let _gen = || foo().await;
//~^ ERROR `await` is only allowed inside `async` functions and blocks
}
fn main() {}

View File

@ -1,8 +1,8 @@
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-51719.rs:10:19
|
LL | let _gen = || foo.await;
| -- ^^^^^^^^^ only allowed inside `async` functions and blocks
LL | let _gen = || foo().await;
| -- ^^^^^^^^^^^ only allowed inside `async` functions and blocks
| |
| this is not `async`

View File

@ -0,0 +1,21 @@
// compile-pass
// edition:2018
//
// Tests that we properly handle StorageDead/StorageLives for temporaries
// created in async loop bodies.
#![feature(async_await)]
async fn bar() -> Option<()> {
Some(())
}
async fn listen() {
while let Some(_) = bar().await {
String::new();
}
}
fn main() {
listen();
}

View File

@ -0,0 +1,19 @@
// edition:2018
#![feature(async_await)]
async fn print_dur() {}
fn main() {
async { let (); }.await;
//~^ ERROR `await` is only allowed inside `async` functions and blocks
async {
//~^ ERROR `await` is only allowed inside `async` functions and blocks
let task1 = print_dur().await;
}.await;
(async || 2333)().await;
//~^ ERROR `await` is only allowed inside `async` functions and blocks
(|_| 2333).await;
//~^ ERROR `await` is only allowed inside `async` functions and blocks
//~^^ ERROR
}

View File

@ -0,0 +1,49 @@
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009.rs:8:5
|
LL | fn main() {
| ---- this is not `async`
LL | async { let (); }.await;
| ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009.rs:10:5
|
LL | fn main() {
| ---- this is not `async`
...
LL | / async {
LL | |
LL | | let task1 = print_dur().await;
LL | | }.await;
| |___________^ only allowed inside `async` functions and blocks
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> $DIR/issue-62009.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() {
| ---- this is not `async`
...
LL | (|_| 2333).await;
| ^^^^^^^^^^^^^^^^ 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
--> $DIR/issue-62009.rs:16:5
|
LL | (|_| 2333).await;
| ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009.rs:16:5: 16:15]`
|
= note: required by `std::future::poll_with_tls_context`
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0277`.

View File

@ -0,0 +1,8 @@
// compile-fail
// edition:2018
// compile-flags: --crate-type lib
#![feature(async_await)]
pub async const fn x() {}
//~^ ERROR expected one of `fn` or `unsafe`, found `const`

View File

@ -0,0 +1,8 @@
error: expected one of `fn` or `unsafe`, found `const`
--> $DIR/no-async-const.rs:7:11
|
LL | pub async const fn x() {}
| ^^^^^ expected one of `fn` or `unsafe` here
error: aborting due to previous error

View File

@ -0,0 +1,9 @@
// compile-fail
// edition:2018
// compile-flags: --crate-type lib
#![feature(async_await)]
pub const async fn x() {}
//~^ ERROR expected identifier, found reserved keyword `async`
//~^^ expected `:`, found keyword `fn`

View File

@ -0,0 +1,18 @@
error: expected identifier, found reserved keyword `async`
--> $DIR/no-const-async.rs:7:11
|
LL | pub const async fn x() {}
| ^^^^^ expected identifier, found reserved keyword
help: you can escape reserved keywords to use them as identifiers
|
LL | pub const r#async fn x() {}
| ^^^^^^^
error: expected `:`, found keyword `fn`
--> $DIR/no-const-async.rs:7:17
|
LL | pub const async fn x() {}
| ^^ expected `:`
error: aborting due to 2 previous errors

View File

@ -0,0 +1,32 @@
// edition:2018
// run-rustfix
#![feature(async_await)]
fn take_u32(_x: u32) {}
async fn make_u32() -> u32 {
22
}
#[allow(unused)]
async fn suggest_await_in_async_fn() {
let x = make_u32();
take_u32(x.await)
//~^ ERROR mismatched types [E0308]
//~| HELP consider using `.await` here
//~| 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() {}

View File

@ -0,0 +1,32 @@
// edition:2018
// run-rustfix
#![feature(async_await)]
fn take_u32(_x: u32) {}
async fn make_u32() -> u32 {
22
}
#[allow(unused)]
async fn suggest_await_in_async_fn() {
let x = make_u32();
take_u32(x)
//~^ ERROR mismatched types [E0308]
//~| HELP consider using `.await` here
//~| 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() {}

View File

@ -0,0 +1,27 @@
error[E0308]: mismatched types
--> $DIR/suggest-missing-await.rs:15:14
|
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[E0308]: mismatched types
--> $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`.

@ -1 +1 @@
Subproject commit 3e519650cea91a4b785cd773a3e5965553f74249
Subproject commit 597c9be8c75be3e664f189c4325c96cf9b464dc3