about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs20
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--library/core/src/async_iter/async_iter.rs23
-rw-r--r--library/core/src/async_iter/mod.rs2
-rw-r--r--library/core/tests/async_iter/mod.rs17
-rw-r--r--library/core/tests/lib.rs4
-rw-r--r--tests/ui/associated-inherent-types/issue-109071.no_gate.stderr9
-rw-r--r--tests/ui/async-await/for-await-consumes-iter.stderr13
-rw-r--r--tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr9
-rw-r--r--tests/ui/typeck/issue-110052.stderr9
10 files changed, 93 insertions, 14 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 5fa04dda8be..1f6d47ab453 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -1814,7 +1814,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     arena_vec![self; head],
                 )
             }
-            ForLoopKind::ForAwait => self.arena.alloc(head),
+            // ` unsafe { Pin::new_unchecked(&mut into_async_iter(<head>)) }`
+            ForLoopKind::ForAwait => {
+                // `::core::async_iter::IntoAsyncIterator::into_async_iter(<head>)`
+                let iter = self.expr_call_lang_item_fn(
+                    head_span,
+                    hir::LangItem::IntoAsyncIterIntoIter,
+                    arena_vec![self; head],
+                );
+                let iter = self.expr_mut_addr_of(head_span, iter);
+                // `Pin::new_unchecked(...)`
+                let iter = self.arena.alloc(self.expr_call_lang_item_fn_mut(
+                    head_span,
+                    hir::LangItem::PinNewUnchecked,
+                    arena_vec![self; iter],
+                ));
+                // `unsafe { ... }`
+                let iter = self.arena.alloc(self.expr_unsafe(iter));
+                iter
+            }
         };
 
         let match_expr = self.arena.alloc(self.expr_match(
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 7691cd11c4f..3f3b57ba94f 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -308,6 +308,7 @@ language_item_table! {
     FuturePoll,              sym::poll,                future_poll_fn,             Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
 
     AsyncIteratorPollNext,   sym::async_iterator_poll_next, async_iterator_poll_next, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0);
+    IntoAsyncIterIntoIter,   sym::into_async_iter_into_iter, into_async_iter_into_iter, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::Exact(0);
 
     Option,                  sym::Option,              option_type,                Target::Enum,           GenericRequirement::None;
     OptionSome,              sym::Some,                option_some_variant,        Target::Variant,        GenericRequirement::None;
diff --git a/library/core/src/async_iter/async_iter.rs b/library/core/src/async_iter/async_iter.rs
index a7512ef6a24..db71a286b6d 100644
--- a/library/core/src/async_iter/async_iter.rs
+++ b/library/core/src/async_iter/async_iter.rs
@@ -135,3 +135,26 @@ impl<T> Poll<Option<T>> {
     #[lang = "AsyncGenFinished"]
     pub const FINISHED: Self = Poll::Ready(None);
 }
+
+/// Convert something into an async iterator
+#[unstable(feature = "async_iterator", issue = "79024")]
+pub trait IntoAsyncIterator {
+    /// The type of the item yielded by the iterator
+    type Item;
+    /// The type of the resulting iterator
+    type IntoAsyncIter: AsyncIterator<Item = Self::Item>;
+
+    /// Converts `self` into an async iterator
+    #[cfg_attr(not(bootstrap), lang = "into_async_iter_into_iter")]
+    fn into_async_iter(self) -> Self::IntoAsyncIter;
+}
+
+#[unstable(feature = "async_iterator", issue = "79024")]
+impl<I: AsyncIterator> IntoAsyncIterator for I {
+    type Item = I::Item;
+    type IntoAsyncIter = I;
+
+    fn into_async_iter(self) -> Self::IntoAsyncIter {
+        self
+    }
+}
diff --git a/library/core/src/async_iter/mod.rs b/library/core/src/async_iter/mod.rs
index 0c6f637711b..e1f1c907582 100644
--- a/library/core/src/async_iter/mod.rs
+++ b/library/core/src/async_iter/mod.rs
@@ -124,5 +124,5 @@
 mod async_iter;
 mod from_iter;
 
-pub use async_iter::AsyncIterator;
+pub use async_iter::{AsyncIterator, IntoAsyncIterator};
 pub use from_iter::{from_iter, FromIter};
diff --git a/library/core/tests/async_iter/mod.rs b/library/core/tests/async_iter/mod.rs
new file mode 100644
index 00000000000..0c30bd1dfea
--- /dev/null
+++ b/library/core/tests/async_iter/mod.rs
@@ -0,0 +1,17 @@
+use core::async_iter::{self, AsyncIterator, IntoAsyncIterator};
+use core::pin::pin;
+use core::task::Poll;
+
+#[test]
+fn into_async_iter() {
+    let async_iter = async_iter::from_iter(0..3);
+    let mut async_iter = pin!(async_iter.into_async_iter());
+
+    let waker = core::task::Waker::noop();
+    let mut cx = &mut core::task::Context::from_waker(&waker);
+
+    assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(0)));
+    assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(1)));
+    assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(Some(2)));
+    assert_eq!(async_iter.as_mut().poll_next(&mut cx), Poll::Ready(None));
+}
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index fabdd4ee25d..b53cf459244 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -4,6 +4,8 @@
 #![feature(array_windows)]
 #![feature(ascii_char)]
 #![feature(ascii_char_variants)]
+#![feature(async_iter_from_iter)]
+#![feature(async_iterator)]
 #![feature(bigint_helper_methods)]
 #![feature(cell_update)]
 #![feature(const_align_offset)]
@@ -55,6 +57,7 @@
 #![feature(maybe_uninit_write_slice)]
 #![feature(maybe_uninit_uninit_array_transpose)]
 #![feature(min_specialization)]
+#![feature(noop_waker)]
 #![feature(numfmt)]
 #![feature(num_midpoint)]
 #![feature(isqrt)]
@@ -125,6 +128,7 @@ mod any;
 mod array;
 mod ascii;
 mod asserting;
+mod async_iter;
 mod atomic;
 mod bool;
 mod cell;
diff --git a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr
index 866a53f57fc..2fceeb15ea9 100644
--- a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr
+++ b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr
@@ -33,7 +33,14 @@ error[E0223]: ambiguous associated type
   --> $DIR/issue-109071.rs:15:22
    |
 LL |     fn T() -> Option<Self::Item> {}
-   |                      ^^^^^^^^^^ help: use fully-qualified syntax: `<Windows<T> as IntoIterator>::Item`
+   |                      ^^^^^^^^^^
+   |
+help: use fully-qualified syntax
+   |
+LL |     fn T() -> Option<<Windows<T> as IntoAsyncIterator>::Item> {}
+   |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     fn T() -> Option<<Windows<T> as IntoIterator>::Item> {}
+   |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/async-await/for-await-consumes-iter.stderr b/tests/ui/async-await/for-await-consumes-iter.stderr
index 48b2e8a51d8..a3e5bbcabf5 100644
--- a/tests/ui/async-await/for-await-consumes-iter.stderr
+++ b/tests/ui/async-await/for-await-consumes-iter.stderr
@@ -5,22 +5,17 @@ LL |     let iter = core::async_iter::from_iter(0..3);
    |         ---- move occurs because `iter` has type `FromIter<std::ops::Range<i32>>`, which does not implement the `Copy` trait
 LL |     let mut count = 0;
 LL |     for await i in iter {
-   |     -------------------
-   |     |              |
-   |     |              value moved here
-   |     inside of this loop
+   |                    ---- `iter` moved due to this method call
 ...
 LL |     for await i in iter {
    |                    ^^^^ value used here after move
    |
-help: consider cloning the value if the performance cost is acceptable
+note: `into_async_iter` takes ownership of the receiver `self`, which moves `iter`
+  --> $SRC_DIR/core/src/async_iter/async_iter.rs:LL:COL
+help: you can `clone` the value and consume it, but this might not be your desired behavior
    |
 LL |     for await i in iter.clone() {
    |                        ++++++++
-help: borrow this binding in the pattern to avoid moving the value
-   |
-LL |     for await i in ref iter {
-   |                    +++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr
index c0f0c414227..cabaa76a886 100644
--- a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr
+++ b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr
@@ -2,7 +2,14 @@ error[E0223]: ambiguous associated type
   --> $DIR/suggest-trait-in-ufcs-in-hrtb.rs:5:38
    |
 LL | impl<S> Foo for Bar<S> where for<'a> <&'a S>::Item: Foo {}
-   |                                      ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<&'a S as IntoIterator>::Item`
+   |                                      ^^^^^^^^^^^^^
+   |
+help: use fully-qualified syntax
+   |
+LL | impl<S> Foo for Bar<S> where for<'a> <&'a S as IntoAsyncIterator>::Item: Foo {}
+   |                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | impl<S> Foo for Bar<S> where for<'a> <&'a S as IntoIterator>::Item: Foo {}
+   |                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/typeck/issue-110052.stderr b/tests/ui/typeck/issue-110052.stderr
index b25b6c0c0b7..5eb10d9a30e 100644
--- a/tests/ui/typeck/issue-110052.stderr
+++ b/tests/ui/typeck/issue-110052.stderr
@@ -2,7 +2,14 @@ error[E0223]: ambiguous associated type
   --> $DIR/issue-110052.rs:6:30
    |
 LL |     for<'iter> dyn Validator<<&'iter I>::Item>:,
-   |                              ^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<&'iter I as IntoIterator>::Item`
+   |                              ^^^^^^^^^^^^^^^^
+   |
+help: use fully-qualified syntax
+   |
+LL |     for<'iter> dyn Validator<<&'iter I as IntoAsyncIterator>::Item>:,
+   |                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     for<'iter> dyn Validator<<&'iter I as IntoIterator>::Item>:,
+   |                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 1 previous error