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:
commit
454784afba
@ -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),
|
||||
|
@ -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>) {
|
||||
|
@ -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,
|
||||
|
@ -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(®ion);
|
||||
@ -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(¶m.ty, &ImplTraitContext::Universal)
|
||||
let itctx = if kind.param_impl_trait_allowed() {
|
||||
ImplTraitContext::Universal
|
||||
} else {
|
||||
self.lower_ty_direct(
|
||||
¶m.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(¶m.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)
|
||||
|
@ -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)
|
||||
}),
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(..)
|
||||
|
@ -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) {
|
||||
|
@ -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)]
|
||||
|
@ -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,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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!(),
|
||||
};
|
||||
|
@ -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(", ");
|
||||
}
|
||||
|
@ -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<'_>) {
|
||||
|
@ -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) =
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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<_>>();
|
||||
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>,
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -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 ");
|
||||
|
@ -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()),
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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 => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user