mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 04:08:40 +00:00
Auto merge of #98279 - cjgillot:all-fresh-nofn, r=petrochenkov
Create elided lifetime parameters for function-like types Split from https://github.com/rust-lang/rust/pull/97720 This PR refactor lifetime generic parameters in bare function types and parenthesized traits to introduce the additional required lifetimes as fresh parameters in a `for<>` bound. This PR does the same to lifetimes appearing in closure signatures, and as-if introducing `for<>` bounds on closures (without the associated change in semantics). r? `@petrochenkov`
This commit is contained in:
commit
10f4ce324b
@ -165,6 +165,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
if let Async::Yes { closure_id, .. } = asyncness {
|
if let Async::Yes { closure_id, .. } = asyncness {
|
||||||
self.lower_expr_async_closure(
|
self.lower_expr_async_closure(
|
||||||
capture_clause,
|
capture_clause,
|
||||||
|
e.id,
|
||||||
closure_id,
|
closure_id,
|
||||||
decl,
|
decl,
|
||||||
body,
|
body,
|
||||||
@ -173,6 +174,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
} else {
|
} else {
|
||||||
self.lower_expr_closure(
|
self.lower_expr_closure(
|
||||||
capture_clause,
|
capture_clause,
|
||||||
|
e.id,
|
||||||
movability,
|
movability,
|
||||||
decl,
|
decl,
|
||||||
body,
|
body,
|
||||||
@ -604,6 +606,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
// `static |_task_context| -> <ret_ty> { body }`:
|
// `static |_task_context| -> <ret_ty> { body }`:
|
||||||
let generator_kind = hir::ExprKind::Closure {
|
let generator_kind = hir::ExprKind::Closure {
|
||||||
capture_clause,
|
capture_clause,
|
||||||
|
bound_generic_params: &[],
|
||||||
fn_decl,
|
fn_decl,
|
||||||
body,
|
body,
|
||||||
fn_decl_span: self.lower_span(span),
|
fn_decl_span: self.lower_span(span),
|
||||||
@ -828,6 +831,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
fn lower_expr_closure(
|
fn lower_expr_closure(
|
||||||
&mut self,
|
&mut self,
|
||||||
capture_clause: CaptureBy,
|
capture_clause: CaptureBy,
|
||||||
|
closure_id: NodeId,
|
||||||
movability: Movability,
|
movability: Movability,
|
||||||
decl: &FnDecl,
|
decl: &FnDecl,
|
||||||
body: &Expr,
|
body: &Expr,
|
||||||
@ -848,16 +852,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
(body_id, generator_option)
|
(body_id, generator_option)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Lower outside new scope to preserve `is_in_loop_condition`.
|
self.with_lifetime_binder(closure_id, &[], |this, bound_generic_params| {
|
||||||
let fn_decl = self.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
|
// Lower outside new scope to preserve `is_in_loop_condition`.
|
||||||
|
let fn_decl = this.lower_fn_decl(decl, None, FnDeclKind::Closure, None);
|
||||||
|
|
||||||
hir::ExprKind::Closure {
|
hir::ExprKind::Closure {
|
||||||
capture_clause,
|
capture_clause,
|
||||||
fn_decl,
|
bound_generic_params,
|
||||||
body,
|
fn_decl,
|
||||||
fn_decl_span: self.lower_span(fn_decl_span),
|
body,
|
||||||
movability: generator_option,
|
fn_decl_span: this.lower_span(fn_decl_span),
|
||||||
}
|
movability: generator_option,
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generator_movability_for_fn(
|
fn generator_movability_for_fn(
|
||||||
@ -897,6 +904,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
capture_clause: CaptureBy,
|
capture_clause: CaptureBy,
|
||||||
closure_id: NodeId,
|
closure_id: NodeId,
|
||||||
|
inner_closure_id: NodeId,
|
||||||
decl: &FnDecl,
|
decl: &FnDecl,
|
||||||
body: &Expr,
|
body: &Expr,
|
||||||
fn_decl_span: Span,
|
fn_decl_span: Span,
|
||||||
@ -927,7 +935,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
if let FnRetTy::Ty(ty) = &decl.output { Some(ty.clone()) } else { None };
|
if let FnRetTy::Ty(ty) = &decl.output { Some(ty.clone()) } else { None };
|
||||||
let async_body = this.make_async_expr(
|
let async_body = this.make_async_expr(
|
||||||
capture_clause,
|
capture_clause,
|
||||||
closure_id,
|
inner_closure_id,
|
||||||
async_ret_ty,
|
async_ret_ty,
|
||||||
body.span,
|
body.span,
|
||||||
hir::AsyncGeneratorKind::Closure,
|
hir::AsyncGeneratorKind::Closure,
|
||||||
@ -938,18 +946,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
body_id
|
body_id
|
||||||
});
|
});
|
||||||
|
|
||||||
// We need to lower the declaration outside the new scope, because we
|
self.with_lifetime_binder(closure_id, &[], |this, bound_generic_params| {
|
||||||
// have to conserve the state of being inside a loop condition for the
|
// We need to lower the declaration outside the new scope, because we
|
||||||
// closure argument types.
|
// have to conserve the state of being inside a loop condition for the
|
||||||
let fn_decl = self.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
|
// closure argument types.
|
||||||
|
let fn_decl = this.lower_fn_decl(&outer_decl, None, FnDeclKind::Closure, None);
|
||||||
|
|
||||||
hir::ExprKind::Closure {
|
hir::ExprKind::Closure {
|
||||||
capture_clause,
|
capture_clause,
|
||||||
fn_decl,
|
bound_generic_params,
|
||||||
body,
|
fn_decl,
|
||||||
fn_decl_span: self.lower_span(fn_decl_span),
|
body,
|
||||||
movability: None,
|
fn_decl_span: this.lower_span(fn_decl_span),
|
||||||
}
|
movability: None,
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Destructure the LHS of complex assignments.
|
/// Destructure the LHS of complex assignments.
|
||||||
|
@ -1386,16 +1386,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
|
|
||||||
let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> =
|
let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> =
|
||||||
self.lower_generic_params_mut(&generics.params).collect();
|
self.lower_generic_params_mut(&generics.params).collect();
|
||||||
|
|
||||||
|
// Introduce extra lifetimes if late resolution tells us to.
|
||||||
|
let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id);
|
||||||
|
params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
|
||||||
|
self.lifetime_res_to_generic_param(ident, node_id, res)
|
||||||
|
}));
|
||||||
|
|
||||||
let has_where_clause_predicates = !generics.where_clause.predicates.is_empty();
|
let has_where_clause_predicates = !generics.where_clause.predicates.is_empty();
|
||||||
let where_clause_span = self.lower_span(generics.where_clause.span);
|
let where_clause_span = self.lower_span(generics.where_clause.span);
|
||||||
let span = self.lower_span(generics.span);
|
let span = self.lower_span(generics.span);
|
||||||
let res = f(self);
|
let res = f(self);
|
||||||
|
|
||||||
let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id);
|
|
||||||
let impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);
|
let impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);
|
||||||
params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
|
|
||||||
self.lifetime_res_to_generic_param(ident, node_id, res)
|
|
||||||
}));
|
|
||||||
params.extend(impl_trait_defs.into_iter());
|
params.extend(impl_trait_defs.into_iter());
|
||||||
|
|
||||||
let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
|
let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
|
||||||
|
@ -223,6 +223,12 @@ impl ResolverAstLoweringExt for ResolverAstLowering {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain the list of lifetimes parameters to add to an item.
|
/// Obtain the list of lifetimes parameters to add to an item.
|
||||||
|
///
|
||||||
|
/// Extra lifetime parameters should only be added in places that can appear
|
||||||
|
/// as a `binder` in `LifetimeRes`.
|
||||||
|
///
|
||||||
|
/// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring
|
||||||
|
/// should appear at the enclosing `PolyTraitRef`.
|
||||||
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> {
|
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> {
|
||||||
self.extra_lifetime_params_map.remove(&id).unwrap_or_default()
|
self.extra_lifetime_params_map.remove(&id).unwrap_or_default()
|
||||||
}
|
}
|
||||||
@ -721,6 +727,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a lifetime into a new generic parameter.
|
/// Converts a lifetime into a new generic parameter.
|
||||||
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
fn lifetime_res_to_generic_param(
|
fn lifetime_res_to_generic_param(
|
||||||
&mut self,
|
&mut self,
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
@ -731,7 +738,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
LifetimeRes::Param { .. } => {
|
LifetimeRes::Param { .. } => {
|
||||||
(hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit)
|
(hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit)
|
||||||
}
|
}
|
||||||
LifetimeRes::Fresh { .. } => (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided),
|
LifetimeRes::Fresh { param, .. } => {
|
||||||
|
// Late resolution delegates to us the creation of the `LocalDefId`.
|
||||||
|
let _def_id = self.create_def(
|
||||||
|
self.current_hir_id_owner,
|
||||||
|
param,
|
||||||
|
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
|
||||||
|
);
|
||||||
|
debug!(?_def_id);
|
||||||
|
|
||||||
|
(hir::ParamName::Fresh, hir::LifetimeParamKind::Elided)
|
||||||
|
}
|
||||||
LifetimeRes::Static | LifetimeRes::Error => return None,
|
LifetimeRes::Static | LifetimeRes::Error => return None,
|
||||||
res => panic!(
|
res => panic!(
|
||||||
"Unexpected lifetime resolution {:?} for {:?} at {:?}",
|
"Unexpected lifetime resolution {:?} for {:?} at {:?}",
|
||||||
@ -777,11 +794,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
/// Register a binder to be ignored for lifetime capture.
|
/// Register a binder to be ignored for lifetime capture.
|
||||||
#[tracing::instrument(level = "debug", skip(self, f))]
|
#[tracing::instrument(level = "debug", skip(self, f))]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_lifetime_binder<T>(&mut self, binder: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
|
fn with_lifetime_binder<T>(
|
||||||
|
&mut self,
|
||||||
|
binder: NodeId,
|
||||||
|
generic_params: &[GenericParam],
|
||||||
|
f: impl FnOnce(&mut Self, &'hir [hir::GenericParam<'hir>]) -> T,
|
||||||
|
) -> T {
|
||||||
|
let mut generic_params: Vec<_> = self.lower_generic_params_mut(generic_params).collect();
|
||||||
|
let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder);
|
||||||
|
debug!(?extra_lifetimes);
|
||||||
|
generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
|
||||||
|
self.lifetime_res_to_generic_param(ident, node_id, res)
|
||||||
|
}));
|
||||||
|
let generic_params = self.arena.alloc_from_iter(generic_params);
|
||||||
|
debug!(?generic_params);
|
||||||
|
|
||||||
if let Some(ctxt) = &mut self.captured_lifetimes {
|
if let Some(ctxt) = &mut self.captured_lifetimes {
|
||||||
ctxt.binders_to_ignore.insert(binder);
|
ctxt.binders_to_ignore.insert(binder);
|
||||||
}
|
}
|
||||||
let ret = f(self);
|
let ret = f(self, generic_params);
|
||||||
if let Some(ctxt) = &mut self.captured_lifetimes {
|
if let Some(ctxt) = &mut self.captured_lifetimes {
|
||||||
ctxt.binders_to_ignore.remove(&binder);
|
ctxt.binders_to_ignore.remove(&binder);
|
||||||
}
|
}
|
||||||
@ -1178,15 +1209,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
let lifetime = self.lower_lifetime(®ion);
|
let lifetime = self.lower_lifetime(®ion);
|
||||||
hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
|
hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
|
||||||
}
|
}
|
||||||
TyKind::BareFn(ref f) => self.with_lifetime_binder(t.id, |this| {
|
TyKind::BareFn(ref f) => {
|
||||||
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
|
self.with_lifetime_binder(t.id, &f.generic_params, |this, generic_params| {
|
||||||
generic_params: this.lower_generic_params(&f.generic_params),
|
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
|
||||||
unsafety: this.lower_unsafety(f.unsafety),
|
generic_params,
|
||||||
abi: this.lower_extern(f.ext),
|
unsafety: this.lower_unsafety(f.unsafety),
|
||||||
decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
|
abi: this.lower_extern(f.ext),
|
||||||
param_names: this.lower_fn_params_to_names(&f.decl),
|
decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
|
||||||
}))
|
param_names: this.lower_fn_params_to_names(&f.decl),
|
||||||
}),
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
TyKind::Never => hir::TyKind::Never,
|
TyKind::Never => hir::TyKind::Never,
|
||||||
TyKind::Tup(ref tys) => hir::TyKind::Tup(
|
TyKind::Tup(ref tys) => hir::TyKind::Tup(
|
||||||
self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))),
|
self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))),
|
||||||
@ -1814,8 +1847,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
hir::LifetimeName::Param(param, p_name)
|
hir::LifetimeName::Param(param, p_name)
|
||||||
}
|
}
|
||||||
LifetimeRes::Fresh { mut param, binder } => {
|
LifetimeRes::Fresh { param, binder } => {
|
||||||
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
|
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
|
||||||
|
let mut param = self.local_def_id(param);
|
||||||
if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() {
|
if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() {
|
||||||
if !captured_lifetimes.binders_to_ignore.contains(&binder) {
|
if !captured_lifetimes.binders_to_ignore.contains(&binder) {
|
||||||
match captured_lifetimes.captures.entry(param) {
|
match captured_lifetimes.captures.entry(param) {
|
||||||
@ -1952,13 +1986,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
p: &PolyTraitRef,
|
p: &PolyTraitRef,
|
||||||
itctx: ImplTraitContext,
|
itctx: ImplTraitContext,
|
||||||
) -> hir::PolyTraitRef<'hir> {
|
) -> hir::PolyTraitRef<'hir> {
|
||||||
let bound_generic_params = self.lower_generic_params(&p.bound_generic_params);
|
self.with_lifetime_binder(
|
||||||
|
p.trait_ref.ref_id,
|
||||||
let trait_ref = self.with_lifetime_binder(p.trait_ref.ref_id, |this| {
|
&p.bound_generic_params,
|
||||||
this.lower_trait_ref(&p.trait_ref, itctx)
|
|this, bound_generic_params| {
|
||||||
});
|
let trait_ref = this.lower_trait_ref(&p.trait_ref, itctx);
|
||||||
|
hir::PolyTraitRef { bound_generic_params, trait_ref, span: this.lower_span(p.span) }
|
||||||
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> {
|
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> {
|
||||||
|
@ -191,9 +191,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
|
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
|
||||||
}
|
}
|
||||||
GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
|
GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
|
||||||
ParenthesizedGenericArgs::Ok => {
|
ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
|
||||||
self.lower_parenthesized_parameter_data(segment.id, data)
|
|
||||||
}
|
|
||||||
ParenthesizedGenericArgs::Err => {
|
ParenthesizedGenericArgs::Err => {
|
||||||
let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
|
let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
|
||||||
err.span_label(data.span, "only `Fn` traits may use parentheses");
|
err.span_label(data.span, "only `Fn` traits may use parentheses");
|
||||||
@ -351,7 +349,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
|
|
||||||
fn lower_parenthesized_parameter_data(
|
fn lower_parenthesized_parameter_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: NodeId,
|
|
||||||
data: &ParenthesizedArgs,
|
data: &ParenthesizedArgs,
|
||||||
) -> (GenericArgsCtor<'hir>, bool) {
|
) -> (GenericArgsCtor<'hir>, bool) {
|
||||||
// Switch to `PassThrough` mode for anonymous lifetimes; this
|
// Switch to `PassThrough` mode for anonymous lifetimes; this
|
||||||
@ -359,31 +356,27 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
// a hidden lifetime parameter. This is needed for backwards
|
// a hidden lifetime parameter. This is needed for backwards
|
||||||
// compatibility, even in contexts like an impl header where
|
// compatibility, even in contexts like an impl header where
|
||||||
// we generally don't permit such things (see #51008).
|
// we generally don't permit such things (see #51008).
|
||||||
self.with_lifetime_binder(id, |this| {
|
let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
|
||||||
let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
|
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| {
|
||||||
let inputs = this.arena.alloc_from_iter(inputs.iter().map(|ty| {
|
self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam))
|
||||||
this.lower_ty_direct(
|
}));
|
||||||
ty,
|
let output_ty = match output {
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam),
|
FnRetTy::Ty(ty) => {
|
||||||
)
|
self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
|
||||||
}));
|
}
|
||||||
let output_ty = match output {
|
FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])),
|
||||||
FnRetTy::Ty(ty) => this
|
};
|
||||||
.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)),
|
let args = smallvec![GenericArg::Type(self.ty_tup(*inputs_span, inputs))];
|
||||||
FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(*span, &[])),
|
let binding = self.output_ty_binding(output_ty.span, output_ty);
|
||||||
};
|
(
|
||||||
let args = smallvec![GenericArg::Type(this.ty_tup(*inputs_span, inputs))];
|
GenericArgsCtor {
|
||||||
let binding = this.output_ty_binding(output_ty.span, output_ty);
|
args,
|
||||||
(
|
bindings: arena_vec![self; binding],
|
||||||
GenericArgsCtor {
|
parenthesized: true,
|
||||||
args,
|
span: data.inputs_span,
|
||||||
bindings: arena_vec![this; binding],
|
},
|
||||||
parenthesized: true,
|
false,
|
||||||
span: data.inputs_span,
|
)
|
||||||
},
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An associated type binding `Output = $ty`.
|
/// An associated type binding `Output = $ty`.
|
||||||
|
@ -254,6 +254,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||||||
/// *user* has a name for. In that case, we'll be able to map
|
/// *user* has a name for. In that case, we'll be able to map
|
||||||
/// `fr` to a `Region<'tcx>`, and that region will be one of
|
/// `fr` to a `Region<'tcx>`, and that region will be one of
|
||||||
/// named variants.
|
/// named variants.
|
||||||
|
#[tracing::instrument(level = "trace", skip(self))]
|
||||||
fn give_name_from_error_region(&self, fr: RegionVid) -> Option<RegionName> {
|
fn give_name_from_error_region(&self, fr: RegionVid) -> Option<RegionName> {
|
||||||
let error_region = self.to_error_region(fr)?;
|
let error_region = self.to_error_region(fr)?;
|
||||||
|
|
||||||
@ -290,7 +291,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||||||
if free_region.bound_region.is_named() {
|
if free_region.bound_region.is_named() {
|
||||||
// A named region that is actually named.
|
// A named region that is actually named.
|
||||||
Some(RegionName { name, source: RegionNameSource::NamedFreeRegion(span) })
|
Some(RegionName { name, source: RegionNameSource::NamedFreeRegion(span) })
|
||||||
} else {
|
} else if let hir::IsAsync::Async = tcx.asyncness(self.mir_hir_id().owner) {
|
||||||
// If we spuriously thought that the region is named, we should let the
|
// If we spuriously thought that the region is named, we should let the
|
||||||
// system generate a true name for error messages. Currently this can
|
// system generate a true name for error messages. Currently this can
|
||||||
// happen if we have an elided name in an async fn for example: the
|
// happen if we have an elided name in an async fn for example: the
|
||||||
@ -301,6 +302,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||||||
name,
|
name,
|
||||||
source: RegionNameSource::AnonRegionFromAsyncFn(span),
|
source: RegionNameSource::AnonRegionFromAsyncFn(span),
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,6 +365,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||||||
/// | fn foo(x: &u32) { .. }
|
/// | fn foo(x: &u32) { .. }
|
||||||
/// ------- fully elaborated type of `x` is `&'1 u32`
|
/// ------- fully elaborated type of `x` is `&'1 u32`
|
||||||
/// ```
|
/// ```
|
||||||
|
#[tracing::instrument(level = "trace", skip(self))]
|
||||||
fn give_name_if_anonymous_region_appears_in_arguments(
|
fn give_name_if_anonymous_region_appears_in_arguments(
|
||||||
&self,
|
&self,
|
||||||
fr: RegionVid,
|
fr: RegionVid,
|
||||||
@ -651,6 +655,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||||||
/// | let x = Some(&22);
|
/// | let x = Some(&22);
|
||||||
/// - fully elaborated type of `x` is `Option<&'1 u32>`
|
/// - fully elaborated type of `x` is `Option<&'1 u32>`
|
||||||
/// ```
|
/// ```
|
||||||
|
#[tracing::instrument(level = "trace", skip(self))]
|
||||||
fn give_name_if_anonymous_region_appears_in_upvars(&self, fr: RegionVid) -> Option<RegionName> {
|
fn give_name_if_anonymous_region_appears_in_upvars(&self, fr: RegionVid) -> Option<RegionName> {
|
||||||
let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?;
|
let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?;
|
||||||
let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
|
let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
|
||||||
@ -670,6 +675,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||||||
/// must be a closure since, in a free fn, such an argument would
|
/// must be a closure since, in a free fn, such an argument would
|
||||||
/// have to either also appear in an argument (if using elision)
|
/// have to either also appear in an argument (if using elision)
|
||||||
/// or be early bound (named, not in argument).
|
/// or be early bound (named, not in argument).
|
||||||
|
#[tracing::instrument(level = "trace", skip(self))]
|
||||||
fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option<RegionName> {
|
fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option<RegionName> {
|
||||||
let tcx = self.infcx.tcx;
|
let tcx = self.infcx.tcx;
|
||||||
let hir = tcx.hir();
|
let hir = tcx.hir();
|
||||||
@ -801,6 +807,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "trace", skip(self))]
|
||||||
fn give_name_if_anonymous_region_appears_in_yield_ty(
|
fn give_name_if_anonymous_region_appears_in_yield_ty(
|
||||||
&self,
|
&self,
|
||||||
fr: RegionVid,
|
fr: RegionVid,
|
||||||
|
@ -722,8 +722,7 @@ pub enum LifetimeRes {
|
|||||||
/// Id of the introducing place. That can be:
|
/// Id of the introducing place. That can be:
|
||||||
/// - an item's id, for the item's generic parameters;
|
/// - an item's id, for the item's generic parameters;
|
||||||
/// - a TraitRef's ref_id, identifying the `for<...>` binder;
|
/// - a TraitRef's ref_id, identifying the `for<...>` binder;
|
||||||
/// - a BareFn type's id;
|
/// - a BareFn type's id.
|
||||||
/// - a Path's id when this path has parenthesized generic args.
|
|
||||||
///
|
///
|
||||||
/// This information is used for impl-trait lifetime captures, to know when to or not to
|
/// This information is used for impl-trait lifetime captures, to know when to or not to
|
||||||
/// capture any given lifetime.
|
/// capture any given lifetime.
|
||||||
@ -732,7 +731,9 @@ pub enum LifetimeRes {
|
|||||||
/// Created a generic parameter for an anonymous lifetime.
|
/// Created a generic parameter for an anonymous lifetime.
|
||||||
Fresh {
|
Fresh {
|
||||||
/// Id of the generic parameter that introduced it.
|
/// Id of the generic parameter that introduced it.
|
||||||
param: LocalDefId,
|
///
|
||||||
|
/// Creating the associated `LocalDefId` is the responsibility of lowering.
|
||||||
|
param: NodeId,
|
||||||
/// Id of the introducing place. See `Param`.
|
/// Id of the introducing place. See `Param`.
|
||||||
binder: NodeId,
|
binder: NodeId,
|
||||||
},
|
},
|
||||||
|
@ -1932,6 +1932,7 @@ pub enum ExprKind<'hir> {
|
|||||||
/// `Option<Movability>`.
|
/// `Option<Movability>`.
|
||||||
Closure {
|
Closure {
|
||||||
capture_clause: CaptureBy,
|
capture_clause: CaptureBy,
|
||||||
|
bound_generic_params: &'hir [GenericParam<'hir>],
|
||||||
fn_decl: &'hir FnDecl<'hir>,
|
fn_decl: &'hir FnDecl<'hir>,
|
||||||
body: BodyId,
|
body: BodyId,
|
||||||
fn_decl_span: Span,
|
fn_decl_span: Span,
|
||||||
@ -3480,7 +3481,7 @@ impl<'hir> Node<'hir> {
|
|||||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||||
mod size_asserts {
|
mod size_asserts {
|
||||||
rustc_data_structures::static_assert_size!(super::Block<'static>, 48);
|
rustc_data_structures::static_assert_size!(super::Block<'static>, 48);
|
||||||
rustc_data_structures::static_assert_size!(super::Expr<'static>, 56);
|
rustc_data_structures::static_assert_size!(super::Expr<'static>, 64);
|
||||||
rustc_data_structures::static_assert_size!(super::Pat<'static>, 88);
|
rustc_data_structures::static_assert_size!(super::Pat<'static>, 88);
|
||||||
rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
|
rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
|
||||||
rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);
|
rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);
|
||||||
|
@ -1169,12 +1169,16 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
|||||||
walk_list!(visitor, visit_arm, arms);
|
walk_list!(visitor, visit_arm, arms);
|
||||||
}
|
}
|
||||||
ExprKind::Closure {
|
ExprKind::Closure {
|
||||||
|
bound_generic_params,
|
||||||
ref fn_decl,
|
ref fn_decl,
|
||||||
body,
|
body,
|
||||||
capture_clause: _,
|
capture_clause: _,
|
||||||
fn_decl_span: _,
|
fn_decl_span: _,
|
||||||
movability: _,
|
movability: _,
|
||||||
} => visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id),
|
} => {
|
||||||
|
walk_list!(visitor, visit_generic_param, bound_generic_params);
|
||||||
|
visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id)
|
||||||
|
}
|
||||||
ExprKind::Block(ref block, ref opt_label) => {
|
ExprKind::Block(ref block, ref opt_label) => {
|
||||||
walk_list!(visitor, visit_label, opt_label);
|
walk_list!(visitor, visit_label, opt_label);
|
||||||
visitor.visit_block(block);
|
visitor.visit_block(block);
|
||||||
|
@ -1459,11 +1459,13 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
hir::ExprKind::Closure {
|
hir::ExprKind::Closure {
|
||||||
capture_clause,
|
capture_clause,
|
||||||
|
bound_generic_params,
|
||||||
ref fn_decl,
|
ref fn_decl,
|
||||||
body,
|
body,
|
||||||
fn_decl_span: _,
|
fn_decl_span: _,
|
||||||
movability: _,
|
movability: _,
|
||||||
} => {
|
} => {
|
||||||
|
self.print_formal_generic_params(bound_generic_params);
|
||||||
self.print_capture_clause(capture_clause);
|
self.print_capture_clause(capture_clause);
|
||||||
|
|
||||||
self.print_closure_params(&fn_decl, body);
|
self.print_closure_params(&fn_decl, body);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2242,9 +2242,18 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
|||||||
]
|
]
|
||||||
.contains(&Some(did))
|
.contains(&Some(did))
|
||||||
{
|
{
|
||||||
let (span, span_type) = match &trait_ref.bound_generic_params {
|
let (span, span_type) = if let Some(bound) =
|
||||||
[] => (trait_ref.span.shrink_to_lo(), ForLifetimeSpanType::BoundEmpty),
|
trait_ref.bound_generic_params.iter().rfind(|param| {
|
||||||
[.., bound] => (bound.span.shrink_to_hi(), ForLifetimeSpanType::BoundTail),
|
matches!(
|
||||||
|
param.kind,
|
||||||
|
hir::GenericParamKind::Lifetime {
|
||||||
|
kind: hir::LifetimeParamKind::Explicit
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
(bound.span.shrink_to_hi(), ForLifetimeSpanType::BoundTail)
|
||||||
|
} else {
|
||||||
|
(trait_ref.span.shrink_to_lo(), ForLifetimeSpanType::BoundEmpty)
|
||||||
};
|
};
|
||||||
self.missing_named_lifetime_spots
|
self.missing_named_lifetime_spots
|
||||||
.push(MissingLifetimeSpot::HigherRanked { span, span_type });
|
.push(MissingLifetimeSpot::HigherRanked { span, span_type });
|
||||||
|
@ -29,8 +29,6 @@ use std::cell::Cell;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::mem::take;
|
use std::mem::take;
|
||||||
|
|
||||||
use tracing::{debug, span, Level};
|
|
||||||
|
|
||||||
trait RegionExt {
|
trait RegionExt {
|
||||||
fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region);
|
fn early(hir_map: Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (LocalDefId, Region);
|
||||||
|
|
||||||
@ -572,41 +570,38 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_fn(
|
fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
|
||||||
&mut self,
|
if let hir::ExprKind::Closure { bound_generic_params, .. } = e.kind {
|
||||||
fk: intravisit::FnKind<'tcx>,
|
let next_early_index = self.next_early_index();
|
||||||
fd: &'tcx hir::FnDecl<'tcx>,
|
let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
|
||||||
b: hir::BodyId,
|
bound_generic_params
|
||||||
s: rustc_span::Span,
|
.iter()
|
||||||
hir_id: hir::HirId,
|
.filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
|
||||||
) {
|
.enumerate()
|
||||||
let name = match fk {
|
.map(|(late_bound_idx, param)| {
|
||||||
intravisit::FnKind::ItemFn(id, _, _) => id.name,
|
let pair = Region::late(late_bound_idx as u32, self.tcx.hir(), param);
|
||||||
intravisit::FnKind::Method(id, _) => id.name,
|
let r = late_region_as_bound_region(self.tcx, &pair.1);
|
||||||
intravisit::FnKind::Closure => sym::closure,
|
(pair, r)
|
||||||
};
|
})
|
||||||
let name = name.as_str();
|
.unzip();
|
||||||
let span = span!(Level::DEBUG, "visit_fn", name);
|
self.map.late_bound_vars.insert(e.hir_id, binders);
|
||||||
let _enter = span.enter();
|
let scope = Scope::Binder {
|
||||||
match fk {
|
hir_id: e.hir_id,
|
||||||
// Any `Binders` are handled elsewhere
|
lifetimes,
|
||||||
intravisit::FnKind::ItemFn(..) | intravisit::FnKind::Method(..) => {
|
s: self.scope,
|
||||||
intravisit::walk_fn(self, fk, fd, b, s, hir_id)
|
next_early_index,
|
||||||
}
|
opaque_type_parent: false,
|
||||||
intravisit::FnKind::Closure => {
|
scope_type: BinderScopeType::Normal,
|
||||||
self.map.late_bound_vars.insert(hir_id, vec![]);
|
allow_late_bound: true,
|
||||||
let scope = Scope::Binder {
|
where_bound_origin: None,
|
||||||
hir_id,
|
};
|
||||||
lifetimes: FxIndexMap::default(),
|
self.with(scope, |this| {
|
||||||
next_early_index: self.next_early_index(),
|
// a closure has no bounds, so everything
|
||||||
s: self.scope,
|
// contained within is scoped within its binder.
|
||||||
opaque_type_parent: false,
|
intravisit::walk_expr(this, e)
|
||||||
scope_type: BinderScopeType::Normal,
|
});
|
||||||
allow_late_bound: true,
|
} else {
|
||||||
where_bound_origin: None,
|
intravisit::walk_expr(self, e)
|
||||||
};
|
|
||||||
self.with(scope, move |this| intravisit::walk_fn(this, fk, fd, b, s, hir_id));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -755,7 +750,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||||||
let next_early_index = self.next_early_index();
|
let next_early_index = self.next_early_index();
|
||||||
let lifetime_span: Option<Span> =
|
let lifetime_span: Option<Span> =
|
||||||
c.generic_params.iter().rev().find_map(|param| match param.kind {
|
c.generic_params.iter().rev().find_map(|param| match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => Some(param.span),
|
GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } => {
|
||||||
|
Some(param.span)
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
let (span, span_type) = if let Some(span) = lifetime_span {
|
let (span, span_type) = if let Some(span) = lifetime_span {
|
||||||
|
@ -2920,13 +2920,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
) {
|
) {
|
||||||
for br in referenced_regions.difference(&constrained_regions) {
|
for br in referenced_regions.difference(&constrained_regions) {
|
||||||
let br_name = match *br {
|
let br_name = match *br {
|
||||||
|
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) | ty::BrEnv => {
|
||||||
|
"an anonymous lifetime".to_string()
|
||||||
|
}
|
||||||
ty::BrNamed(_, name) => format!("lifetime `{}`", name),
|
ty::BrNamed(_, name) => format!("lifetime `{}`", name),
|
||||||
ty::BrAnon(_) | ty::BrEnv => "an anonymous lifetime".to_string(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut err = generate_err(&br_name);
|
let mut err = generate_err(&br_name);
|
||||||
|
|
||||||
if let ty::BrAnon(_) = *br {
|
if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(_) = *br {
|
||||||
// The only way for an anonymous lifetime to wind up
|
// The only way for an anonymous lifetime to wind up
|
||||||
// in the return type but **also** be unconstrained is
|
// in the return type but **also** be unconstrained is
|
||||||
// if it only appears in "associated types" in the
|
// if it only appears in "associated types" in the
|
||||||
|
@ -628,24 +628,40 @@ fn compare_number_of_generics<'tcx>(
|
|||||||
let mut err_occurred = None;
|
let mut err_occurred = None;
|
||||||
for (kind, trait_count, impl_count) in matchings {
|
for (kind, trait_count, impl_count) in matchings {
|
||||||
if impl_count != trait_count {
|
if impl_count != trait_count {
|
||||||
|
let arg_spans = |kind: ty::AssocKind, generics: &hir::Generics<'_>| {
|
||||||
|
let mut spans = generics
|
||||||
|
.params
|
||||||
|
.iter()
|
||||||
|
.filter(|p| match p.kind {
|
||||||
|
hir::GenericParamKind::Lifetime {
|
||||||
|
kind: hir::LifetimeParamKind::Elided,
|
||||||
|
} => {
|
||||||
|
// A fn can have an arbitrary number of extra elided lifetimes for the
|
||||||
|
// same signature.
|
||||||
|
!matches!(kind, ty::AssocKind::Fn)
|
||||||
|
}
|
||||||
|
_ => true,
|
||||||
|
})
|
||||||
|
.map(|p| p.span)
|
||||||
|
.collect::<Vec<Span>>();
|
||||||
|
if spans.is_empty() {
|
||||||
|
spans = vec![generics.span]
|
||||||
|
}
|
||||||
|
spans
|
||||||
|
};
|
||||||
let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
|
let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
|
||||||
let trait_item = tcx.hir().expect_trait_item(def_id);
|
let trait_item = tcx.hir().expect_trait_item(def_id);
|
||||||
if trait_item.generics.params.is_empty() {
|
let arg_spans: Vec<Span> = arg_spans(trait_.kind, trait_item.generics);
|
||||||
(Some(vec![trait_item.generics.span]), vec![])
|
let impl_trait_spans: Vec<Span> = trait_item
|
||||||
} else {
|
.generics
|
||||||
let arg_spans: Vec<Span> =
|
.params
|
||||||
trait_item.generics.params.iter().map(|p| p.span).collect();
|
.iter()
|
||||||
let impl_trait_spans: Vec<Span> = trait_item
|
.filter_map(|p| match p.kind {
|
||||||
.generics
|
GenericParamKind::Type { synthetic: true, .. } => Some(p.span),
|
||||||
.params
|
_ => None,
|
||||||
.iter()
|
})
|
||||||
.filter_map(|p| match p.kind {
|
.collect();
|
||||||
GenericParamKind::Type { synthetic: true, .. } => Some(p.span),
|
(Some(arg_spans), impl_trait_spans)
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
(Some(arg_spans), impl_trait_spans)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
(trait_span.map(|s| vec![s]), vec![])
|
(trait_span.map(|s| vec![s]), vec![])
|
||||||
};
|
};
|
||||||
@ -660,23 +676,7 @@ fn compare_number_of_generics<'tcx>(
|
|||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let spans = if impl_item.generics.params.is_empty() {
|
let spans = arg_spans(impl_.kind, impl_item.generics);
|
||||||
vec![impl_item.generics.span]
|
|
||||||
} else {
|
|
||||||
impl_item
|
|
||||||
.generics
|
|
||||||
.params
|
|
||||||
.iter()
|
|
||||||
.filter(|p| {
|
|
||||||
matches!(
|
|
||||||
p.kind,
|
|
||||||
hir::GenericParamKind::Type { .. }
|
|
||||||
| hir::GenericParamKind::Const { .. }
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.map(|p| p.span)
|
|
||||||
.collect::<Vec<Span>>()
|
|
||||||
};
|
|
||||||
let span = spans.first().copied();
|
let span = spans.first().copied();
|
||||||
|
|
||||||
let mut err = tcx.sess.struct_span_err_with_code(
|
let mut err = tcx.sess.struct_span_err_with_code(
|
||||||
|
@ -222,10 +222,15 @@ impl<'tcx> Clean<'tcx, Option<Lifetime>> for ty::Region<'tcx> {
|
|||||||
match **self {
|
match **self {
|
||||||
ty::ReStatic => Some(Lifetime::statik()),
|
ty::ReStatic => Some(Lifetime::statik()),
|
||||||
ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => {
|
ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => {
|
||||||
Some(Lifetime(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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)),
|
|
||||||
|
|
||||||
ty::ReLateBound(..)
|
ty::ReLateBound(..)
|
||||||
| ty::ReFree(..)
|
| ty::ReFree(..)
|
||||||
| ty::ReVar(..)
|
| ty::ReVar(..)
|
||||||
@ -530,29 +535,25 @@ fn clean_generic_param<'tcx>(
|
|||||||
GenericParamDef { name, kind }
|
GenericParamDef { name, kind }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Synthetic type-parameters are inserted after normal ones.
|
||||||
|
/// In order for normal parameters to be able to refer to synthetic ones,
|
||||||
|
/// scans them first.
|
||||||
|
fn is_impl_trait(param: &hir::GenericParam<'_>) -> bool {
|
||||||
|
match param.kind {
|
||||||
|
hir::GenericParamKind::Type { synthetic, .. } => synthetic,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This can happen for `async fn`, e.g. `async fn f<'_>(&'_ self)`.
|
||||||
|
///
|
||||||
|
/// See `lifetime_to_generic_param` in `rustc_ast_lowering` for more information.
|
||||||
|
fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
|
||||||
|
matches!(param.kind, hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided })
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Clean<'tcx, Generics> for hir::Generics<'tcx> {
|
impl<'tcx> Clean<'tcx, Generics> for hir::Generics<'tcx> {
|
||||||
fn clean(&self, cx: &mut DocContext<'tcx>) -> Generics {
|
fn clean(&self, cx: &mut DocContext<'tcx>) -> Generics {
|
||||||
// Synthetic type-parameters are inserted after normal ones.
|
|
||||||
// In order for normal parameters to be able to refer to synthetic ones,
|
|
||||||
// scans them first.
|
|
||||||
fn is_impl_trait(param: &hir::GenericParam<'_>) -> bool {
|
|
||||||
match param.kind {
|
|
||||||
hir::GenericParamKind::Type { synthetic, .. } => synthetic,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// This can happen for `async fn`, e.g. `async fn f<'_>(&'_ self)`.
|
|
||||||
///
|
|
||||||
/// See [`lifetime_to_generic_param`] in [`rustc_ast_lowering`] for more information.
|
|
||||||
///
|
|
||||||
/// [`lifetime_to_generic_param`]: rustc_ast_lowering::LoweringContext::lifetime_to_generic_param
|
|
||||||
fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
|
|
||||||
matches!(
|
|
||||||
param.kind,
|
|
||||||
hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
let impl_trait_params = self
|
let impl_trait_params = self
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
@ -991,6 +992,7 @@ impl<'tcx> Clean<'tcx, PolyTrait> for hir::PolyTraitRef<'tcx> {
|
|||||||
generic_params: self
|
generic_params: self
|
||||||
.bound_generic_params
|
.bound_generic_params
|
||||||
.iter()
|
.iter()
|
||||||
|
.filter(|p| !is_elided_lifetime(p))
|
||||||
.map(|x| clean_generic_param(cx, None, x))
|
.map(|x| clean_generic_param(cx, None, x))
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
@ -1865,8 +1867,12 @@ impl<'tcx> Clean<'tcx, BareFunctionDecl> for hir::BareFnTy<'tcx> {
|
|||||||
fn clean(&self, cx: &mut DocContext<'tcx>) -> BareFunctionDecl {
|
fn clean(&self, cx: &mut DocContext<'tcx>) -> BareFunctionDecl {
|
||||||
let (generic_params, decl) = enter_impl_trait(cx, |cx| {
|
let (generic_params, decl) = enter_impl_trait(cx, |cx| {
|
||||||
// NOTE: generics must be cleaned before args
|
// NOTE: generics must be cleaned before args
|
||||||
let generic_params =
|
let generic_params = self
|
||||||
self.generic_params.iter().map(|x| clean_generic_param(cx, None, x)).collect();
|
.generic_params
|
||||||
|
.iter()
|
||||||
|
.filter(|p| !is_elided_lifetime(p))
|
||||||
|
.map(|x| clean_generic_param(cx, None, x))
|
||||||
|
.collect();
|
||||||
let args = clean_args_from_types_and_names(cx, self.decl.inputs, self.param_names);
|
let args = clean_args_from_types_and_names(cx, self.decl.inputs, self.param_names);
|
||||||
let decl = clean_fn_decl_with_args(cx, self.decl, args);
|
let decl = clean_fn_decl_with_args(cx, self.decl, args);
|
||||||
(generic_params, decl)
|
(generic_params, decl)
|
||||||
|
@ -84,12 +84,9 @@ pub(crate) fn substs_to_args<'tcx>(
|
|||||||
let mut ret_val =
|
let mut ret_val =
|
||||||
Vec::with_capacity(substs.len().saturating_sub(if skip_first { 1 } else { 0 }));
|
Vec::with_capacity(substs.len().saturating_sub(if skip_first { 1 } else { 0 }));
|
||||||
ret_val.extend(substs.iter().filter_map(|kind| match kind.unpack() {
|
ret_val.extend(substs.iter().filter_map(|kind| match kind.unpack() {
|
||||||
GenericArgKind::Lifetime(lt) => match *lt {
|
GenericArgKind::Lifetime(lt) => {
|
||||||
ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrAnon(_), .. }) => {
|
Some(GenericArg::Lifetime(lt.clean(cx).unwrap_or(Lifetime::elided())))
|
||||||
Some(GenericArg::Lifetime(Lifetime::elided()))
|
}
|
||||||
}
|
|
||||||
_ => lt.clean(cx).map(GenericArg::Lifetime),
|
|
||||||
},
|
|
||||||
GenericArgKind::Type(_) if skip_first => {
|
GenericArgKind::Type(_) if skip_first => {
|
||||||
skip_first = false;
|
skip_first = false;
|
||||||
None
|
None
|
||||||
|
@ -45,7 +45,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
|
fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
|
||||||
//~^ ERROR: missing lifetime specifier
|
//~^ ERROR `'_` cannot be used here [E0637]
|
||||||
//~| ERROR: missing lifetime specifier
|
//~| ERROR: missing lifetime specifier
|
||||||
DocumentImpl {}
|
DocumentImpl {}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,8 @@
|
|||||||
error[E0106]: missing lifetime specifier
|
error[E0637]: `'_` cannot be used here
|
||||||
--> $DIR/issue-70304.rs:47:41
|
--> $DIR/issue-70304.rs:47:41
|
||||||
|
|
|
|
||||||
LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
|
LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
|
||||||
| ^^ expected named lifetime parameter
|
| ^^ `'_` is a reserved lifetime name
|
||||||
|
|
|
||||||
= 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 create_doc() -> impl Document<Cursor<'static> = DocCursorImpl<'_>> {
|
|
||||||
| ~~~~~~~
|
|
||||||
|
|
||||||
error[E0106]: missing lifetime specifier
|
error[E0106]: missing lifetime specifier
|
||||||
--> $DIR/issue-70304.rs:47:61
|
--> $DIR/issue-70304.rs:47:61
|
||||||
@ -24,4 +18,5 @@ LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'static>> {
|
|||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0106`.
|
Some errors have detailed explanations: E0106, E0637.
|
||||||
|
For more information about an error, try `rustc --explain E0106`.
|
||||||
|
@ -9,7 +9,7 @@ trait Foo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn foo(x: &impl Foo<Item<'_> = u32>) { }
|
fn foo(x: &impl Foo<Item<'_> = u32>) { }
|
||||||
//~^ ERROR missing lifetime specifier
|
//~^ ERROR `'_` cannot be used here [E0637]
|
||||||
|
|
||||||
fn bar(x: &impl for<'a> Foo<Item<'a> = &'_ u32>) { }
|
fn bar(x: &impl for<'a> Foo<Item<'a> = &'_ u32>) { }
|
||||||
//~^ ERROR missing lifetime specifier
|
//~^ ERROR missing lifetime specifier
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
error[E0106]: missing lifetime specifier
|
error[E0637]: `'_` cannot be used here
|
||||||
--> $DIR/issue-95305.rs:11:26
|
--> $DIR/issue-95305.rs:11:26
|
||||||
|
|
|
|
||||||
LL | fn foo(x: &impl Foo<Item<'_> = u32>) { }
|
LL | fn foo(x: &impl Foo<Item<'_> = u32>) { }
|
||||||
| ^^ expected named lifetime parameter
|
| ^^ `'_` is a reserved lifetime name
|
||||||
|
|
|
||||||
help: consider introducing a named lifetime parameter
|
|
||||||
|
|
|
||||||
LL | fn foo<'a>(x: &impl Foo<Item<'a> = u32>) { }
|
|
||||||
| ++++ ~~
|
|
||||||
|
|
||||||
error[E0106]: missing lifetime specifier
|
error[E0106]: missing lifetime specifier
|
||||||
--> $DIR/issue-95305.rs:14:41
|
--> $DIR/issue-95305.rs:14:41
|
||||||
@ -22,4 +17,5 @@ LL | fn bar(x: &impl for<'a> Foo<Item<'a> = &'a u32>) { }
|
|||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0106`.
|
Some errors have detailed explanations: E0106, E0637.
|
||||||
|
For more information about an error, try `rustc --explain E0106`.
|
||||||
|
@ -8,7 +8,7 @@ LL | type A = u32;
|
|||||||
| ^ lifetimes do not match type in trait
|
| ^ lifetimes do not match type in trait
|
||||||
|
|
||||||
error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
|
error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
|
||||||
--> $DIR/parameter_number_and_kind_impl.rs:17:16
|
--> $DIR/parameter_number_and_kind_impl.rs:17:12
|
||||||
|
|
|
|
||||||
LL | type B<'a, 'b>;
|
LL | type B<'a, 'b>;
|
||||||
| -- --
|
| -- --
|
||||||
@ -16,7 +16,9 @@ LL | type B<'a, 'b>;
|
|||||||
| expected 0 type parameters
|
| expected 0 type parameters
|
||||||
...
|
...
|
||||||
LL | type B<'a, T> = Vec<T>;
|
LL | type B<'a, T> = Vec<T>;
|
||||||
| ^ found 1 type parameter
|
| ^^ ^
|
||||||
|
| |
|
||||||
|
| found 1 type parameter
|
||||||
|
|
||||||
error[E0195]: lifetime parameters or bounds on type `C` do not match the trait declaration
|
error[E0195]: lifetime parameters or bounds on type `C` do not match the trait declaration
|
||||||
--> $DIR/parameter_number_and_kind_impl.rs:19:11
|
--> $DIR/parameter_number_and_kind_impl.rs:19:11
|
||||||
|
@ -23,7 +23,7 @@ error[E0308]: mismatched types
|
|||||||
LL | foo(bar, "string", |s| s.len() == 5);
|
LL | foo(bar, "string", |s| s.len() == 5);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||||
|
|
|
|
||||||
= note: expected trait `FnOnce<(&&str,)>`
|
= note: expected trait `for<'r, 's> FnOnce<(&'r &'s str,)>`
|
||||||
found trait `for<'r> FnOnce<(&'r &str,)>`
|
found trait `for<'r> FnOnce<(&'r &str,)>`
|
||||||
note: this closure does not fulfill the lifetime requirements
|
note: this closure does not fulfill the lifetime requirements
|
||||||
--> $DIR/issue-71955.rs:45:24
|
--> $DIR/issue-71955.rs:45:24
|
||||||
@ -61,7 +61,7 @@ error[E0308]: mismatched types
|
|||||||
LL | foo(baz, "string", |s| s.0.len() == 5);
|
LL | foo(baz, "string", |s| s.0.len() == 5);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||||
|
|
|
|
||||||
= note: expected trait `FnOnce<(&Wrapper<'_>,)>`
|
= note: expected trait `for<'r, 's> FnOnce<(&'r Wrapper<'s>,)>`
|
||||||
found trait `for<'r> FnOnce<(&'r Wrapper<'_>,)>`
|
found trait `for<'r> FnOnce<(&'r Wrapper<'_>,)>`
|
||||||
note: this closure does not fulfill the lifetime requirements
|
note: this closure does not fulfill the lifetime requirements
|
||||||
--> $DIR/issue-71955.rs:48:24
|
--> $DIR/issue-71955.rs:48:24
|
||||||
|
@ -6,8 +6,8 @@ trait SomeTrait<'a> {
|
|||||||
|
|
||||||
fn give_me_ice<T>() {
|
fn give_me_ice<T>() {
|
||||||
callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
|
callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
|
||||||
//~^ ERROR the trait bound `T: SomeTrait<'_>` is not satisfied [E0277]
|
//~^ ERROR the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied [E0277]
|
||||||
//~| ERROR the trait bound `T: SomeTrait<'_>` is not satisfied [E0277]
|
//~| ERROR the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied [E0277]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn callee<T: Fn<(&'static (),)>>() {
|
fn callee<T: Fn<(&'static (),)>>() {
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
error[E0277]: the trait bound `T: SomeTrait<'_>` is not satisfied
|
error[E0277]: the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied
|
||||||
--> $DIR/issue-85455.rs:8:5
|
--> $DIR/issue-85455.rs:8:5
|
||||||
|
|
|
|
||||||
LL | callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
|
LL | callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `SomeTrait<'_>` is not implemented for `T`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'r> SomeTrait<'r>` is not implemented for `T`
|
||||||
|
|
|
|
||||||
help: consider restricting type parameter `T`
|
help: consider restricting type parameter `T`
|
||||||
|
|
|
|
||||||
LL | fn give_me_ice<T: SomeTrait<'_>>() {
|
LL | fn give_me_ice<T: for<'r> SomeTrait<'r>>() {
|
||||||
| +++++++++++++++
|
| +++++++++++++++++++++++
|
||||||
|
|
||||||
error[E0277]: the trait bound `T: SomeTrait<'_>` is not satisfied
|
error[E0277]: the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied
|
||||||
--> $DIR/issue-85455.rs:8:14
|
--> $DIR/issue-85455.rs:8:14
|
||||||
|
|
|
|
||||||
LL | callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
|
LL | callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `SomeTrait<'_>` is not implemented for `T`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'r> SomeTrait<'r>` is not implemented for `T`
|
||||||
|
|
|
|
||||||
help: consider restricting type parameter `T`
|
help: consider restricting type parameter `T`
|
||||||
|
|
|
|
||||||
LL | fn give_me_ice<T: SomeTrait<'_>>() {
|
LL | fn give_me_ice<T: for<'r> SomeTrait<'r>>() {
|
||||||
| +++++++++++++++
|
| +++++++++++++++++++++++
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
@ -13,6 +13,10 @@ impl StaticTrait for Box<dyn Debug> { }
|
|||||||
trait NotStaticTrait { }
|
trait NotStaticTrait { }
|
||||||
impl NotStaticTrait for Box<dyn Debug + '_> { }
|
impl NotStaticTrait for Box<dyn Debug + '_> { }
|
||||||
|
|
||||||
|
// Check that we don't err when the trait has a lifetime parameter.
|
||||||
|
trait TraitWithLifetime<'a> { }
|
||||||
|
impl NotStaticTrait for &dyn TraitWithLifetime<'_> { }
|
||||||
|
|
||||||
fn static_val<T: StaticTrait>(_: T) {
|
fn static_val<T: StaticTrait>(_: T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0521]: borrowed data escapes outside of function
|
error[E0521]: borrowed data escapes outside of function
|
||||||
--> $DIR/dyn-trait.rs:20:5
|
--> $DIR/dyn-trait.rs:24:5
|
||||||
|
|
|
|
||||||
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
|
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
|
||||||
| -- - `x` is a reference that is only valid in the function body
|
| -- - `x` is a reference that is only valid in the function body
|
||||||
|
13
src/test/ui/lifetimes/elided-lifetime-in-path-in-pat.rs
Normal file
13
src/test/ui/lifetimes/elided-lifetime-in-path-in-pat.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// check-pass
|
||||||
|
|
||||||
|
struct Foo<'a> {
|
||||||
|
x: &'a (),
|
||||||
|
}
|
||||||
|
|
||||||
|
// The lifetime in pattern-position `Foo` is elided.
|
||||||
|
// Verify that lowering does not create an independent lifetime parameter for it.
|
||||||
|
fn foo<'a>(Foo { x }: Foo<'a>) {
|
||||||
|
*x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -10,8 +10,8 @@ LL | y.push(z);
|
|||||||
|
|
|
|
||||||
help: consider introducing a named lifetime parameter
|
help: consider introducing a named lifetime parameter
|
||||||
|
|
|
|
||||||
LL | fn foo<'a>(x:Box<dyn Fn(&'a u8, &'a u8)> , y: Vec<&u8>, z: &u8) {
|
LL | fn foo<'a>(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&'a u8>, z: &'a u8) {
|
||||||
| ++++ ++ ++
|
| ++++ ++ ++
|
||||||
|
|
||||||
error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
|
error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
|
||||||
--> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:3
|
--> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:3
|
||||||
|
Loading…
Reference in New Issue
Block a user