Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always create elided lifetime parameters for functions #97720

Merged
merged 4 commits into from
Jul 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ declare_features! (
/// below (it has to be checked before expansion possibly makes
/// macros disappear).
(active, allow_internal_unstable, "1.0.0", None, None),
/// Allows using anonymous lifetimes in argument-position impl-trait.
(active, anonymous_lifetime_in_impl_trait, "1.63.0", None, None),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or 1.64.0?

/// Allows identifying the `compiler_builtins` crate.
(active, compiler_builtins, "1.13.0", None, None),
/// Outputs useful `assert!` messages
Expand Down
20 changes: 9 additions & 11 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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),
);
Expand Down
17 changes: 16 additions & 1 deletion compiler/rustc_resolve/src/late/lifetimes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1677,14 +1677,29 @@ 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));
}
match scope_type {
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;
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ symbols! {
always,
and,
and_then,
anonymous_lifetime_in_impl_trait,
any,
append_const_msg,
arbitrary_enum_discriminant,
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui-fulldeps/internal-lints/rustc_pass_by_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl CustomStruct {

fn test_alias(
value: CustomAlias,
reference: &CustomAlias, //~ ERROR passing `CustomAlias<>` by reference
reference: &CustomAlias, //~ ERROR passing `CustomAlias<'_>` by reference
) {
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ error: passing `CustomStruct` by reference
LL | reference: &CustomStruct,
| ^^^^^^^^^^^^^ help: try passing by value: `CustomStruct`

error: passing `CustomAlias<>` by reference
error: passing `CustomAlias<'_>` by reference
--> $DIR/rustc_pass_by_value.rs:96:20
|
LL | reference: &CustomAlias,
| ^^^^^^^^^^^^ help: try passing by value: `CustomAlias<>`
| ^^^^^^^^^^^^ help: try passing by value: `CustomAlias<'_>`

error: passing `WithParameters<T, 1>` by reference
--> $DIR/rustc_pass_by_value.rs:110:20
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/generic-associated-types/bugs/issue-87748.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied
LL | fn do_sth(_: u32) {}
| ^^^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the anonymous lifetime #2 defined here
note: lifetime parameter instantiated with the anonymous lifetime as defined here
--> $DIR/issue-87748.rs:18:5
|
LL | fn do_sth(_: u32) {}
| ^^^^^^^^^^^^^^^^^
note: but lifetime parameter must outlive the anonymous lifetime #1 defined here
note: but lifetime parameter must outlive the anonymous lifetime as defined here
--> $DIR/issue-87748.rs:18:5
|
LL | fn do_sth(_: u32) {}
Expand Down
7 changes: 5 additions & 2 deletions src/test/ui/generic-associated-types/issue-95305.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@
// at some point in the future.

#![feature(generic_associated_types)]

#![feature(anonymous_lifetime_in_impl_trait)]
trait Foo {
type Item<'a>;
}

fn foo(x: &impl Foo<Item<'_> = u32>) { }
//~^ ERROR `'_` cannot be used here [E0637]

// Ok: the anonymous lifetime is bound to the function.
fn bar(x: &impl for<'a> Foo<Item<'a> = &'_ u32>) { }
//~^ ERROR missing lifetime specifier

// Ok: the anonymous lifetime is bound to the function.
fn baz(x: &impl for<'a> Foo<Item<'a> = &u32>) { }

fn main() {}
16 changes: 2 additions & 14 deletions src/test/ui/generic-associated-types/issue-95305.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,6 @@ error[E0637]: `'_` cannot be used here
LL | fn foo(x: &impl Foo<Item<'_> = u32>) { }
| ^^ `'_` is a reserved lifetime name

error[E0106]: missing lifetime specifier
--> $DIR/issue-95305.rs:14:41
|
LL | fn bar(x: &impl for<'a> Foo<Item<'a> = &'_ u32>) { }
| ^^ expected named lifetime parameter
|
help: consider using the `'a` lifetime
|
LL | fn bar(x: &impl for<'a> Foo<Item<'a> = &'a u32>) { }
| ~~

error: aborting due to 2 previous errors
error: aborting due to previous error

Some errors have detailed explanations: E0106, E0637.
For more information about an error, try `rustc --explain E0106`.
For more information about this error, try `rustc --explain E0637`.
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-37884.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ LL | fn next(&'a mut self) -> Option<Self::Item>
|
= note: expected fn pointer `fn(&mut RepeatMut<'a, T>) -> Option<_>`
found fn pointer `fn(&'a mut RepeatMut<'a, T>) -> Option<_>`
note: the anonymous lifetime #1 defined here...
note: the anonymous lifetime as defined here...
--> $DIR/issue-37884.rs:6:5
|
LL | fn next(&'a mut self) -> Option<Self::Item>
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea
--> $DIR/impl-trait-captures.rs:11:5
|
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
| -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0)) T` captures the anonymous lifetime defined here
| -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here
LL | x
| ^
|
help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0))` lifetime bound
help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound
|
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrAnon(0)) {
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_)) {
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

error: aborting due to previous error

Expand Down
21 changes: 21 additions & 0 deletions src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// edition:2021
// gate-test-anonymous_lifetime_in_impl_trait
// Verify the behaviour of `feature(anonymous_lifetime_in_impl_trait)`.

fn f(_: impl Iterator<Item = &'_ ()>) {}
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable

fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
//~| ERROR missing lifetime specifier

// Anonymous lifetimes in async fn are already allowed.
// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
async fn h(_: impl Iterator<Item = &'_ ()>) {}

// Anonymous lifetimes in async fn are already allowed.
// But that lifetime does not participate in resolution.
async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
//~^ ERROR missing lifetime specifier

fn main() {}
44 changes: 44 additions & 0 deletions src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:5:31
|
LL | fn f(_: impl Iterator<Item = &'_ ()>) {}
| ^^
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable

error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:8:50
|
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
help: consider using the `'static` lifetime
|
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~

error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:8:31
|
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
| ^^
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable

error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:18:56
|
LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
help: consider using the `'static` lifetime
|
LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~

error: aborting due to 4 previous errors

Some errors have detailed explanations: E0106, E0658.
For more information about an error, try `rustc --explain E0106`.
19 changes: 18 additions & 1 deletion src/test/ui/suggestions/impl-trait-missing-lifetime.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,19 @@
fn f(_: impl Iterator<Item = &'_ ()>) {} //~ ERROR missing lifetime specifier
// edition:2021

#![feature(anonymous_lifetime_in_impl_trait)]

// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
fn f(_: impl Iterator<Item = &'_ ()>) {}

// But that lifetime does not participate in resolution.
fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
//~^ ERROR missing lifetime specifier

// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
async fn h(_: impl Iterator<Item = &'_ ()>) {}

// But that lifetime does not participate in resolution.
async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
//~^ ERROR missing lifetime specifier

fn main() {}
27 changes: 20 additions & 7 deletions src/test/ui/suggestions/impl-trait-missing-lifetime.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime.rs:1:31
--> $DIR/impl-trait-missing-lifetime.rs:9:50
|
LL | fn f(_: impl Iterator<Item = &'_ ()>) {}
| ^^ expected named lifetime parameter
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
| ^^ expected named lifetime parameter
|
help: consider introducing a named lifetime parameter
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
help: consider using the `'static` lifetime
|
LL | fn f<'a>(_: impl Iterator<Item = &'a ()>) {}
| ++++ ~~
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~

error: aborting due to previous error
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime.rs:16:56
|
LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
help: consider using the `'static` lifetime
|
LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0106`.
6 changes: 3 additions & 3 deletions src/test/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ note: because this has an unmet lifetime requirement
|
LL | pub struct Wrapper<T: Trait>(T);
| ^^^^^ introduces a `'static` lifetime requirement
note: the anonymous lifetime #1 defined here...
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:5
note: the anonymous lifetime as defined here...
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:29
|
LL | pub fn repro(_: Wrapper<Ref>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^
note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
--> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:1
|
Expand Down
4 changes: 2 additions & 2 deletions src/tools/clippy/clippy_lints/src/inherent_to_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{get_trait_def_id, paths, return_ty, trait_ref_of_method};
use if_chain::if_chain;
use rustc_hir::{ImplItem, ImplItemKind};
use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
Expand Down Expand Up @@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString {
let decl = &signature.decl;
if decl.implicit_self.has_implicit_self();
if decl.inputs.len() == 1;
if impl_item.generics.params.is_empty();
if impl_item.generics.params.iter().all(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }));

// Check if return type is String
if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::String);
Expand Down
10 changes: 7 additions & 3 deletions src/tools/clippy/clippy_lints/src/lifetimes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use rustc_hir::intravisit::{
use rustc_hir::FnRetTy::Return;
use rustc_hir::{
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin,
TraitBoundModifier, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, LifetimeParamKind, ParamName, PolyTraitRef,
PredicateOrigin, TraitBoundModifier, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter as middle_nested_filter;
Expand Down Expand Up @@ -338,7 +338,10 @@ fn could_use_elision<'tcx>(
fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet<RefLt> {
let mut allowed_lts = FxHashSet::default();
for par in named_generics.iter() {
if let GenericParamKind::Lifetime { .. } = par.kind {
if let GenericParamKind::Lifetime {
kind: LifetimeParamKind::Explicit,
} = par.kind
{
allowed_lts.insert(RefLt::Named(par.name.ident().name));
}
}
Expand Down Expand Up @@ -379,6 +382,7 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
self.lts.push(RefLt::Static);
} else if let LifetimeName::Param(_, ParamName::Fresh) = lt.name {
// Fresh lifetimes generated should be ignored.
self.lts.push(RefLt::Unnamed);
} else if lt.is_elided() {
self.lts.push(RefLt::Unnamed);
} else {
Expand Down
3 changes: 2 additions & 1 deletion src/tools/clippy/clippy_lints/src/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,12 +495,13 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio
if let FnRetTy::Return(ty) = sig.decl.output
&& let Some((out, Mutability::Mut, _)) = get_rptr_lm(ty)
{
let out_region = cx.tcx.named_region(out.hir_id);
let args: Option<Vec<_>> = sig
.decl
.inputs
.iter()
.filter_map(get_rptr_lm)
.filter(|&(lt, _, _)| lt.name == out.name)
.filter(|&(lt, _, _)| cx.tcx.named_region(lt.hir_id) == out_region)
.map(|(_, mutability, span)| (mutability == Mutability::Not).then(|| span))
.collect();
if let Some(args) = args
Expand Down
Loading