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``
This commit is contained in:
commit
f5e9cb53ab
20 changed files with 163 additions and 56 deletions
|
@ -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),
|
||||
);
|
||||
|
|
|
@ -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(®ion_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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue