Use kw::Empty for elided lifetimes in path.

This commit is contained in:
Camille GILLOT 2022-11-06 11:40:31 +00:00
parent 41090346d8
commit 1c737d6997
12 changed files with 281 additions and 83 deletions

View File

@ -2101,7 +2101,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::LifetimeName::Param(param) hir::LifetimeName::Param(param)
} }
LifetimeRes::Fresh { param, .. } => { LifetimeRes::Fresh { param, .. } => {
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
let param = self.local_def_id(param); let param = self.local_def_id(param);
hir::LifetimeName::Param(param) hir::LifetimeName::Param(param)
} }

View File

@ -309,7 +309,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let id = NodeId::from_u32(i); let id = NodeId::from_u32(i);
let l = self.lower_lifetime(&Lifetime { let l = self.lower_lifetime(&Lifetime {
id, id,
ident: Ident::new(kw::UnderscoreLifetime, elided_lifetime_span), ident: Ident::new(kw::Empty, elided_lifetime_span),
}); });
GenericArg::Lifetime(l) GenericArg::Lifetime(l)
}), }),

View File

@ -29,14 +29,15 @@ use std::fmt;
#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)] #[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
pub struct Lifetime { pub struct Lifetime {
pub hir_id: HirId, pub hir_id: HirId,
pub ident: Ident,
/// Either "`'a`", referring to a named lifetime definition, /// Either "`'a`", referring to a named lifetime definition,
/// or "``" (i.e., `kw::Empty`), for elision placeholders. /// `'_` referring to an anonymous lifetime (either explicitly `'_` or `&type`),
/// or "``" (i.e., `kw::Empty`) when appearing in path.
/// ///
/// HIR lowering inserts these placeholders in type paths that /// See `Lifetime::suggestion_position` for practical use.
/// refer to type definitions needing lifetime parameters, pub ident: Ident,
/// `&T` and `&mut T`, and trait objects without `... + 'a`.
/// Semantics of this lifetime.
pub res: LifetimeName, pub res: LifetimeName,
} }
@ -135,6 +136,19 @@ impl fmt::Display for Lifetime {
} }
} }
pub enum LifetimeSuggestionPosition {
/// The user wrote `'a` or `'_`.
Normal,
/// The user wrote `&type` or `&mut type`.
Ampersand,
/// The user wrote `Path` and omitted the `<'_>`.
ElidedPath,
/// The user wrote `Path<T>`, and omitted the `'_,`.
ElidedPathArgument,
/// The user wrote `dyn Trait` and omitted the `+ '_`.
ObjectDefault,
}
impl Lifetime { impl Lifetime {
pub fn is_elided(&self) -> bool { pub fn is_elided(&self) -> bool {
self.res.is_elided() self.res.is_elided()
@ -144,6 +158,22 @@ impl Lifetime {
self.ident.name == kw::Empty || self.ident.name == kw::UnderscoreLifetime self.ident.name == kw::Empty || self.ident.name == kw::UnderscoreLifetime
} }
pub fn suggestion_position(&self) -> (LifetimeSuggestionPosition, Span) {
if self.ident.name == kw::Empty {
if self.ident.span.is_empty() {
(LifetimeSuggestionPosition::ElidedPathArgument, self.ident.span)
} else {
(LifetimeSuggestionPosition::ElidedPath, self.ident.span.shrink_to_hi())
}
} else if self.res == LifetimeName::ImplicitObjectLifetimeDefault {
(LifetimeSuggestionPosition::ObjectDefault, self.ident.span)
} else if self.ident.span.is_empty() {
(LifetimeSuggestionPosition::Ampersand, self.ident.span)
} else {
(LifetimeSuggestionPosition::Normal, self.ident.span)
}
}
pub fn is_static(&self) -> bool { pub fn is_static(&self) -> bool {
self.res == LifetimeName::Static self.res == LifetimeName::Static
} }

View File

@ -19,7 +19,7 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_lifetime::*; use rustc_middle::middle::resolve_lifetime::*;
use rustc_middle::ty::{self, DefIdTree, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_middle::ty::{self, DefIdTree, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::symbol::{sym, Ident};
use rustc_span::Span; use rustc_span::Span;
use std::fmt; use std::fmt;
@ -1218,13 +1218,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
(generics.span, "<'a>".to_owned()) (generics.span, "<'a>".to_owned())
}; };
let lifetime_sugg = match lifetime_ref.ident.name { let lifetime_sugg = match lifetime_ref.suggestion_position() {
kw::Empty => "'a, ".to_owned(), (hir::LifetimeSuggestionPosition::Normal, span) => (span, "'a".to_owned()),
kw::UnderscoreLifetime => "'a ".to_owned(), (hir::LifetimeSuggestionPosition::Ampersand, span) => (span, "'a ".to_owned()),
_ => "'a ".to_owned(), (hir::LifetimeSuggestionPosition::ElidedPath, span) => (span, "<'a>".to_owned()),
(hir::LifetimeSuggestionPosition::ElidedPathArgument, span) => (span, "'a, ".to_owned()),
(hir::LifetimeSuggestionPosition::ObjectDefault, span) => (span, "+ 'a".to_owned()),
}; };
let suggestions = vec![ let suggestions = vec![
(lifetime_ref.ident.span.shrink_to_hi(), lifetime_sugg), lifetime_sugg,
new_param_sugg, new_param_sugg,
]; ];

View File

@ -3,7 +3,7 @@ use crate::ty::{EarlyBinder, SubstsRef};
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_span::symbol::Symbol; use rustc_span::symbol::{kw, Symbol};
use rustc_span::Span; use rustc_span::Span;
use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predicate, TyCtxt}; use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predicate, TyCtxt};
@ -78,6 +78,15 @@ impl GenericParamDef {
} }
} }
pub fn is_anonymous_lifetime(&self) -> bool {
match self.kind {
GenericParamDefKind::Lifetime => {
self.name == kw::UnderscoreLifetime || self.name == kw::Empty
}
_ => false,
}
}
pub fn default_value<'tcx>( pub fn default_value<'tcx>(
&self, &self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,

View File

@ -530,7 +530,7 @@ impl ty::EarlyBoundRegion {
/// Does this early bound region have a name? Early bound regions normally /// Does this early bound region have a name? Early bound regions normally
/// always have names except when using anonymous lifetimes (`'_`). /// always have names except when using anonymous lifetimes (`'_`).
pub fn has_name(&self) -> bool { pub fn has_name(&self) -> bool {
self.name != kw::UnderscoreLifetime self.name != kw::UnderscoreLifetime && self.name != kw::Empty
} }
} }

View File

@ -1963,17 +1963,13 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions; let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions;
match *region { match *region {
ty::ReEarlyBound(ref data) => { ty::ReEarlyBound(ref data) => data.has_name(),
data.name != kw::Empty && data.name != kw::UnderscoreLifetime
}
ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
| ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
| ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
if let ty::BrNamed(_, name) = br { if br.is_named() {
if name != kw::Empty && name != kw::UnderscoreLifetime { return true;
return true;
}
} }
if let Some((region, _)) = highlight.highlight_bound_region { if let Some((region, _)) = highlight.highlight_bound_region {
@ -2049,11 +2045,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
| ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
| ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
if let ty::BrNamed(_, name) = br { if let ty::BrNamed(_, name) = br && br.is_named() {
if name != kw::Empty && name != kw::UnderscoreLifetime { p!(write("{}", name));
p!(write("{}", name)); return Ok(self);
return Ok(self);
}
} }
if let Some((region, counter)) = highlight.highlight_bound_region { if let Some((region, counter)) = highlight.highlight_bound_region {
@ -2266,7 +2260,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
(name, ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)) (name, ty::BrNamed(CRATE_DEF_ID.to_def_id(), name))
} }
ty::BrNamed(def_id, kw::UnderscoreLifetime) => { ty::BrNamed(def_id, kw::UnderscoreLifetime | kw::Empty) => {
let name = next_name(&self); let name = next_name(&self);
if let Some(lt_idx) = lifetime_idx { if let Some(lt_idx) = lifetime_idx {

View File

@ -83,7 +83,9 @@ pub struct BoundRegion {
impl BoundRegionKind { impl BoundRegionKind {
pub fn is_named(&self) -> bool { pub fn is_named(&self) -> bool {
match *self { match *self {
BoundRegionKind::BrNamed(_, name) => name != kw::UnderscoreLifetime, BoundRegionKind::BrNamed(_, name) => {
name != kw::UnderscoreLifetime && name != kw::Empty
}
_ => false, _ => false,
} }
} }

View File

@ -182,9 +182,7 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
.collect_referenced_late_bound_regions(&poly_trait_ref) .collect_referenced_late_bound_regions(&poly_trait_ref)
.into_iter() .into_iter()
.filter_map(|br| match br { .filter_map(|br| match br {
ty::BrNamed(_, name) if name != kw::UnderscoreLifetime => { ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)),
Some(GenericParamDef::lifetime(name))
}
_ => None, _ => None,
}) })
.collect(); .collect();
@ -233,16 +231,11 @@ pub(crate) fn clean_middle_const<'tcx>(
pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Lifetime> { pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Lifetime> {
match *region { match *region {
ty::ReStatic => Some(Lifetime::statik()), ty::ReStatic => Some(Lifetime::statik()),
_ if !region.has_name() => None,
ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => { ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => {
if name != kw::UnderscoreLifetime { Some(Lifetime(name)) } else { None } Some(Lifetime(name))
}
ty::ReEarlyBound(ref data) => {
if data.name != kw::UnderscoreLifetime {
Some(Lifetime(data.name))
} else {
None
}
} }
ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)),
ty::ReLateBound(..) ty::ReLateBound(..)
| ty::ReFree(..) | ty::ReFree(..)
| ty::ReVar(..) | ty::ReVar(..)
@ -396,7 +389,7 @@ fn clean_projection_predicate<'tcx>(
.collect_referenced_late_bound_regions(&pred) .collect_referenced_late_bound_regions(&pred)
.into_iter() .into_iter()
.filter_map(|br| match br { .filter_map(|br| match br {
ty::BrNamed(_, name) if name != kw::UnderscoreLifetime => Some(Lifetime(name)), ty::BrNamed(_, name) if br.is_named() => Some(Lifetime(name)),
_ => None, _ => None,
}) })
.collect(); .collect();
@ -660,7 +653,7 @@ fn clean_ty_generics<'tcx>(
.params .params
.iter() .iter()
.filter_map(|param| match param.kind { .filter_map(|param| match param.kind {
ty::GenericParamDefKind::Lifetime if param.name == kw::UnderscoreLifetime => None, ty::GenericParamDefKind::Lifetime if param.is_anonymous_lifetime() => None,
ty::GenericParamDefKind::Lifetime => Some(clean_generic_param_def(param, cx)), ty::GenericParamDefKind::Lifetime => Some(clean_generic_param_def(param, cx)),
ty::GenericParamDefKind::Type { synthetic, .. } => { ty::GenericParamDefKind::Type { synthetic, .. } => {
if param.name == kw::SelfUpper { if param.name == kw::SelfUpper {
@ -1460,8 +1453,11 @@ fn maybe_expand_private_type_alias<'tcx>(
}); });
if let Some(lt) = lifetime { if let Some(lt) = lifetime {
let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id); let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
let cleaned = let cleaned = if !lt.is_anonymous() {
if !lt.is_elided() { clean_lifetime(lt, cx) } else { Lifetime::elided() }; clean_lifetime(lt, cx)
} else {
Lifetime::elided()
};
substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned)); substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned));
} }
indices.lifetimes += 1; indices.lifetimes += 1;
@ -1892,7 +1888,7 @@ fn clean_generic_args<'tcx>(
.args .args
.iter() .iter()
.map(|arg| match arg { .map(|arg| match arg {
hir::GenericArg::Lifetime(lt) if !lt.is_elided() => { hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => {
GenericArg::Lifetime(clean_lifetime(*lt, cx)) GenericArg::Lifetime(clean_lifetime(*lt, cx))
} }
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),

View File

@ -2,20 +2,62 @@
// gate-test-anonymous_lifetime_in_impl_trait // gate-test-anonymous_lifetime_in_impl_trait
// Verify the behaviour of `feature(anonymous_lifetime_in_impl_trait)`. // Verify the behaviour of `feature(anonymous_lifetime_in_impl_trait)`.
fn f(_: impl Iterator<Item = &'_ ()>) {} mod elided {
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable fn f(_: impl Iterator<Item = &()>) {}
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } fn g(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable //~^ ERROR anonymous lifetimes in `impl Trait` are unstable
//~| ERROR missing lifetime specifier //~| ERROR missing lifetime specifier
// Anonymous lifetimes in async fn are already allowed. // Anonymous lifetimes in async fn are already allowed.
// This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`. // This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`.
async fn h(_: impl Iterator<Item = &'_ ()>) {} async fn h(_: impl Iterator<Item = &()>) {}
// Anonymous lifetimes in async fn are already allowed. // Anonymous lifetimes in async fn are already allowed.
// But that lifetime does not participate in resolution. // But that lifetime does not participate in resolution.
async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } async fn i(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
//~^ ERROR missing lifetime specifier //~^ ERROR missing lifetime specifier
}
mod underscore {
fn f(_: impl Iterator<Item = &'_ ()>) {}
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
fn g(mut 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(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
//~^ ERROR missing lifetime specifier
}
mod alone_in_path {
trait Foo<'a> { fn next(&mut self) -> Option<&'a ()>; }
fn f(_: impl Foo) {}
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
fn g(mut x: impl Foo) -> Option<&()> { x.next() }
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
//~| ERROR missing lifetime specifier
}
mod in_path {
trait Foo<'a, T> { fn next(&mut self) -> Option<&'a T>; }
fn f(_: impl Foo<()>) {}
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
//~^ ERROR anonymous lifetimes in `impl Trait` are unstable
//~| ERROR missing lifetime specifier
}
fn main() {} fn main() {}

View File

@ -1,52 +1,172 @@
error[E0106]: missing lifetime specifier error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:8:50 --> $DIR/impl-trait-missing-lifetime-gated.rs:9:54
| |
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } LL | fn g(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
| ^^ expected named lifetime parameter | ^ expected named lifetime parameter
| |
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime help: consider using the `'static` lifetime
| |
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() } LL | fn g(mut x: impl Iterator<Item = &()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~ | +++++++
error[E0106]: missing lifetime specifier error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:18:56 --> $DIR/impl-trait-missing-lifetime-gated.rs:19:60
| |
LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } LL | async fn i(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
| ^^ expected named lifetime parameter | ^ expected named lifetime parameter
| |
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime help: consider using the `'static` lifetime
| |
LL | async fn i(x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() } LL | async fn i(mut x: impl Iterator<Item = &()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~ | +++++++
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:27:58
|
LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
|
LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:37:64
|
LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
|
LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:47:37
|
LL | fn g(mut x: impl Foo) -> Option<&()> { x.next() }
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
|
LL | fn g(mut x: impl Foo) -> Option<&'static ()> { x.next() }
| +++++++
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:58:41
|
LL | fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
|
LL | fn g(mut x: impl Foo<()>) -> Option<&'static ()> { x.next() }
| +++++++
error[E0658]: anonymous lifetimes in `impl Trait` are unstable error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:5:31 --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35
| |
LL | fn f(_: impl Iterator<Item = &'_ ()>) {} LL | fn f(_: impl Iterator<Item = &()>) {}
| ^^ expected named lifetime parameter | ^ expected named lifetime parameter
| |
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
help: consider introducing a named lifetime parameter help: consider introducing a named lifetime parameter
| |
LL | fn f<'a>(_: impl Iterator<Item = &'_'a ()>) {} LL | fn f<'a>(_: impl Iterator<Item = &'a ()>) {}
| ++++ ++ | ++++ ++
error[E0658]: anonymous lifetimes in `impl Trait` are unstable error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:8:31 --> $DIR/impl-trait-missing-lifetime-gated.rs:9:39
| |
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } LL | fn g(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
| ^^ expected named lifetime parameter | ^ expected named lifetime parameter
| |
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
help: consider introducing a named lifetime parameter help: consider introducing a named lifetime parameter
| |
LL | fn g<'a>(x: impl Iterator<Item = &'_'a ()>) -> Option<&'_ ()> { x.next() } LL | fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&()> { x.next() }
| ++++ ++ | ++++ ++
error: aborting due to 4 previous errors error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:24:35
|
LL | fn f(_: impl Iterator<Item = &'_ ()>) {}
| ^^ expected named lifetime parameter
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
help: consider introducing a named lifetime parameter
|
LL | fn f<'a>(_: impl Iterator<Item = &'a ()>) {}
| ++++ ~~
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:27:39
|
LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
| ^^ expected named lifetime parameter
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
help: consider introducing a named lifetime parameter
|
LL | fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'_ ()> { x.next() }
| ++++ ~~
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:44:18
|
LL | fn f(_: impl Foo) {}
| ^^^ expected named lifetime parameter
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
help: consider introducing a named lifetime parameter
|
LL | fn f<'a>(_: impl Foo<'a>) {}
| ++++ ++++
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:47:22
|
LL | fn g(mut x: impl Foo) -> Option<&()> { x.next() }
| ^^^ expected named lifetime parameter
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
help: consider introducing a named lifetime parameter
|
LL | fn g<'a>(mut x: impl Foo<'a>) -> Option<&()> { x.next() }
| ++++ ++++
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:55:22
|
LL | fn f(_: impl Foo<()>) {}
| ^ expected named lifetime parameter
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
help: consider introducing a named lifetime parameter
|
LL | fn f<'a>(_: impl Foo<'a, ()>) {}
| ++++ +++
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:58:26
|
LL | fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
| ^ expected named lifetime parameter
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
help: consider introducing a named lifetime parameter
|
LL | fn g<'a>(mut x: impl Foo<'a, ()>) -> Option<&()> { x.next() }
| ++++ +++
error: aborting due to 14 previous errors
Some errors have detailed explanations: E0106, E0658. Some errors have detailed explanations: E0106, E0658.
For more information about an error, try `rustc --explain E0106`. For more information about an error, try `rustc --explain E0106`.

View File

@ -10,8 +10,8 @@ use rustc_hir::lang_items;
use rustc_hir::FnRetTy::Return; use rustc_hir::FnRetTy::Return;
use rustc_hir::{ use rustc_hir::{
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem, BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, PolyTraitRef, PredicateOrigin, TraitFn, TraitItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, PolyTraitRef, PredicateOrigin, TraitFn,
TraitItemKind, Ty, TyKind, WherePredicate, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
}; };
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter as middle_nested_filter; use rustc_middle::hir::nested_filter as middle_nested_filter;
@ -595,7 +595,9 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
.params .params
.iter() .iter()
.filter_map(|par| match par.kind { .filter_map(|par| match par.kind {
GenericParamKind::Lifetime { .. } => Some((par.name.ident().name, par.span)), GenericParamKind::Lifetime {
kind: LifetimeParamKind::Explicit,
} => Some((par.name.ident().name, par.span)),
_ => None, _ => None,
}) })
.collect(); .collect();
@ -620,7 +622,9 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
.params .params
.iter() .iter()
.filter_map(|par| match par.kind { .filter_map(|par| match par.kind {
GenericParamKind::Lifetime { .. } => Some((par.name.ident().name, par.span)), GenericParamKind::Lifetime {
kind: LifetimeParamKind::Explicit,
} => Some((par.name.ident().name, par.span)),
_ => None, _ => None,
}) })
.collect(); .collect();
@ -647,7 +651,7 @@ struct BodyLifetimeChecker {
impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker { impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker {
// for lifetimes as parameters of generics // for lifetimes as parameters of generics
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) { fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
if lifetime.ident.name != kw::UnderscoreLifetime && lifetime.ident.name != kw::StaticLifetime { if !lifetime.is_anonymous() && lifetime.ident.name != kw::StaticLifetime {
self.lifetimes_used_in_body = true; self.lifetimes_used_in_body = true;
} }
} }