about summary refs log tree commit diff
path: root/compiler/rustc_resolve
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-07-14 14:14:19 +0530
committerGitHub <noreply@github.com>2022-07-14 14:14:19 +0530
commitf5e9cb53ab35bdf6e1bdd75894eca93ac7d8a0be (patch)
tree130660a53abebbf1450e43db702db9406861b626 /compiler/rustc_resolve
parent431c6f84990cdd08b68d46efff2efc75549934fe (diff)
parent5a20834884f653e84485fb905785fdbca98b7e02 (diff)
downloadrust-f5e9cb53ab35bdf6e1bdd75894eca93ac7d8a0be.tar.gz
rust-f5e9cb53ab35bdf6e1bdd75894eca93ac7d8a0be.zip
Rollup merge of #97720 - cjgillot:all-fresh, r=petrochenkov
Always create elided lifetime parameters for functions

Anonymous and elided lifetimes in functions are sometimes (async fns) --and sometimes not (regular fns)-- desugared to implicit generic parameters.

This difference of treatment makes it some downstream analyses more complicated to handle.  This step is a pre-requisite to perform lifetime elision resolution on AST.

There is currently an inconsistency in the treatment of argument-position impl-trait for functions and async fns:
```rust
trait Foo<'a> {}
fn foo(t: impl Foo<'_>) {} //~ ERROR missing lifetime specifier
async fn async_foo(t: impl Foo<'_>) {} //~ OK
fn bar(t: impl Iterator<Item = &'_ u8>) {} //~ ERROR missing lifetime specifier
async fn async_bar(t: impl Iterator<Item = &'_ u8>) {} //~ OK
```

The current implementation reports "missing lifetime specifier" on `foo`, but **accepts it** in `async_foo`.
This PR **proposes to accept** the anonymous lifetime in both cases as an extra generic lifetime parameter.
This change would be insta-stable, so let's ping t-lang.
Anonymous lifetimes in GAT bindings keep being forbidden:
```rust
fn foo(t: impl Foo<Assoc<'_> = Bar<'_>>) {}
                         ^^        ^^
                       forbidden   ok
```
I started a discussion here: https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Anonymous.20lifetimes.20in.20universal.20impl-trait/near/284968606

r? ``@petrochenkov``
Diffstat (limited to 'compiler/rustc_resolve')
-rw-r--r--compiler/rustc_resolve/src/late.rs20
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs17
2 files changed, 25 insertions, 12 deletions
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 098b5a0c92e..3b371740022 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -758,7 +758,10 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                 // We don't need to deal with patterns in parameters, because
                 // they are not possible for foreign or bodiless functions.
                 self.with_lifetime_rib(
-                    LifetimeRibKind::AnonymousPassThrough(fn_id, false),
+                    LifetimeRibKind::AnonymousCreateParameter {
+                        binder: fn_id,
+                        report_in_path: false,
+                    },
                     |this| walk_list!(this, visit_param, &sig.decl.inputs),
                 );
                 self.with_lifetime_rib(
@@ -792,18 +795,13 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                         // generic parameters.  This is especially useful for `async fn`, where
                         // these fresh generic parameters can be applied to the opaque `impl Trait`
                         // return type.
-                        let rib = if async_node_id.is_some() {
-                            // Only emit a hard error for `async fn`, since this kind of
-                            // elision has always been allowed in regular `fn`s.
+                        this.with_lifetime_rib(
                             LifetimeRibKind::AnonymousCreateParameter {
                                 binder: fn_id,
-                                report_in_path: true,
-                            }
-                        } else {
-                            LifetimeRibKind::AnonymousPassThrough(fn_id, false)
-                        };
-                        this.with_lifetime_rib(
-                            rib,
+                                // Only emit a hard error for `async fn`, since this kind of
+                                // elision has always been allowed in regular `fn`s.
+                                report_in_path: async_node_id.is_some(),
+                            },
                             // Add each argument to the rib.
                             |this| this.resolve_params(&declaration.inputs),
                         );
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index 557dbecfabe..79688529082 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -1677,7 +1677,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                     break None;
                 }
 
-                Scope::Binder { ref lifetimes, scope_type, s, .. } => {
+                Scope::Binder { ref lifetimes, scope_type, s, where_bound_origin, .. } => {
                     if let Some(&def) = lifetimes.get(&region_def_id) {
                         break Some(def.shifted(late_depth));
                     }
@@ -1685,6 +1685,21 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                         BinderScopeType::Normal => late_depth += 1,
                         BinderScopeType::Concatenating => {}
                     }
+                    // Fresh lifetimes in APIT used to be allowed in async fns and forbidden in
+                    // regular fns.
+                    if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
+                        && let hir::LifetimeName::Param(_, hir::ParamName::Fresh) = lifetime_ref.name
+                        && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner)
+                        && !self.tcx.features().anonymous_lifetime_in_impl_trait
+                    {
+                        rustc_session::parse::feature_err(
+                            &self.tcx.sess.parse_sess,
+                            sym::anonymous_lifetime_in_impl_trait,
+                            lifetime_ref.span,
+                            "anonymous lifetimes in `impl Trait` are unstable",
+                        ).emit();
+                        return;
+                    }
                     scope = s;
                 }