about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs69
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs18
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0760.md6
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs4
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs34
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs15
-rw-r--r--compiler/rustc_typeck/src/check/check.rs15
-rw-r--r--compiler/rustc_typeck/src/collect.rs5
8 files changed, 88 insertions, 78 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 60b5aeb52b1..b1e601516ab 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1659,12 +1659,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         // When we create the opaque type for this async fn, it is going to have
         // to capture all the lifetimes involved in the signature (including in the
-        // return type). This is done by:
+        // return type). This is done by introducing lifetime parameters for:
         //
-        // - making the opaque type inherit all lifetime parameters from its parent;
-        // - make all the elided lifetimes in the fn arguments into parameters;
-        // - manually introducing parameters on the opaque type for elided
-        //   lifetimes in the return type.
+        // - all the explicitly declared lifetimes from the impl and function itself;
+        // - all the elided lifetimes in the fn arguments;
+        // - all the elided lifetimes in the return type.
         //
         // So for example in this snippet:
         //
@@ -1680,14 +1679,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // we would create an opaque type like:
         //
         // ```
-        // type Foo<'a>::bar<'b, '0, '1>::Bar<'2> = impl Future<Output = &'2 u32>;
+        // type Bar<'a, 'b, '0, '1, '2> = impl Future<Output = &'2 u32>;
         // ```
         //
         // and we would then desugar `bar` to the equivalent of:
         //
         // ```rust
         // impl<'a> Foo<'a> {
-        //   fn bar<'b, '0, '1>(&'0 self, x: &'b Vec<f64>, y: &'1 str) -> Bar<'_>
+        //   fn bar<'b, '0, '1>(&'0 self, x: &'b Vec<f64>, y: &'1 str) -> Bar<'a, 'b, '0, '1, '_>
         // }
         // ```
         //
@@ -1695,7 +1694,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // this is because the elided lifetimes from the return type
         // should be figured out using the ordinary elision rules, and
         // this desugaring achieves that.
-        let mut lifetime_params = Vec::new();
+
+        debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", self.in_scope_lifetimes);
+        debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", self.lifetimes_to_define);
+
+        // Calculate all the lifetimes that should be captured
+        // by the opaque type. This should include all in-scope
+        // lifetime parameters, including those defined in-band.
+        //
+        // `lifetime_params` is a vector of tuple (span, parameter name, lifetime name).
+
+        // Input lifetime like `'a` or `'1`:
+        let mut lifetime_params: Vec<_> = self
+            .in_scope_lifetimes
+            .iter()
+            .cloned()
+            .map(|name| (name.ident().span, name, hir::LifetimeName::Param(name)))
+            .chain(
+                self.lifetimes_to_define
+                    .iter()
+                    .map(|&(span, name)| (span, name, hir::LifetimeName::Param(name))),
+            )
+            .collect();
+
         self.with_hir_id_owner(opaque_ty_node_id, |this| {
             // We have to be careful to get elision right here. The
             // idea is that we create a lifetime parameter for each
@@ -1714,12 +1735,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound);
             debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", lifetimes_to_define);
 
-            // Output lifetime like `'_`:
-            lifetime_params = lifetimes_to_define;
+            lifetime_params.extend(
+                // Output lifetime like `'_`:
+                lifetimes_to_define
+                    .into_iter()
+                    .map(|(span, name)| (span, name, hir::LifetimeName::Implicit(false))),
+            );
             debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params);
 
             let generic_params =
-                this.arena.alloc_from_iter(lifetime_params.iter().map(|&(span, hir_name)| {
+                this.arena.alloc_from_iter(lifetime_params.iter().map(|&(span, hir_name, _)| {
                     this.lifetime_to_generic_param(span, hir_name, opaque_ty_def_id)
                 }));
 
@@ -1737,22 +1762,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span)
         });
 
-        // We need to create the lifetime arguments to our opaque type.
-        // Continuing with our example, we're creating the type arguments
-        // for the return type:
+        // As documented above on the variable
+        // `input_lifetimes_count`, we need to create the lifetime
+        // arguments to our opaque type. Continuing with our example,
+        // we're creating the type arguments for the return type:
         //
         // ```
-        // For<'a>::bar<'b, '0, '1>::Bar<'_>
+        // Bar<'a, 'b, '0, '1, '_>
         // ```
         //
-        // For the "input" lifetime parameters are inherited automatically.
-        // For the "output" lifetime parameters, we just want to generate `'_`.
+        // For the "input" lifetime parameters, we wish to create
+        // references to the parameters themselves, including the
+        // "implicit" ones created from parameter types (`'a`, `'b`,
+        // '`0`, `'1`).
+        //
+        // For the "output" lifetime parameters, we just want to
+        // generate `'_`.
         let generic_args =
-            self.arena.alloc_from_iter(lifetime_params.into_iter().map(|(span, _)| {
+            self.arena.alloc_from_iter(lifetime_params.into_iter().map(|(span, _, name)| {
                 GenericArg::Lifetime(hir::Lifetime {
                     hir_id: self.next_id(),
                     span: self.lower_span(span),
-                    name: hir::LifetimeName::Implicit(false),
+                    name,
                 })
             }));
 
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index dee47a3e440..abd6a15334c 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -2156,24 +2156,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 }
             }
 
-            // When in async fn, prefer errors that come from inside the closure.
-            if !categorized_path[i].from_closure {
-                let span = categorized_path.iter().find_map(|p| {
-                    if p.from_closure
-                        && p.category == categorized_path[i].category
-                        && categorized_path[i].cause.span.contains(p.cause.span)
-                    {
-                        Some(p.cause.span)
-                    } else {
-                        None
-                    }
-                });
-
-                if let Some(span) = span {
-                    categorized_path[i].cause.span = span;
-                }
-            }
-
             return categorized_path[i].clone();
         }
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0760.md b/compiler/rustc_error_codes/src/error_codes/E0760.md
index 65acd4fabdf..e1dcfefebcd 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0760.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0760.md
@@ -1,4 +1,4 @@
-`impl trait` return type cannot contain a projection
+`async fn`/`impl trait` return type cannot contain a projection
 or `Self` that references lifetimes from a parent scope.
 
 Erroneous code example:
@@ -7,7 +7,7 @@ Erroneous code example:
 struct S<'a>(&'a i32);
 
 impl<'a> S<'a> {
-    fn new(i: &'a i32) -> impl Into<Self> {
+    async fn new(i: &'a i32) -> Self {
         S(&22)
     }
 }
@@ -19,7 +19,7 @@ To fix this error we need to spell out `Self` to `S<'a>`:
 struct S<'a>(&'a i32);
 
 impl<'a> S<'a> {
-    fn new(i: &'a i32) -> impl Into<S<'a>> {
+    async fn new(i: &'a i32) -> S<'a> {
         S(&22)
     }
 }
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index e79ece9a4a4..e7dca94806c 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -276,7 +276,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         debug!(?concrete_ty);
 
         let first_own_region = match opaque_defn.origin {
-            hir::OpaqueTyOrigin::FnReturn(..) => {
+            hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {
                 // We lower
                 //
                 // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
@@ -291,7 +291,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             }
             // These opaque type inherit all lifetime parameters from their
             // parent, so we have to check them all.
-            hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::TyAlias => 0,
+            hir::OpaqueTyOrigin::TyAlias => 0,
         };
 
         // For a case like `impl Foo<'a, 'b>`, we would generate a constraint
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index 1ce70f5dcf7..3bea95fa1d5 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -729,16 +729,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         match item.kind {
             hir::ItemKind::Fn(ref sig, ref generics, _) => {
                 self.missing_named_lifetime_spots.push(generics.into());
-                self.visit_early_late(
-                    None,
-                    item.hir_id(),
-                    &sig.decl,
-                    generics,
-                    sig.header.asyncness,
-                    |this| {
-                        intravisit::walk_item(this, item);
-                    },
-                );
+                self.visit_early_late(None, item.hir_id(), &sig.decl, generics, |this| {
+                    intravisit::walk_item(this, item);
+                });
                 self.missing_named_lifetime_spots.pop();
             }
 
@@ -856,16 +849,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
 
     fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
         match item.kind {
-            hir::ForeignItemKind::Fn(ref decl, _, ref generics) => self.visit_early_late(
-                None,
-                item.hir_id(),
-                decl,
-                generics,
-                hir::IsAsync::NotAsync,
-                |this| {
+            hir::ForeignItemKind::Fn(ref decl, _, ref generics) => {
+                self.visit_early_late(None, item.hir_id(), decl, generics, |this| {
                     intravisit::walk_foreign_item(this, item);
-                },
-            ),
+                })
+            }
             hir::ForeignItemKind::Static(..) => {
                 intravisit::walk_foreign_item(self, item);
             }
@@ -1142,7 +1130,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     trait_item.hir_id(),
                     &sig.decl,
                     &trait_item.generics,
-                    sig.header.asyncness,
                     |this| intravisit::walk_trait_item(this, trait_item),
                 );
                 self.missing_named_lifetime_spots.pop();
@@ -1212,7 +1199,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     impl_item.hir_id(),
                     &sig.decl,
                     &impl_item.generics,
-                    sig.header.asyncness,
                     |this| intravisit::walk_impl_item(this, impl_item),
                 );
                 self.missing_named_lifetime_spots.pop();
@@ -2173,15 +2159,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         hir_id: hir::HirId,
         decl: &'tcx hir::FnDecl<'tcx>,
         generics: &'tcx hir::Generics<'tcx>,
-        asyncness: hir::IsAsync,
         walk: F,
     ) where
         F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>),
     {
-        // Async fns need all their lifetime parameters to be early bound.
-        if asyncness != hir::IsAsync::Async {
-            insert_late_bound_lifetimes(self.map, decl, generics);
-        }
+        insert_late_bound_lifetimes(self.map, decl, generics);
 
         // Find the start of nested early scopes, e.g., in methods.
         let mut next_early_index = 0;
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 845f03183c3..96f92049983 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -2409,11 +2409,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let def_id = item_id.def_id.to_def_id();
 
                 match opaque_ty.kind {
-                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
-                        let replace_parent_lifetimes =
-                            matches!(origin, hir::OpaqueTyOrigin::FnReturn(..));
-                        self.impl_trait_ty_to_ty(def_id, lifetimes, replace_parent_lifetimes)
-                    }
+                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => self
+                        .impl_trait_ty_to_ty(
+                            def_id,
+                            lifetimes,
+                            matches!(
+                                origin,
+                                hir::OpaqueTyOrigin::FnReturn(..)
+                                    | hir::OpaqueTyOrigin::AsyncFn(..)
+                            ),
+                        ),
                     ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
                 }
             }
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 6dbda1005dd..fba8292b467 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -545,8 +545,10 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
         }
     }
 
-    if let ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(..), .. }) =
-        item.kind
+    if let ItemKind::OpaqueTy(hir::OpaqueTy {
+        origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
+        ..
+    }) = item.kind
     {
         let mut visitor = ProhibitOpaqueVisitor {
             opaque_identity_ty: tcx.mk_opaque(
@@ -568,13 +570,20 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
 
         if let Some(ty) = prohibit_opaque.break_value() {
             visitor.visit_item(&item);
+            let is_async = match item.kind {
+                ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
+                    matches!(origin, hir::OpaqueTyOrigin::AsyncFn(..))
+                }
+                _ => unreachable!(),
+            };
 
             let mut err = struct_span_err!(
                 tcx.sess,
                 span,
                 E0760,
-                "`impl Trait` return type cannot contain a projection or `Self` that references lifetimes from \
+                "`{}` return type cannot contain a projection or `Self` that references lifetimes from \
                  a parent scope",
+                if is_async { "async fn" } else { "impl Trait" },
             );
 
             for (span, name) in visitor.selftys {
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 88dc90dd3e7..4c9f21d0d4a 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -2157,7 +2157,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                     generics
                 }
                 ItemKind::OpaqueTy(OpaqueTy {
-                    origin: hir::OpaqueTyOrigin::FnReturn(..), ..
+                    origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
+                    ..
                 }) => {
                     // return-position impl trait
                     //
@@ -2177,7 +2178,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                 }
                 ItemKind::OpaqueTy(OpaqueTy {
                     ref generics,
-                    origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::TyAlias,
+                    origin: hir::OpaqueTyOrigin::TyAlias,
                     ..
                 }) => {
                     // type-alias impl trait