Auto merge of #104048 - cjgillot:split-lifetime, r=compiler-errors

Separate lifetime ident from lifetime resolution in HIR

Drive-by: change how suggested generic args are computed.
Fixes https://github.com/rust-lang/rust/issues/103815

I recommend reviewing commit-by-commit.
This commit is contained in:
bors 2022-11-27 14:30:19 +00:00
commit 454784afba
49 changed files with 581 additions and 435 deletions

View File

@ -605,6 +605,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
output,
c_variadic: false,
implicit_self: hir::ImplicitSelfKind::None,
lifetime_elision_allowed: false,
});
// Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
@ -917,7 +918,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
// Lower outside new scope to preserve `is_in_loop_condition`.
let fn_decl = self.lower_fn_decl(decl, None, fn_decl_span, FnDeclKind::Closure, None);
let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
let c = self.arena.alloc(hir::Closure {
def_id: self.local_def_id(closure_id),
@ -1027,7 +1028,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// have to conserve the state of being inside a loop condition for the
// closure argument types.
let fn_decl =
self.lower_fn_decl(&outer_decl, None, fn_decl_span, FnDeclKind::Closure, None);
self.lower_fn_decl(&outer_decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
let c = self.arena.alloc(hir::Closure {
def_id: self.local_def_id(closure_id),

View File

@ -303,7 +303,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
}
fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) {
self.insert(lifetime.span, lifetime.hir_id, Node::Lifetime(lifetime));
self.insert(lifetime.ident.span, lifetime.hir_id, Node::Lifetime(lifetime));
}
fn visit_variant(&mut self, v: &'hir Variant<'hir>) {

View File

@ -274,7 +274,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let mut itctx = ImplTraitContext::Universal;
let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| {
let ret_id = asyncness.opt_return_id();
this.lower_fn_decl(&decl, Some(id), *fn_sig_span, FnDeclKind::Fn, ret_id)
this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id)
});
let sig = hir::FnSig {
decl,
@ -659,7 +659,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Disallow `impl Trait` in foreign items.
this.lower_fn_decl(
fdec,
None,
i.id,
sig.span,
FnDeclKind::ExternFn,
None,
@ -1247,7 +1247,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let header = self.lower_fn_header(sig.header);
let mut itctx = ImplTraitContext::Universal;
let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| {
this.lower_fn_decl(&sig.decl, Some(id), sig.span, kind, is_async)
this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async)
});
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
}
@ -1479,10 +1479,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
}))
}
GenericParamKind::Lifetime => {
let ident_span = self.lower_span(ident.span);
let ident = self.lower_ident(ident);
let lt_id = self.next_node_id();
let lifetime = self.new_named_lifetime(id, lt_id, ident_span, ident);
let lifetime = self.new_named_lifetime(id, lt_id, ident);
Some(hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
lifetime,
span,

View File

@ -327,7 +327,14 @@ enum FnDeclKind {
}
impl FnDeclKind {
fn impl_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
fn param_impl_trait_allowed(&self) -> bool {
match self {
FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => true,
_ => false,
}
}
fn return_impl_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
match self {
FnDeclKind::Fn | FnDeclKind::Inherent => true,
FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true,
@ -1255,7 +1262,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} else {
self.next_node_id()
};
let span = self.tcx.sess.source_map().start_point(t.span);
let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();
Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id }
});
let lifetime = self.lower_lifetime(&region);
@ -1267,7 +1274,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
generic_params,
unsafety: self.lower_unsafety(f.unsafety),
abi: self.lower_extern(f.ext),
decl: self.lower_fn_decl(&f.decl, None, t.span, FnDeclKind::Pointer, None),
decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None),
param_names: self.lower_fn_params_to_names(&f.decl),
}))
}
@ -1546,15 +1553,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let lifetimes =
self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(_, lifetime)| {
let id = self.next_node_id();
let span = lifetime.ident.span;
let ident = if lifetime.ident.name == kw::UnderscoreLifetime {
Ident::with_dummy_span(kw::UnderscoreLifetime)
} else {
lifetime.ident
};
let l = self.new_named_lifetime(lifetime.id, id, span, ident);
let l = self.new_named_lifetime(lifetime.id, id, lifetime.ident);
hir::GenericArg::Lifetime(l)
}));
debug!(?lifetimes);
@ -1679,7 +1678,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_fn_decl(
&mut self,
decl: &FnDecl,
fn_node_id: Option<NodeId>,
fn_node_id: NodeId,
fn_span: Span,
kind: FnDeclKind,
make_ret_async: Option<(NodeId, Span)>,
@ -1694,23 +1693,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
inputs = &inputs[..inputs.len() - 1];
}
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
if fn_node_id.is_some() {
self.lower_ty_direct(&param.ty, &ImplTraitContext::Universal)
let itctx = if kind.param_impl_trait_allowed() {
ImplTraitContext::Universal
} else {
self.lower_ty_direct(
&param.ty,
&ImplTraitContext::Disallowed(match kind {
FnDeclKind::Fn | FnDeclKind::Inherent => {
unreachable!("fn should allow in-band lifetimes")
}
FnDeclKind::ExternFn => ImplTraitPosition::ExternFnParam,
FnDeclKind::Closure => ImplTraitPosition::ClosureParam,
FnDeclKind::Pointer => ImplTraitPosition::PointerParam,
FnDeclKind::Trait => ImplTraitPosition::TraitParam,
FnDeclKind::Impl => ImplTraitPosition::ImplParam,
}),
)
}
ImplTraitContext::Disallowed(match kind {
FnDeclKind::Fn | FnDeclKind::Inherent => {
unreachable!("fn should allow APIT")
}
FnDeclKind::ExternFn => ImplTraitPosition::ExternFnParam,
FnDeclKind::Closure => ImplTraitPosition::ClosureParam,
FnDeclKind::Pointer => ImplTraitPosition::PointerParam,
FnDeclKind::Trait => ImplTraitPosition::TraitParam,
FnDeclKind::Impl => ImplTraitPosition::ImplParam,
})
};
self.lower_ty_direct(&param.ty, &itctx)
}));
let output = if let Some((ret_id, span)) = make_ret_async {
@ -1733,22 +1730,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.lower_async_fn_ret_ty(
&decl.output,
fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
fn_node_id,
ret_id,
matches!(kind, FnDeclKind::Trait),
)
} else {
match &decl.output {
FnRetTy::Ty(ty) => {
let mut context = match fn_node_id {
Some(fn_node_id) if kind.impl_trait_allowed(self.tcx) => {
let fn_def_id = self.local_def_id(fn_node_id);
ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
in_trait: matches!(kind, FnDeclKind::Trait),
}
let mut context = if kind.return_impl_trait_allowed(self.tcx) {
let fn_def_id = self.local_def_id(fn_node_id);
ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
in_trait: matches!(kind, FnDeclKind::Trait),
}
_ => ImplTraitContext::Disallowed(match kind {
} else {
ImplTraitContext::Disallowed(match kind {
FnDeclKind::Fn | FnDeclKind::Inherent => {
unreachable!("fn should allow in-band lifetimes")
}
@ -1757,7 +1753,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
FnDeclKind::Trait => ImplTraitPosition::TraitReturn,
FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
}),
})
};
hir::FnRetTy::Return(self.lower_ty(ty, &mut context))
}
@ -1769,6 +1765,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
inputs,
output,
c_variadic,
lifetime_elision_allowed: self.resolver.lifetime_elision_allowed.contains(&fn_node_id),
implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
let is_mutable_pat = matches!(
arg.pat.kind,
@ -2010,18 +2007,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let generic_args = self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(
|(_, lifetime, res)| {
let id = self.next_node_id();
let span = lifetime.ident.span;
let ident = if lifetime.ident.name == kw::UnderscoreLifetime {
Ident::with_dummy_span(kw::UnderscoreLifetime)
} else {
lifetime.ident
};
let res = res.unwrap_or(
self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
);
hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, span, ident, res))
hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, lifetime.ident, res))
},
));
@ -2091,43 +2080,40 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime {
let span = self.lower_span(l.ident.span);
let ident = self.lower_ident(l.ident);
self.new_named_lifetime(l.id, l.id, span, ident)
self.new_named_lifetime(l.id, l.id, ident)
}
#[instrument(level = "debug", skip(self))]
fn new_named_lifetime_with_res(
&mut self,
id: NodeId,
span: Span,
ident: Ident,
res: LifetimeRes,
) -> &'hir hir::Lifetime {
let name = match res {
let res = match res {
LifetimeRes::Param { param, .. } => {
let p_name = ParamName::Plain(ident);
let param = self.get_remapped_def_id(param);
hir::LifetimeName::Param(param, p_name)
hir::LifetimeName::Param(param)
}
LifetimeRes::Fresh { param, .. } => {
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
let param = self.local_def_id(param);
hir::LifetimeName::Param(param, ParamName::Fresh)
hir::LifetimeName::Param(param)
}
LifetimeRes::Infer => hir::LifetimeName::Infer,
LifetimeRes::Static => hir::LifetimeName::Static,
LifetimeRes::Error => hir::LifetimeName::Error,
res => panic!("Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, span),
res => panic!(
"Unexpected lifetime resolution {:?} for {:?} at {:?}",
res, ident, ident.span
),
};
debug!(?name);
debug!(?res);
self.arena.alloc(hir::Lifetime {
hir_id: self.lower_node_id(id),
span: self.lower_span(span),
name,
ident: self.lower_ident(ident),
res,
})
}
@ -2136,11 +2122,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
id: NodeId,
new_id: NodeId,
span: Span,
ident: Ident,
) -> &'hir hir::Lifetime {
let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
self.new_named_lifetime_with_res(new_id, span, ident, res)
self.new_named_lifetime_with_res(new_id, ident, res)
}
fn lower_generic_params_mut<'s>(
@ -2552,8 +2537,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime {
let r = hir::Lifetime {
hir_id: self.next_id(),
span: self.lower_span(span),
name: hir::LifetimeName::ImplicitObjectLifetimeDefault,
ident: Ident::new(kw::Empty, self.lower_span(span)),
res: hir::LifetimeName::ImplicitObjectLifetimeDefault,
};
debug!("elided_dyn_bound: r={:?}", r);
self.arena.alloc(r)

View File

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

View File

@ -2670,7 +2670,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let hir::TyKind::Rptr(lifetime, _) = &fn_decl.inputs[index].kind {
// With access to the lifetime, we can get
// the span of it.
arguments.push((*argument, lifetime.span));
arguments.push((*argument, lifetime.ident.span));
} else {
bug!("ty type is a ref but hir type is not");
}
@ -2689,7 +2689,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let mut return_span = fn_decl.output.span();
if let hir::FnRetTy::Return(ty) = &fn_decl.output {
if let hir::TyKind::Rptr(lifetime, _) = ty.kind {
return_span = lifetime.span;
return_span = lifetime.ident.span;
}
}

View File

@ -1211,7 +1211,7 @@ fn get_mut_span_in_struct_field<'tcx>(
&& let hir::Node::Field(field) = node
&& let hir::TyKind::Rptr(lt, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = field.ty.kind
{
return Some(lt.span.between(ty.span));
return Some(lt.ident.span.between(ty.span));
}
None

View File

@ -576,30 +576,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let args = last_segment.args.as_ref()?;
let lifetime =
self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
match lifetime.name {
hir::LifetimeName::Param(_, hir::ParamName::Plain(_) | hir::ParamName::Error)
| hir::LifetimeName::Error
| hir::LifetimeName::Static => {
let lifetime_span = lifetime.span;
Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span))
}
hir::LifetimeName::Param(_, hir::ParamName::Fresh)
| hir::LifetimeName::ImplicitObjectLifetimeDefault
| hir::LifetimeName::Infer => {
// In this case, the user left off the lifetime; so
// they wrote something like:
//
// ```
// x: Foo<T>
// ```
//
// where the fully elaborated form is `Foo<'_, '1,
// T>`. We don't consider this a match; instead we let
// the "fully elaborated" type fallback above handle
// it.
None
}
if lifetime.is_anonymous() {
None
} else {
Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime.ident.span))
}
}

View File

@ -29,15 +29,16 @@ use std::fmt;
#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
pub struct Lifetime {
pub hir_id: HirId,
pub span: Span,
/// 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
/// refer to type definitions needing lifetime parameters,
/// `&T` and `&mut T`, and trait objects without `... + 'a`.
pub name: LifetimeName,
/// See `Lifetime::suggestion_position` for practical use.
pub ident: Ident,
/// Semantics of this lifetime.
pub res: LifetimeName,
}
#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
@ -88,7 +89,7 @@ impl ParamName {
#[derive(HashStable_Generic)]
pub enum LifetimeName {
/// User-given names or fresh (synthetic) names.
Param(LocalDefId, ParamName),
Param(LocalDefId),
/// Implicit lifetime in a context like `dyn Foo`. This is
/// distinguished from implicit lifetimes elsewhere because the
@ -116,25 +117,6 @@ pub enum LifetimeName {
}
impl LifetimeName {
pub fn ident(&self) -> Ident {
match *self {
LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Error => Ident::empty(),
LifetimeName::Infer => Ident::with_dummy_span(kw::UnderscoreLifetime),
LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime),
LifetimeName::Param(_, param_name) => param_name.ident(),
}
}
pub fn is_anonymous(&self) -> bool {
match *self {
LifetimeName::ImplicitObjectLifetimeDefault
| LifetimeName::Infer
| LifetimeName::Param(_, ParamName::Fresh)
| LifetimeName::Error => true,
LifetimeName::Static | LifetimeName::Param(..) => false,
}
}
pub fn is_elided(&self) -> bool {
match self {
LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Infer => true,
@ -146,34 +128,54 @@ impl LifetimeName {
LifetimeName::Error | LifetimeName::Param(..) | LifetimeName::Static => false,
}
}
fn is_static(&self) -> bool {
self == &LifetimeName::Static
}
pub fn normalize_to_macros_2_0(&self) -> LifetimeName {
match *self {
LifetimeName::Param(def_id, param_name) => {
LifetimeName::Param(def_id, param_name.normalize_to_macros_2_0())
}
lifetime_name => lifetime_name,
}
}
}
impl fmt::Display for Lifetime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.name.ident().fmt(f)
if self.ident.name != kw::Empty { self.ident.name.fmt(f) } else { "'_".fmt(f) }
}
}
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 {
pub fn is_elided(&self) -> bool {
self.name.is_elided()
self.res.is_elided()
}
pub fn is_anonymous(&self) -> bool {
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 {
self.name.is_static()
self.res == LifetimeName::Static
}
}
@ -267,7 +269,7 @@ pub enum GenericArg<'hir> {
impl GenericArg<'_> {
pub fn span(&self) -> Span {
match self {
GenericArg::Lifetime(l) => l.span,
GenericArg::Lifetime(l) => l.ident.span,
GenericArg::Type(t) => t.span,
GenericArg::Const(c) => c.span,
GenericArg::Infer(i) => i.span,
@ -284,7 +286,7 @@ impl GenericArg<'_> {
}
pub fn is_synthetic(&self) -> bool {
matches!(self, GenericArg::Lifetime(lifetime) if lifetime.name.ident() == Ident::empty())
matches!(self, GenericArg::Lifetime(lifetime) if lifetime.ident == Ident::empty())
}
pub fn descr(&self) -> &'static str {
@ -446,7 +448,7 @@ impl GenericBound<'_> {
match self {
GenericBound::Trait(t, ..) => t.span,
GenericBound::LangItemTrait(_, span, ..) => *span,
GenericBound::Outlives(l) => l.span,
GenericBound::Outlives(l) => l.ident.span,
}
}
}
@ -559,6 +561,19 @@ impl<'hir> Generics<'hir> {
}
}
/// If there are generic parameters, return where to introduce a new one.
pub fn span_for_lifetime_suggestion(&self) -> Option<Span> {
if let Some(first) = self.params.first()
&& self.span.contains(first.span)
{
// `fn foo<A>(t: impl Trait)`
// ^ suggest `'a, ` here
Some(first.span.shrink_to_lo())
} else {
None
}
}
/// If there are generic parameters, return where to introduce a new one.
pub fn span_for_param_suggestion(&self) -> Option<Span> {
if self.params.iter().any(|p| self.span.contains(p.span)) {
@ -765,10 +780,7 @@ pub struct WhereRegionPredicate<'hir> {
impl<'hir> WhereRegionPredicate<'hir> {
/// Returns `true` if `param_def_id` matches the `lifetime` of this predicate.
pub fn is_param_bound(&self, param_def_id: LocalDefId) -> bool {
match self.lifetime.name {
LifetimeName::Param(id, _) => id == param_def_id,
_ => false,
}
self.lifetime.res == LifetimeName::Param(param_def_id)
}
}
@ -2688,6 +2700,8 @@ pub struct FnDecl<'hir> {
pub c_variadic: bool,
/// Does the function have an implicit self?
pub implicit_self: ImplicitSelfKind,
/// Is lifetime elision allowed.
pub lifetime_elision_allowed: bool,
}
/// Represents what type of implicit self a function has, if any.
@ -3453,7 +3467,7 @@ impl<'hir> Node<'hir> {
| Node::Variant(Variant { ident, .. })
| Node::Item(Item { ident, .. })
| Node::PathSegment(PathSegment { ident, .. }) => Some(*ident),
Node::Lifetime(lt) => Some(lt.name.ident()),
Node::Lifetime(lt) => Some(lt.ident),
Node::GenericParam(p) => Some(p.name.ident()),
Node::TypeBinding(b) => Some(b.ident),
Node::Param(..)

View File

@ -1109,17 +1109,7 @@ pub fn walk_generic_arg<'v, V: Visitor<'v>>(visitor: &mut V, generic_arg: &'v Ge
pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
visitor.visit_id(lifetime.hir_id);
match lifetime.name {
LifetimeName::Param(_, ParamName::Plain(ident)) => {
visitor.visit_ident(ident);
}
LifetimeName::Param(_, ParamName::Fresh)
| LifetimeName::Param(_, ParamName::Error)
| LifetimeName::Static
| LifetimeName::Error
| LifetimeName::ImplicitObjectLifetimeDefault
| LifetimeName::Infer => {}
}
visitor.visit_ident(lifetime.ident);
}
pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath<'v>, id: HirId) {

View File

@ -5,6 +5,7 @@
#![feature(associated_type_defaults)]
#![feature(closure_track_caller)]
#![feature(const_btree_len)]
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(rustc_attrs)]

View File

@ -241,14 +241,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
None => {
self.re_infer(def, lifetime.span).unwrap_or_else(|| {
self.re_infer(def, lifetime.ident.span).unwrap_or_else(|| {
debug!(?lifetime, "unelided lifetime in signature");
// This indicates an illegal lifetime
// elision. `resolve_lifetime` should have
// reported an error in this case -- but if
// not, let's error out.
tcx.sess.delay_span_bug(lifetime.span, "unelided lifetime in signature");
tcx.sess.delay_span_bug(lifetime.ident.span, "unelided lifetime in signature");
// Supply some dummy value. We don't have an
// `re_error`, annoyingly, so use `'static`.
@ -961,9 +961,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
hir::GenericBound::Outlives(lifetime) => {
let region = self.ast_region_to_region(lifetime, None);
bounds
.region_bounds
.push((ty::Binder::bind_with_vars(region, bound_vars), lifetime.span));
bounds.region_bounds.push((
ty::Binder::bind_with_vars(region, bound_vars),
lifetime.ident.span,
));
}
}
}

View File

@ -398,7 +398,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
Some(rl::Region::Static | rl::Region::EarlyBound(..)) => {}
Some(rl::Region::LateBound(debruijn, _, _)) if debruijn < self.outer_index => {}
Some(rl::Region::LateBound(..) | rl::Region::Free(..)) | None => {
self.has_late_bound_regions = Some(lt.span);
self.has_late_bound_regions = Some(lt.ident.span);
}
}
}

View File

@ -595,7 +595,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
this.visit_poly_trait_ref(bound);
}
});
match lifetime.name {
match lifetime.res {
LifetimeName::ImplicitObjectLifetimeDefault => {
// If the user does not write *anything*, we
// use the object lifetime defaulting
@ -686,7 +686,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
if !parent_id.is_owner() {
struct_span_err!(
self.tcx.sess,
lifetime.span,
lifetime.ident.span,
E0657,
"`impl Trait` can only capture lifetimes bound at the fn or impl level"
)
@ -698,7 +698,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}) = self.tcx.hir().get(parent_id)
{
let mut err = self.tcx.sess.struct_span_err(
lifetime.span,
lifetime.ident.span,
"higher kinded lifetime bounds on nested opaque types are not supported yet",
);
err.span_note(self.tcx.def_span(def_id), "lifetime declared here");
@ -802,9 +802,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
match lifetime_ref.name {
match lifetime_ref.res {
hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static),
hir::LifetimeName::Param(param_def_id, _) => {
hir::LifetimeName::Param(param_def_id) => {
self.resolve_lifetime_ref(param_def_id, lifetime_ref)
}
// If we've already reported an error, just ignore `lifetime_ref`.
@ -912,27 +912,27 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
this.visit_lifetime(lifetime);
walk_list!(this, visit_param_bound, bounds);
if lifetime.name != hir::LifetimeName::Static {
if lifetime.res != hir::LifetimeName::Static {
for bound in bounds {
let hir::GenericBound::Outlives(ref lt) = bound else {
continue;
};
if lt.name != hir::LifetimeName::Static {
if lt.res != hir::LifetimeName::Static {
continue;
}
this.insert_lifetime(lt, Region::Static);
this.tcx
.sess
.struct_span_warn(
lifetime.span,
lifetime.ident.span,
&format!(
"unnecessary lifetime parameter `{}`",
lifetime.name.ident(),
lifetime.ident,
),
)
.help(&format!(
"you can use the `'static` lifetime directly, in place of `{}`",
lifetime.name.ident(),
lifetime.ident,
))
.emit();
}
@ -1043,7 +1043,7 @@ fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> Obje
for bound in bound.bounds {
if let hir::GenericBound::Outlives(ref lifetime) = *bound {
set.insert(lifetime.name.normalize_to_macros_2_0());
set.insert(lifetime.res);
}
}
}
@ -1051,7 +1051,7 @@ fn object_lifetime_default<'tcx>(tcx: TyCtxt<'tcx>, param_def_id: DefId) -> Obje
match set {
Set1::Empty => ObjectLifetimeDefault::Empty,
Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
Set1::One(hir::LifetimeName::Param(param_def_id, _)) => {
Set1::One(hir::LifetimeName::Param(param_def_id)) => {
ObjectLifetimeDefault::Param(param_def_id.to_def_id())
}
_ => ObjectLifetimeDefault::Ambiguous,
@ -1195,42 +1195,50 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// 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::LifetimeName::Param(_) = lifetime_ref.res
&& lifetime_ref.is_anonymous()
&& let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id)
&& !self.tcx.features().anonymous_lifetime_in_impl_trait
{
let mut diag = rustc_session::parse::feature_err(
&self.tcx.sess.parse_sess,
sym::anonymous_lifetime_in_impl_trait,
lifetime_ref.span,
lifetime_ref.ident.span,
"anonymous lifetimes in `impl Trait` are unstable",
);
match self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id) {
Some(generics) => {
if let Some(generics) =
self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id)
{
let new_param_sugg = if let Some(span) =
generics.span_for_lifetime_suggestion()
{
(span, "'a, ".to_owned())
} else {
(generics.span, "<'a>".to_owned())
};
let new_param_sugg_tuple;
let lifetime_sugg = match lifetime_ref.suggestion_position() {
(hir::LifetimeSuggestionPosition::Normal, span) => (span, "'a".to_owned()),
(hir::LifetimeSuggestionPosition::Ampersand, span) => (span, "'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![
lifetime_sugg,
new_param_sugg,
];
new_param_sugg_tuple = match generics.span_for_param_suggestion() {
Some(_) => {
Some((self.tcx.sess.source_map().span_through_char(generics.span, '<').shrink_to_hi(), "'a, ".to_owned()))
},
None => Some((generics.span, "<'a>".to_owned()))
};
let mut multi_sugg_vec = vec![(lifetime_ref.span.shrink_to_hi(), "'a ".to_owned())];
if let Some(new_tuple) = new_param_sugg_tuple{
multi_sugg_vec.push(new_tuple);
}
diag.span_label(lifetime_ref.span, "expected named lifetime parameter");
diag.multipart_suggestion("consider introducing a named lifetime parameter",
multi_sugg_vec,
rustc_errors::Applicability::MaybeIncorrect);
},
None => { }
diag.span_label(
lifetime_ref.ident.span,
"expected named lifetime parameter",
);
diag.multipart_suggestion(
"consider introducing a named lifetime parameter",
suggestions,
rustc_errors::Applicability::MaybeIncorrect,
);
}
diag.emit();
@ -1287,7 +1295,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
} => {
let mut err = self.tcx.sess.struct_span_err(
lifetime_ref.span,
lifetime_ref.ident.span,
"`impl Trait` can only mention lifetimes bound at the fn or impl level",
);
err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
@ -1307,7 +1315,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
self.tcx.sess.delay_span_bug(
lifetime_ref.span,
lifetime_ref.ident.span,
&format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,),
);
}
@ -1625,10 +1633,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) {
debug!(
node = ?self.tcx.hir().node_to_string(lifetime_ref.hir_id),
span = ?self.tcx.sess.source_map().span_to_diagnostic_string(lifetime_ref.span)
);
debug!(span = ?lifetime_ref.ident.span);
self.map.defs.insert(lifetime_ref.hir_id, def);
}
@ -1839,7 +1844,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
}
fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name {
if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
self.regions.insert(def_id);
}
}
@ -1852,7 +1857,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
impl<'v> Visitor<'v> for AllCollector {
fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
if let hir::LifetimeName::Param(def_id, _) = lifetime_ref.name {
if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
self.regions.insert(def_id);
}
}

View File

@ -229,7 +229,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
predicates.extend(region_pred.bounds.iter().map(|bound| {
let (r2, span) = match bound {
hir::GenericBound::Outlives(lt) => {
(<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.span)
(<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.ident.span)
}
_ => bug!(),
};

View File

@ -296,25 +296,35 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
) -> String {
debug!(?path_hir_id);
// If there was already a lifetime among the arguments, just replicate that one.
if let Some(lt) = self.gen_args.args.iter().find_map(|arg| match arg {
hir::GenericArg::Lifetime(lt) => Some(lt),
_ => None,
}) {
return std::iter::repeat(lt.to_string())
.take(num_params_to_take)
.collect::<Vec<_>>()
.join(", ");
}
let mut ret = Vec::new();
let mut ty_id = None;
for (id, node) in self.tcx.hir().parent_iter(path_hir_id) {
debug!(?id);
let params = if let Some(generics) = node.generics() {
generics.params
} else if let hir::Node::Ty(ty) = node
&& let hir::TyKind::BareFn(bare_fn) = ty.kind
{
bare_fn.generic_params
} else {
&[]
};
ret.extend(params.iter().filter_map(|p| {
let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
= p.kind
else { return None };
let hir::ParamName::Plain(name) = p.name else { return None };
Some(name.to_string())
}));
if let hir::Node::Ty(_) = node {
ty_id = Some(id);
}
// Suggest `'_` when in function parameter or elided function return.
if let Some(fn_decl) = node.fn_decl() && let Some(ty_id) = ty_id {
let in_arg = fn_decl.inputs.iter().any(|t| t.hir_id == ty_id);
let in_ret = matches!(fn_decl.output, hir::FnRetTy::Return(ty) if ty.hir_id == ty_id);
if in_arg || (in_ret && fn_decl.lifetime_elision_allowed) {
return std::iter::repeat("'_".to_owned()).take(num_params_to_take).collect::<Vec<_>>().join(", ");
}
}
// Suggest `'static` when in const/static item-like.
if let hir::Node::Item(hir::Item {
kind: hir::ItemKind::Static { .. } | hir::ItemKind::Const { .. },
@ -334,11 +344,29 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
})
| hir::Node::AnonConst(..) = node
{
ret.extend(
std::iter::repeat("'static".to_owned())
.take(num_params_to_take.saturating_sub(ret.len())),
);
return std::iter::repeat("'static".to_owned())
.take(num_params_to_take.saturating_sub(ret.len()))
.collect::<Vec<_>>()
.join(", ");
}
let params = if let Some(generics) = node.generics() {
generics.params
} else if let hir::Node::Ty(ty) = node
&& let hir::TyKind::BareFn(bare_fn) = ty.kind
{
bare_fn.generic_params
} else {
&[]
};
ret.extend(params.iter().filter_map(|p| {
let hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
= p.kind
else { return None };
let hir::ParamName::Plain(name) = p.name else { return None };
Some(name.to_string())
}));
if ret.len() >= num_params_to_take {
return ret[..num_params_to_take].join(", ");
}

View File

@ -2159,7 +2159,7 @@ impl<'a> State<'a> {
}
pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) {
self.print_ident(lifetime.name.ident())
self.print_ident(lifetime.ident)
}
pub fn print_where_clause(&mut self, generics: &hir::Generics<'_>) {

View File

@ -375,7 +375,7 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
return false;
};
if !lifetime_sub.name.is_anonymous() || !lifetime_sup.name.is_anonymous() {
if !lifetime_sub.is_anonymous() || !lifetime_sup.is_anonymous() {
return false;
};
@ -407,20 +407,20 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
let suggestion_param_name =
suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| "'a".to_owned());
debug!(?lifetime_sup.span);
debug!(?lifetime_sub.span);
let make_suggestion = |span: rustc_span::Span| {
if span.is_empty() {
(span, format!("{}, ", suggestion_param_name))
} else if let Ok("&") = self.tcx.sess.source_map().span_to_snippet(span).as_deref()
{
(span.shrink_to_hi(), format!("{} ", suggestion_param_name))
debug!(?lifetime_sup.ident.span);
debug!(?lifetime_sub.ident.span);
let make_suggestion = |ident: Ident| {
let sugg = if ident.name == kw::Empty {
format!("{}, ", suggestion_param_name)
} else if ident.name == kw::UnderscoreLifetime && ident.span.is_empty() {
format!("{} ", suggestion_param_name)
} else {
(span, suggestion_param_name.clone())
}
suggestion_param_name.clone()
};
(ident.span, sugg)
};
let mut suggestions =
vec![make_suggestion(lifetime_sub.span), make_suggestion(lifetime_sup.span)];
vec![make_suggestion(lifetime_sub.ident), make_suggestion(lifetime_sup.ident)];
if introduce_new {
let new_param_suggestion = if let Some(first) =

View File

@ -314,10 +314,10 @@ pub fn suggest_new_region_bound(
.iter()
.filter_map(|arg| match arg {
GenericBound::Outlives(Lifetime {
name: LifetimeName::Static,
span,
res: LifetimeName::Static,
ident,
..
}) => Some(*span),
}) => Some(ident.span),
_ => None,
})
.next()
@ -342,10 +342,10 @@ pub fn suggest_new_region_bound(
.bounds
.iter()
.filter_map(|arg| match arg {
GenericBound::Outlives(Lifetime { name, span, .. })
if name.ident().to_string() == lifetime_name =>
GenericBound::Outlives(Lifetime { ident, .. })
if ident.name.to_string() == lifetime_name =>
{
Some(*span)
Some(ident.span)
}
_ => None,
})
@ -361,8 +361,8 @@ pub fn suggest_new_region_bound(
);
}
}
TyKind::TraitObject(_, lt, _) => match lt.name {
LifetimeName::ImplicitObjectLifetimeDefault => {
TyKind::TraitObject(_, lt, _) => {
if let LifetimeName::ImplicitObjectLifetimeDefault = lt.res {
err.span_suggestion_verbose(
fn_return.span.shrink_to_hi(),
&format!(
@ -374,15 +374,14 @@ pub fn suggest_new_region_bound(
&plus_lt,
Applicability::MaybeIncorrect,
);
}
name if name.ident().to_string() != lifetime_name => {
} else if lt.ident.name.to_string() != lifetime_name {
// With this check we avoid suggesting redundant bounds. This
// would happen if there are nested impl/dyn traits and only
// one of them has the bound we'd suggest already there, like
// in `impl Foo<X = dyn Bar> + '_`.
if let Some(explicit_static) = &explicit_static {
err.span_suggestion_verbose(
lt.span,
lt.ident.span,
&format!("{} the trait object's {}", consider, explicit_static),
&lifetime_name,
Applicability::MaybeIncorrect,
@ -397,8 +396,7 @@ pub fn suggest_new_region_bound(
);
}
}
_ => {}
},
}
_ => {}
}
}
@ -561,7 +559,7 @@ impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
if let TyKind::TraitObject(
poly_trait_refs,
Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. },
Lifetime { res: LifetimeName::ImplicitObjectLifetimeDefault, .. },
_,
) = t.kind
{

View File

@ -272,11 +272,7 @@ fn gen_args(segment: &PathSegment<'_>) -> String {
.args
.iter()
.filter_map(|arg| {
if let GenericArg::Lifetime(lt) = arg {
Some(lt.name.ident().to_string())
} else {
None
}
if let GenericArg::Lifetime(lt) = arg { Some(lt.ident.to_string()) } else { None }
})
.collect::<Vec<_>>();

View File

@ -78,7 +78,7 @@ fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String {
.args
.iter()
.map(|arg| match arg {
GenericArg::Lifetime(lt) => lt.name.ident().to_string(),
GenericArg::Lifetime(lt) => lt.to_string(),
GenericArg::Type(ty) => {
cx.tcx.sess.source_map().span_to_snippet(ty.span).unwrap_or_else(|_| "_".into())
}

View File

@ -1058,7 +1058,7 @@ impl<'hir> Map<'hir> {
Node::Arm(arm) => arm.span,
Node::Block(block) => block.span,
Node::Ctor(..) => self.span_with_body(self.get_parent_node(hir_id)),
Node::Lifetime(lifetime) => lifetime.span,
Node::Lifetime(lifetime) => lifetime.ident.span,
Node::GenericParam(param) => param.span,
Node::Infer(i) => i.span,
Node::Local(local) => local.span,

View File

@ -397,7 +397,7 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
hir::TyKind::TraitObject(
_,
hir::Lifetime {
name:
res:
hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
..
},
@ -421,10 +421,9 @@ pub struct StaticLifetimeVisitor<'tcx>(pub Vec<Span>, pub crate::hir::map::Map<'
impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> {
fn visit_lifetime(&mut self, lt: &'v hir::Lifetime) {
if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static =
lt.name
if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static = lt.res
{
self.0.push(lt.span);
self.0.push(lt.ident.span);
}
}
}

View File

@ -3,7 +3,7 @@ use crate::ty::{EarlyBinder, SubstsRef};
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
use rustc_span::symbol::Symbol;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::Span;
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>(
&self,
tcx: TyCtxt<'tcx>,

View File

@ -208,6 +208,8 @@ pub struct ResolverAstLowering {
/// A small map keeping true kinds of built-in macros that appear to be fn-like on
/// the surface (`macro` items in libcore), but are actually attributes or derives.
pub builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>,
/// List functions and methods for which lifetime elision was successful.
pub lifetime_elision_allowed: FxHashSet<ast::NodeId>,
}
#[derive(Clone, Copy, Debug)]
@ -529,7 +531,7 @@ impl ty::EarlyBoundRegion {
/// Does this early bound region have a name? Early bound regions normally
/// always have names except when using anonymous lifetimes (`'_`).
pub fn has_name(&self) -> bool {
self.name != kw::UnderscoreLifetime
self.name != kw::UnderscoreLifetime && self.name != kw::Empty
}
}

View File

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

View File

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

View File

@ -1838,6 +1838,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let outer_failures = take(&mut self.diagnostic_metadata.current_elision_failures);
let output_rib = if let Ok(res) = elision_lifetime.as_ref() {
self.r.lifetime_elision_allowed.insert(fn_id);
LifetimeRibKind::Elided(*res)
} else {
LifetimeRibKind::ElisionFailure

View File

@ -1036,6 +1036,8 @@ pub struct Resolver<'a> {
/// they are declared in the static array generated by proc_macro_harness.
proc_macros: Vec<NodeId>,
confused_type_with_std_module: FxHashMap<Span, Span>,
/// Whether lifetime elision was successful.
lifetime_elision_allowed: FxHashSet<NodeId>,
effective_visibilities: EffectiveVisibilities,
}
@ -1354,6 +1356,7 @@ impl<'a> Resolver<'a> {
trait_impls: Default::default(),
proc_macros: Default::default(),
confused_type_with_std_module: Default::default(),
lifetime_elision_allowed: Default::default(),
effective_visibilities: Default::default(),
};
@ -1448,6 +1451,7 @@ impl<'a> Resolver<'a> {
def_id_to_node_id: self.def_id_to_node_id,
trait_map: self.trait_map,
builtin_macro_kinds: self.builtin_macro_kinds,
lifetime_elision_allowed: self.lifetime_elision_allowed,
};
ResolverOutputs { definitions, global_ctxt, ast_lowering }
}
@ -1491,6 +1495,7 @@ impl<'a> Resolver<'a> {
def_id_to_node_id: self.def_id_to_node_id.clone(),
trait_map: self.trait_map.clone(),
builtin_macro_kinds: self.builtin_macro_kinds.clone(),
lifetime_elision_allowed: self.lifetime_elision_allowed.clone(),
};
ResolverOutputs { definitions, global_ctxt, ast_lowering }
}

View File

@ -167,7 +167,7 @@ impl<'hir> Sig for hir::Ty<'hir> {
}
hir::TyKind::Rptr(ref lifetime, ref mt) => {
let mut prefix = "&".to_owned();
prefix.push_str(&lifetime.name.ident().to_string());
prefix.push_str(&lifetime.ident.to_string());
prefix.push(' ');
if mt.mutbl.is_mut() {
prefix.push_str("mut ");

View File

@ -182,9 +182,7 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
.collect_referenced_late_bound_regions(&poly_trait_ref)
.into_iter()
.filter_map(|br| match br {
ty::BrNamed(_, name) if name != kw::UnderscoreLifetime => {
Some(GenericParamDef::lifetime(name))
}
ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)),
_ => None,
})
.collect();
@ -208,7 +206,7 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
return lt;
}
}
Lifetime(lifetime.name.ident().name)
Lifetime(lifetime.ident.name)
}
pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant {
@ -233,16 +231,11 @@ pub(crate) fn clean_middle_const<'tcx>(
pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Lifetime> {
match *region {
ty::ReStatic => Some(Lifetime::statik()),
_ if !region.has_name() => None,
ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => {
if name != kw::UnderscoreLifetime { Some(Lifetime(name)) } else { None }
}
ty::ReEarlyBound(ref data) => {
if data.name != kw::UnderscoreLifetime {
Some(Lifetime(data.name))
} else {
None
}
Some(Lifetime(name))
}
ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)),
ty::ReLateBound(..)
| ty::ReFree(..)
| ty::ReVar(..)
@ -400,7 +393,7 @@ fn clean_projection_predicate<'tcx>(
.collect_referenced_late_bound_regions(&pred)
.into_iter()
.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,
})
.collect();
@ -664,7 +657,7 @@ fn clean_ty_generics<'tcx>(
.params
.iter()
.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::Type { synthetic, .. } => {
if param.name == kw::SelfUpper {
@ -1467,8 +1460,11 @@ fn maybe_expand_private_type_alias<'tcx>(
});
if let Some(lt) = lifetime {
let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
let cleaned =
if !lt.is_elided() { clean_lifetime(lt, cx) } else { Lifetime::elided() };
let cleaned = if !lt.is_anonymous() {
clean_lifetime(lt, cx)
} else {
Lifetime::elided()
};
substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned));
}
indices.lifetimes += 1;
@ -1531,16 +1527,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
TyKind::Never => Primitive(PrimitiveType::Never),
TyKind::Ptr(ref m) => RawPointer(m.mutbl, Box::new(clean_ty(m.ty, cx))),
TyKind::Rptr(ref l, ref m) => {
// There are two times a `Fresh` lifetime can be created:
// 1. For `&'_ x`, written by the user. This corresponds to `lower_lifetime` in `rustc_ast_lowering`.
// 2. For `&x` as a parameter to an `async fn`. This corresponds to `elided_ref_lifetime in `rustc_ast_lowering`.
// See #59286 for more information.
// Ideally we would only hide the `'_` for case 2., but I don't know a way to distinguish it.
// Turning `fn f(&'_ self)` into `fn f(&self)` isn't the worst thing in the world, though;
// there's no case where it could cause the function to fail to compile.
let elided =
l.is_elided() || matches!(l.name, LifetimeName::Param(_, ParamName::Fresh));
let lifetime = if elided { None } else { Some(clean_lifetime(*l, cx)) };
let lifetime = if l.is_anonymous() { None } else { Some(clean_lifetime(*l, cx)) };
BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) }
}
TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))),
@ -1915,7 +1902,7 @@ fn clean_generic_args<'tcx>(
.args
.iter()
.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))
}
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),

View File

@ -11,7 +11,7 @@ LL | type Y<'a>;
| ^ --
help: add missing lifetime argument
|
LL | fn f2<'a>(arg: Box<dyn X<Y<'a, 1> = &'a ()>>) {}
LL | fn f2<'a>(arg: Box<dyn X<Y<'_, 1> = &'a ()>>) {}
| +++
error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied

View File

@ -13,8 +13,8 @@ LL | struct S<'a, 'b>(&'a u8, &'b u8);
| ^ -- --
help: add missing lifetime argument
|
LL | S::<'static, 'b>(&0, &0);
| ++++
LL | S::<'static, 'static>(&0, &0);
| +++++++++
error[E0107]: this struct takes 2 lifetime arguments but 3 lifetime arguments were supplied
--> $DIR/constructor-lifetime-args.rs:19:5
@ -45,8 +45,8 @@ LL | enum E<'a, 'b> {
| ^ -- --
help: add missing lifetime argument
|
LL | E::V::<'static, 'b>(&0);
| ++++
LL | E::V::<'static, 'static>(&0);
| +++++++++
error[E0107]: this enum takes 2 lifetime arguments but 3 lifetime arguments were supplied
--> $DIR/constructor-lifetime-args.rs:24:8

View File

@ -11,7 +11,7 @@ LL | type Assoc<'a> where Self: 'a;
| ^^^^^ --
help: add missing lifetime argument
|
LL | fn g(&self) -> Self::Assoc<'a>;
LL | fn g(&self) -> Self::Assoc<'_>;
| ~~~~~~~~~
error[E0107]: missing generics for associated type `Trait::Assoc`
@ -27,7 +27,7 @@ LL | type Assoc<'a> where Self: 'a;
| ^^^^^ --
help: add missing lifetime argument
|
LL | fn g(&self) -> Self::Assoc<'a> {
LL | fn g(&self) -> Self::Assoc<'_> {
| ~~~~~~~~~
error: aborting due to 2 previous errors

View File

@ -36,7 +36,7 @@ LL | type Y<'a>;
| ^ --
help: add missing lifetime argument
|
LL | fn foo<'a>(arg: Box<dyn X<Y('a, 'a) = &'a ()>>) {}
LL | fn foo<'a>(arg: Box<dyn X<Y('_, 'a) = &'a ()>>) {}
| +++
error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied
@ -66,7 +66,7 @@ LL | type Y<'a>;
| ^ --
help: add missing lifetime argument
|
LL | fn bar<'a>(arg: Box<dyn X<Y('a) = ()>>) {}
LL | fn bar<'a>(arg: Box<dyn X<Y('_) = ()>>) {}
| ++
error: aborting due to 6 previous errors

View File

@ -11,7 +11,7 @@ LL | type Item<'a>;
| ^^^^ --
help: add missing lifetime argument
|
LL | fn next(&mut self) -> Option<Self::Item<'a>>;
LL | fn next(&mut self) -> Option<Self::Item<'_>>;
| ~~~~~~~~
error: aborting due to previous error

View File

@ -11,7 +11,7 @@ LL | type Y<'a, 'b>;
| ^ -- --
help: add missing lifetime arguments
|
LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'c, 'd> = (&'c u32, &'d u32)>>) {}
LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'_, '_> = (&'c u32, &'d u32)>>) {}
| ~~~~~~~~~
error[E0107]: this struct takes 3 lifetime arguments but 2 lifetime arguments were supplied
@ -47,7 +47,7 @@ LL | struct Foo<'a, 'b, 'c> {
| ^^^ -- -- --
help: add missing lifetime arguments
|
LL | fn f<'a>(_arg: Foo<'a, 'b, 'c>) {}
LL | fn f<'a>(_arg: Foo<'a, 'a, 'a>) {}
| ++++++++
error: aborting due to 3 previous errors

View File

@ -11,7 +11,7 @@ LL | type Y<'a>;
| ^ --
help: add missing lifetime argument
|
LL | fn f2<'a>(arg : Box<dyn X<Y<'a, 1> = &'a ()>>) {}
LL | fn f2<'a>(arg : Box<dyn X<Y<'_, 1> = &'a ()>>) {}
| +++
error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied

View File

@ -812,8 +812,8 @@ LL | trait GenericLifetimeLifetimeAT<'a, 'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ -- --
help: add missing lifetime argument
|
LL | type B = Box<dyn GenericLifetimeLifetimeAT<'static, 'b, AssocTy=()>>;
| ++++
LL | type B = Box<dyn GenericLifetimeLifetimeAT<'static, 'static, AssocTy=()>>;
| +++++++++
error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:287:26
@ -846,8 +846,8 @@ LL | trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- --
help: add missing lifetime argument
|
LL | type B = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'b, AssocTy=()>>;
| ++++
LL | type B = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'static, AssocTy=()>>;
| +++++++++
error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:294:26
@ -880,8 +880,8 @@ LL | trait GenericLifetimeLifetimeTypeAT<'a, 'b, A> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- --
help: add missing lifetime argument
|
LL | type C = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'b, (), AssocTy=()>>;
| ++++
LL | type C = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'static, (), AssocTy=()>>;
| +++++++++
error[E0107]: missing generics for struct `HashMap`
--> $DIR/wrong-number-of-args.rs:310:18

View File

@ -13,8 +13,8 @@ LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
| ^^^^^ -- --
help: add missing lifetime argument
|
LL | S.early::<'static, 'b>();
| ++++
LL | S.early::<'static, 'static>();
| +++++++++
error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
--> $DIR/method-call-lifetime-args-fail.rs:18:7
@ -213,8 +213,8 @@ LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
| ^^^^^ -- --
help: add missing lifetime argument
|
LL | S::early::<'static, 'b>(S);
| ++++
LL | S::early::<'static, 'static>(S);
| +++++++++
error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
--> $DIR/method-call-lifetime-args-fail.rs:65:8

View File

@ -119,7 +119,7 @@ hir-stats HIR STATS
hir-stats Name Accumulated Size Count Item Size
hir-stats ----------------------------------------------------------------
hir-stats ForeignItemRef 24 ( 0.3%) 1 24
hir-stats Lifetime 32 ( 0.3%) 1 32
hir-stats Lifetime 24 ( 0.3%) 1 24
hir-stats Mod 32 ( 0.3%) 1 32
hir-stats ExprField 40 ( 0.4%) 1 40
hir-stats TraitItemRef 56 ( 0.6%) 2 28
@ -152,7 +152,7 @@ hir-stats - Struct 72 ( 0.8%) 1
hir-stats - Binding 216 ( 2.4%) 3
hir-stats GenericParam 400 ( 4.4%) 5 80
hir-stats Generics 560 ( 6.1%) 10 56
hir-stats Ty 720 ( 7.8%) 15 48
hir-stats Ty 720 ( 7.9%) 15 48
hir-stats - Ptr 48 ( 0.5%) 1
hir-stats - Rptr 48 ( 0.5%) 1
hir-stats - Path 624 ( 6.8%) 13
@ -171,8 +171,8 @@ hir-stats - ForeignMod 80 ( 0.9%) 1
hir-stats - Impl 80 ( 0.9%) 1
hir-stats - Fn 160 ( 1.7%) 2
hir-stats - Use 400 ( 4.4%) 5
hir-stats Path 1_280 (13.9%) 32 40
hir-stats Path 1_280 (14.0%) 32 40
hir-stats PathSegment 1_920 (20.9%) 40 48
hir-stats ----------------------------------------------------------------
hir-stats Total 9_176
hir-stats Total 9_168
hir-stats

View File

@ -2,20 +2,62 @@
// 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
mod elided {
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
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.
// 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
// 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 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() {}

View File

@ -1,52 +1,172 @@
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() }
| ^^ expected named lifetime parameter
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(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
--> $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() }
| ^^ expected named lifetime parameter
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(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
--> $DIR/impl-trait-missing-lifetime-gated.rs:5:31
--> $DIR/impl-trait-missing-lifetime-gated.rs:6:35
|
LL | fn f(_: impl Iterator<Item = &'_ ()>) {}
| ^^ expected named lifetime parameter
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 ()>) {}
| ++++ ++
LL | fn f<'a>(_: impl Iterator<Item = &'a ()>) {}
| ++++ ++
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() }
| ^^ expected named lifetime parameter
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>(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.
For more information about an error, try `rustc --explain E0106`.

View File

@ -166,8 +166,8 @@ LL | pub union Qux<'t, 'k, I> {
| ^^^ -- --
help: add missing lifetime argument
|
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
| ++++
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:39:44
@ -184,8 +184,8 @@ LL | pub union Qux<'t, 'k, I> {
| ^^^ -- --
help: add missing lifetime argument
|
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
| ++++
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:39:44
@ -202,8 +202,8 @@ LL | pub union Qux<'t, 'k, I> {
| ^^^ -- --
help: add missing lifetime argument
|
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
| ++++
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:39:44
@ -256,8 +256,8 @@ LL | trait Tar<'t, 'k, I> {}
| ^^^ -- --
help: add missing lifetime argument
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
| ++++
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:47:45
@ -274,8 +274,8 @@ LL | trait Tar<'t, 'k, I> {}
| ^^^ -- --
help: add missing lifetime argument
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
| ++++
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:47:45
@ -292,8 +292,8 @@ LL | trait Tar<'t, 'k, I> {}
| ^^^ -- --
help: add missing lifetime argument
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'k, i32>>>>> = RefCell::new(HashMap::new());
| ++++
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:47:45

View File

@ -10,8 +10,8 @@ use rustc_hir::lang_items;
use rustc_hir::FnRetTy::Return;
use rustc_hir::{
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin, TraitFn, TraitItem,
TraitItemKind, Ty, TyKind, WherePredicate,
ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, PolyTraitRef, PredicateOrigin, TraitFn,
TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter as middle_nested_filter;
@ -180,7 +180,7 @@ fn check_fn_inner<'tcx>(
_ => None,
});
for bound in lifetimes {
if bound.name != LifetimeName::Static && !bound.is_elided() {
if !bound.is_static() && !bound.is_elided() {
return;
}
}
@ -414,17 +414,13 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
fn record(&mut self, lifetime: &Option<Lifetime>) {
if let Some(ref lt) = *lifetime {
if lt.name == LifetimeName::Static {
if lt.is_static() {
self.lts.push(RefLt::Static);
} else if let LifetimeName::Param(_, ParamName::Fresh) = lt.name {
} else if lt.is_anonymous() {
// Fresh lifetimes generated should be ignored.
self.lts.push(RefLt::Unnamed);
} else if lt.is_elided() {
self.lts.push(RefLt::Unnamed);
} else if let LifetimeName::Param(def_id, _) = lt.name {
} else if let LifetimeName::Param(def_id) = lt.res {
self.lts.push(RefLt::Named(def_id));
} else {
self.lts.push(RefLt::Unnamed);
}
} else {
self.lts.push(RefLt::Unnamed);
@ -472,7 +468,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
walk_item(self, item);
self.lts.truncate(len);
self.lts.extend(bounds.iter().filter_map(|bound| match bound {
GenericArg::Lifetime(l) => Some(if let LifetimeName::Param(def_id, _) = l.name {
GenericArg::Lifetime(l) => Some(if let LifetimeName::Param(def_id) = l.res {
RefLt::Named(def_id)
} else {
RefLt::Unnamed
@ -498,10 +494,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
}
fn visit_generic_arg(&mut self, generic_arg: &'tcx GenericArg<'tcx>) {
if let GenericArg::Lifetime(l) = generic_arg
&& let LifetimeName::Param(def_id, _) = l.name
{
self.lifetime_generic_arg_spans.entry(def_id).or_insert(l.span);
if let GenericArg::Lifetime(l) = generic_arg && let LifetimeName::Param(def_id) = l.res {
self.lifetime_generic_arg_spans.entry(def_id).or_insert(l.ident.span);
}
// Replace with `walk_generic_arg` if/when https://github.com/rust-lang/rust/pull/103692 lands.
// walk_generic_arg(self, generic_arg);
@ -577,7 +571,7 @@ where
// for lifetimes as parameters of generics
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
self.map.remove(&lifetime.name.ident().name);
self.map.remove(&lifetime.ident.name);
}
fn visit_generic_param(&mut self, param: &'tcx GenericParam<'_>) {
@ -601,7 +595,9 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>,
.params
.iter()
.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,
})
.collect();
@ -626,7 +622,9 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
.params
.iter()
.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,
})
.collect();
@ -653,7 +651,7 @@ struct BodyLifetimeChecker {
impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker {
// for lifetimes as parameters of generics
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
if lifetime.name.ident().name != kw::UnderscoreLifetime && lifetime.name.ident().name != kw::StaticLifetime {
if !lifetime.is_anonymous() && lifetime.ident.name != kw::StaticLifetime {
self.lifetimes_used_in_body = true;
}
}

View File

@ -118,7 +118,7 @@ fn future_trait_ref<'tcx>(
.iter()
.filter_map(|bound| {
if let GenericArg::Lifetime(lt) = bound {
Some(lt.name)
Some(lt.res)
} else {
None
}
@ -153,7 +153,7 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
.iter()
.filter_map(|ty| {
if let TyKind::Rptr(lt, _) = ty.kind {
Some(lt.name)
Some(lt.res)
} else {
None
}

View File

@ -12,8 +12,8 @@ use rustc_hir::hir_id::HirIdMap;
use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::{
self as hir, AnonConst, BinOpKind, BindingAnnotation, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg,
ImplItemKind, ItemKind, Lifetime, LifetimeName, Mutability, Node, Param, ParamName, PatKind, QPath, TraitFn,
TraitItem, TraitItemKind, TyKind, Unsafety,
ImplItemKind, ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, TraitFn, TraitItem, TraitItemKind,
TyKind, Unsafety,
};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{Obligation, ObligationCause};
@ -343,21 +343,16 @@ impl PtrArg<'_> {
}
struct RefPrefix {
lt: LifetimeName,
lt: Lifetime,
mutability: Mutability,
}
impl fmt::Display for RefPrefix {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use fmt::Write;
f.write_char('&')?;
match self.lt {
LifetimeName::Param(_, ParamName::Plain(name)) => {
name.fmt(f)?;
f.write_char(' ')?;
},
LifetimeName::Infer => f.write_str("'_ ")?,
LifetimeName::Static => f.write_str("'static ")?,
_ => (),
if !self.lt.is_anonymous() {
self.lt.ident.fmt(f)?;
f.write_char(' ')?;
}
f.write_str(self.mutability.prefix_str())
}
@ -495,7 +490,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
ty_name: name.ident.name,
method_renames,
ref_prefix: RefPrefix {
lt: lt.name,
lt: lt.clone(),
mutability,
},
deref_ty,

View File

@ -31,10 +31,10 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
return false;
}
let ltopt = if lt.name.is_anonymous() {
let ltopt = if lt.is_anonymous() {
String::new()
} else {
format!("{} ", lt.name.ident().as_str())
format!("{} ", lt.ident.as_str())
};
if mut_ty.mutbl == Mutability::Mut {

View File

@ -7,7 +7,7 @@ use rustc_hir::def::Res;
use rustc_hir::HirIdMap;
use rustc_hir::{
ArrayLen, BinOpKind, BindingAnnotation, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg,
GenericArgs, Guard, HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path,
GenericArgs, Guard, HirId, InlineAsmOperand, Let, Lifetime, LifetimeName, Pat, PatField, PatKind, Path,
PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
};
use rustc_lexer::{tokenize, TokenKind};
@ -337,7 +337,7 @@ impl HirEqInterExpr<'_, '_, '_> {
}
fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool {
left.name == right.name
left.res == right.res
}
fn eq_pat_field(&mut self, left: &PatField<'_>, right: &PatField<'_>) -> bool {
@ -925,16 +925,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
}
pub fn hash_lifetime(&mut self, lifetime: &Lifetime) {
std::mem::discriminant(&lifetime.name).hash(&mut self.s);
if let LifetimeName::Param(param_id, ref name) = lifetime.name {
std::mem::discriminant(name).hash(&mut self.s);
lifetime.ident.name.hash(&mut self.s);
std::mem::discriminant(&lifetime.res).hash(&mut self.s);
if let LifetimeName::Param(param_id) = lifetime.res {
param_id.hash(&mut self.s);
match name {
ParamName::Plain(ref ident) => {
ident.name.hash(&mut self.s);
},
ParamName::Fresh | ParamName::Error => {},
}
}
}