mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Always create parameters for functions-like types.
This commit is contained in:
parent
4b79b8bfa1
commit
32af719b07
@ -223,6 +223,12 @@ impl ResolverAstLoweringExt for ResolverAstLowering {
|
||||
}
|
||||
|
||||
/// 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)> {
|
||||
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.
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
fn lifetime_res_to_generic_param(
|
||||
&mut self,
|
||||
ident: Ident,
|
||||
@ -787,11 +794,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
/// Register a binder to be ignored for lifetime capture.
|
||||
#[tracing::instrument(level = "debug", skip(self, f))]
|
||||
#[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 {
|
||||
ctxt.binders_to_ignore.insert(binder);
|
||||
}
|
||||
let ret = f(self);
|
||||
let ret = f(self, generic_params);
|
||||
if let Some(ctxt) = &mut self.captured_lifetimes {
|
||||
ctxt.binders_to_ignore.remove(&binder);
|
||||
}
|
||||
@ -1188,15 +1209,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let lifetime = self.lower_lifetime(®ion);
|
||||
hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
|
||||
}
|
||||
TyKind::BareFn(ref f) => self.with_lifetime_binder(t.id, |this| {
|
||||
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
|
||||
generic_params: this.lower_generic_params(&f.generic_params),
|
||||
unsafety: this.lower_unsafety(f.unsafety),
|
||||
abi: this.lower_extern(f.ext),
|
||||
decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None),
|
||||
param_names: this.lower_fn_params_to_names(&f.decl),
|
||||
}))
|
||||
}),
|
||||
TyKind::BareFn(ref f) => {
|
||||
self.with_lifetime_binder(t.id, &f.generic_params, |this, generic_params| {
|
||||
hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
|
||||
generic_params,
|
||||
unsafety: this.lower_unsafety(f.unsafety),
|
||||
abi: this.lower_extern(f.ext),
|
||||
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::Tup(ref tys) => hir::TyKind::Tup(
|
||||
self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))),
|
||||
@ -1963,13 +1986,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
p: &PolyTraitRef,
|
||||
itctx: ImplTraitContext,
|
||||
) -> hir::PolyTraitRef<'hir> {
|
||||
let bound_generic_params = self.lower_generic_params(&p.bound_generic_params);
|
||||
|
||||
let trait_ref = self.with_lifetime_binder(p.trait_ref.ref_id, |this| {
|
||||
this.lower_trait_ref(&p.trait_ref, itctx)
|
||||
});
|
||||
|
||||
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
|
||||
self.with_lifetime_binder(
|
||||
p.trait_ref.ref_id,
|
||||
&p.bound_generic_params,
|
||||
|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) }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
|
||||
ParenthesizedGenericArgs::Ok => {
|
||||
self.lower_parenthesized_parameter_data(segment.id, data)
|
||||
}
|
||||
ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
|
||||
ParenthesizedGenericArgs::Err => {
|
||||
let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
|
||||
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(
|
||||
&mut self,
|
||||
id: NodeId,
|
||||
data: &ParenthesizedArgs,
|
||||
) -> (GenericArgsCtor<'hir>, bool) {
|
||||
// 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
|
||||
// compatibility, even in contexts like an impl header where
|
||||
// we generally don't permit such things (see #51008).
|
||||
self.with_lifetime_binder(id, |this| {
|
||||
let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
|
||||
let inputs = this.arena.alloc_from_iter(inputs.iter().map(|ty| {
|
||||
this.lower_ty_direct(
|
||||
ty,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam),
|
||||
)
|
||||
}));
|
||||
let output_ty = match output {
|
||||
FnRetTy::Ty(ty) => this
|
||||
.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)),
|
||||
FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(*span, &[])),
|
||||
};
|
||||
let args = smallvec![GenericArg::Type(this.ty_tup(*inputs_span, inputs))];
|
||||
let binding = this.output_ty_binding(output_ty.span, output_ty);
|
||||
(
|
||||
GenericArgsCtor {
|
||||
args,
|
||||
bindings: arena_vec![this; binding],
|
||||
parenthesized: true,
|
||||
span: data.inputs_span,
|
||||
},
|
||||
false,
|
||||
)
|
||||
})
|
||||
let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
|
||||
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| {
|
||||
self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam))
|
||||
}));
|
||||
let output_ty = match output {
|
||||
FnRetTy::Ty(ty) => {
|
||||
self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
|
||||
}
|
||||
FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])),
|
||||
};
|
||||
let args = smallvec![GenericArg::Type(self.ty_tup(*inputs_span, inputs))];
|
||||
let binding = self.output_ty_binding(output_ty.span, output_ty);
|
||||
(
|
||||
GenericArgsCtor {
|
||||
args,
|
||||
bindings: arena_vec![self; binding],
|
||||
parenthesized: true,
|
||||
span: data.inputs_span,
|
||||
},
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
/// An associated type binding `Output = $ty`.
|
||||
|
@ -722,8 +722,7 @@ pub enum LifetimeRes {
|
||||
/// Id of the introducing place. That can be:
|
||||
/// - an item's id, for the item's generic parameters;
|
||||
/// - a TraitRef's ref_id, identifying the `for<...>` binder;
|
||||
/// - a BareFn type's id;
|
||||
/// - a Path's id when this path has parenthesized generic args.
|
||||
/// - a BareFn type's id.
|
||||
///
|
||||
/// This information is used for impl-trait lifetime captures, to know when to or not to
|
||||
/// capture any given lifetime.
|
||||
|
@ -21,7 +21,6 @@ use rustc_hir::def::Namespace::{self, *};
|
||||
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
|
||||
use rustc_hir::{PrimTy, TraitCandidate};
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::ty::DefIdTree;
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::lint;
|
||||
@ -240,9 +239,16 @@ enum LifetimeRibKind {
|
||||
/// Create a new anonymous lifetime parameter and reference it.
|
||||
///
|
||||
/// If `report_in_path`, report an error when encountering lifetime elision in a path:
|
||||
/// ```ignore
|
||||
/// struct Foo<'a> { .. }
|
||||
/// fn foo(x: Foo) {}
|
||||
/// ```compile_fail
|
||||
/// struct Foo<'a> { x: &'a () }
|
||||
/// async fn foo(x: Foo) {}
|
||||
/// ```
|
||||
///
|
||||
/// Note: the error should not trigger when the elided lifetime is in a pattern or
|
||||
/// expression-position path:
|
||||
/// ```
|
||||
/// struct Foo<'a> { x: &'a () }
|
||||
/// async fn foo(Foo { x: _ }: Foo<'_>) {}
|
||||
/// ```
|
||||
AnonymousCreateParameter { binder: NodeId, report_in_path: bool },
|
||||
|
||||
@ -634,7 +640,10 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||
|this| {
|
||||
this.visit_generic_params(&bare_fn.generic_params, false);
|
||||
this.with_lifetime_rib(
|
||||
LifetimeRibKind::AnonymousPassThrough(ty.id, false),
|
||||
LifetimeRibKind::AnonymousCreateParameter {
|
||||
binder: ty.id,
|
||||
report_in_path: false,
|
||||
},
|
||||
|this| walk_list!(this, visit_param, &bare_fn.decl.inputs),
|
||||
);
|
||||
this.with_lifetime_rib(
|
||||
@ -720,15 +729,13 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||
// a body, or if there's no body for some other reason.
|
||||
FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _)
|
||||
| FnKind::Fn(_, _, sig, _, generics, None) => {
|
||||
self.visit_fn_header(&sig.header);
|
||||
self.visit_generics(generics);
|
||||
// We don't need to deal with patterns in parameters, because
|
||||
// they are not possible for foreign or bodiless functions.
|
||||
self.with_lifetime_rib(
|
||||
LifetimeRibKind::AnonymousPassThrough(fn_id, false),
|
||||
|this| {
|
||||
this.visit_fn_header(&sig.header);
|
||||
this.visit_generics(generics);
|
||||
walk_list!(this, visit_param, &sig.decl.inputs);
|
||||
},
|
||||
|this| walk_list!(this, visit_param, &sig.decl.inputs),
|
||||
);
|
||||
self.with_lifetime_rib(
|
||||
LifetimeRibKind::AnonymousPassThrough(fn_id, true),
|
||||
@ -761,15 +768,18 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||
// generic parameters. This is especially useful for `async fn`, where
|
||||
// these fresh generic parameters can be applied to the opaque `impl Trait`
|
||||
// return type.
|
||||
let rib = if async_node_id.is_some() {
|
||||
// Only emit a hard error for `async fn`, since this kind of
|
||||
// elision has always been allowed in regular `fn`s.
|
||||
LifetimeRibKind::AnonymousCreateParameter {
|
||||
binder: fn_id,
|
||||
report_in_path: true,
|
||||
}
|
||||
} else {
|
||||
LifetimeRibKind::AnonymousPassThrough(fn_id, false)
|
||||
};
|
||||
this.with_lifetime_rib(
|
||||
if async_node_id.is_some() {
|
||||
LifetimeRibKind::AnonymousCreateParameter {
|
||||
binder: fn_id,
|
||||
report_in_path: true,
|
||||
}
|
||||
} else {
|
||||
LifetimeRibKind::AnonymousPassThrough(fn_id, false)
|
||||
},
|
||||
rib,
|
||||
// Add each argument to the rib.
|
||||
|this| this.resolve_params(&declaration.inputs),
|
||||
);
|
||||
@ -937,19 +947,66 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||
self.diagnostic_metadata.currently_processing_generics = prev;
|
||||
}
|
||||
|
||||
fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) {
|
||||
self.visit_ident(constraint.ident);
|
||||
if let Some(ref gen_args) = constraint.gen_args {
|
||||
// Forbid anonymous lifetimes in GAT parameters until proper semantics are decided.
|
||||
self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
|
||||
this.visit_generic_args(gen_args.span(), gen_args)
|
||||
});
|
||||
}
|
||||
match constraint.kind {
|
||||
AssocConstraintKind::Equality { ref term } => match term {
|
||||
Term::Ty(ty) => self.visit_ty(ty),
|
||||
Term::Const(c) => self.visit_anon_const(c),
|
||||
},
|
||||
AssocConstraintKind::Bound { ref bounds } => {
|
||||
walk_list!(self, visit_param_bound, bounds, BoundKind::Bound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) {
|
||||
if let Some(ref args) = path_segment.args {
|
||||
match &**args {
|
||||
GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, path_span, args),
|
||||
GenericArgs::Parenthesized(ref data) => {
|
||||
self.with_lifetime_rib(
|
||||
LifetimeRibKind::AnonymousPassThrough(path_segment.id, false),
|
||||
|this| walk_list!(this, visit_ty, &data.inputs),
|
||||
);
|
||||
self.with_lifetime_rib(
|
||||
LifetimeRibKind::AnonymousPassThrough(path_segment.id, true),
|
||||
|this| visit::walk_fn_ret_ty(this, &data.output),
|
||||
)
|
||||
GenericArgs::Parenthesized(p_args) => {
|
||||
// Probe the lifetime ribs to know how to behave.
|
||||
for rib in self.lifetime_ribs.iter().rev() {
|
||||
match rib.kind {
|
||||
// We are inside a `PolyTraitRef`. The lifetimes are
|
||||
// to be intoduced in that (maybe implicit) `for<>` binder.
|
||||
LifetimeRibKind::Generics {
|
||||
binder,
|
||||
kind: LifetimeBinderKind::PolyTrait,
|
||||
..
|
||||
} => {
|
||||
self.with_lifetime_rib(
|
||||
LifetimeRibKind::AnonymousCreateParameter {
|
||||
binder,
|
||||
report_in_path: false,
|
||||
},
|
||||
|this| walk_list!(this, visit_ty, &p_args.inputs),
|
||||
);
|
||||
self.with_lifetime_rib(
|
||||
LifetimeRibKind::AnonymousPassThrough(binder, true),
|
||||
|this| visit::walk_fn_ret_ty(this, &p_args.output),
|
||||
);
|
||||
break;
|
||||
}
|
||||
// We have nowhere to introduce generics. Code is malformed,
|
||||
// so use regular lifetime resolution to avoid spurious errors.
|
||||
LifetimeRibKind::Item | LifetimeRibKind::Generics { .. } => {
|
||||
visit::walk_generic_args(self, path_span, args);
|
||||
break;
|
||||
}
|
||||
LifetimeRibKind::AnonymousPassThrough(..)
|
||||
| LifetimeRibKind::AnonymousCreateParameter { .. }
|
||||
| LifetimeRibKind::AnonymousReportError
|
||||
| LifetimeRibKind::AnonConst
|
||||
| LifetimeRibKind::ConstGeneric => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1474,7 +1531,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut should_lint = match source {
|
||||
let missing = match source {
|
||||
PathSource::Trait(..) | PathSource::TraitItem(..) | PathSource::Type => true,
|
||||
PathSource::Expr(..)
|
||||
| PathSource::Pat
|
||||
@ -1499,6 +1556,39 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
LifetimeRes::ElidedAnchor { start: node_ids.start, end: node_ids.end },
|
||||
);
|
||||
|
||||
if !missing {
|
||||
// Do not create a parameter for patterns and expressions.
|
||||
for rib in self.lifetime_ribs.iter().rev() {
|
||||
match rib.kind {
|
||||
LifetimeRibKind::AnonymousPassThrough(binder, _) => {
|
||||
let res = LifetimeRes::Anonymous { binder, elided: true };
|
||||
for id in node_ids {
|
||||
self.record_lifetime_res(id, res);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// `LifetimeRes::Error`, which would usually be used in the case of
|
||||
// `ReportError`, is unsuitable here, as we don't emit an error yet. Instead,
|
||||
// we simply resolve to an implicit lifetime, which will be checked later, at
|
||||
// which point a suitable error will be emitted.
|
||||
LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => {
|
||||
// FIXME(cjgillot) This resolution is wrong, but this does not matter
|
||||
// since these cases are erroneous anyway. Lifetime resolution should
|
||||
// emit a "missing lifetime specifier" diagnostic.
|
||||
let res =
|
||||
LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true };
|
||||
for id in node_ids {
|
||||
self.record_lifetime_res(id, res);
|
||||
}
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut should_lint = true;
|
||||
for rib in self.lifetime_ribs.iter().rev() {
|
||||
match rib.kind {
|
||||
// In create-parameter mode we error here because we don't want to support
|
||||
@ -1526,44 +1616,38 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
err.note("assuming a `'static` lifetime...");
|
||||
err.emit();
|
||||
should_lint = false;
|
||||
for i in 0..expected_lifetimes {
|
||||
let id = node_ids.start.plus(i);
|
||||
|
||||
for id in node_ids {
|
||||
self.record_lifetime_res(id, LifetimeRes::Error);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Do not create a parameter for patterns and expressions.
|
||||
LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
|
||||
let res = self.create_fresh_lifetime(node_ids.start, ident, binder);
|
||||
self.record_lifetime_res(node_ids.start, res);
|
||||
for i in 1..expected_lifetimes {
|
||||
let id = node_ids.start.plus(i);
|
||||
for id in node_ids {
|
||||
let res = self.create_fresh_lifetime(id, ident, binder);
|
||||
self.record_lifetime_res(id, res);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// `PassThrough` is the normal case.
|
||||
// `new_error_lifetime`, which would usually be used in the case of `ReportError`,
|
||||
// is unsuitable here, as these can occur from missing lifetime parameters in a
|
||||
// `PathSegment`, for which there is no associated `'_` or `&T` with no explicit
|
||||
// lifetime. Instead, we simply create an implicit lifetime, which will be checked
|
||||
// later, at which point a suitable error will be emitted.
|
||||
LifetimeRibKind::AnonymousPassThrough(binder, _) => {
|
||||
let res = LifetimeRes::Anonymous { binder, elided: true };
|
||||
self.record_lifetime_res(node_ids.start, res);
|
||||
for i in 1..expected_lifetimes {
|
||||
let id = node_ids.start.plus(i);
|
||||
for id in node_ids {
|
||||
self.record_lifetime_res(id, res);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// `LifetimeRes::Error`, which would usually be used in the case of
|
||||
// `ReportError`, is unsuitable here, as we don't emit an error yet. Instead,
|
||||
// we simply resolve to an implicit lifetime, which will be checked later, at
|
||||
// which point a suitable error will be emitted.
|
||||
LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => {
|
||||
// FIXME(cjgillot) This resolution is wrong, but this does not matter
|
||||
// since these cases are erroneous anyway. Lifetime resolution should
|
||||
// emit a "missing lifetime specifier" diagnostic.
|
||||
let res = LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true };
|
||||
for i in 0..expected_lifetimes {
|
||||
let id = node_ids.start.plus(i);
|
||||
for id in node_ids {
|
||||
self.record_lifetime_res(id, res);
|
||||
}
|
||||
break;
|
||||
@ -2235,7 +2319,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
fn resolve_impl_item(&mut self, item: &'ast AssocItem) {
|
||||
use crate::ResolutionError::*;
|
||||
match &item.kind {
|
||||
AssocItemKind::Const(_default, _ty, _expr) => {
|
||||
AssocItemKind::Const(_, ty, default) => {
|
||||
debug!("resolve_implementation AssocItemKind::Const");
|
||||
// If this is a trait impl, ensure the const
|
||||
// exists in trait
|
||||
@ -2248,14 +2332,17 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||
|i, s, c| ConstNotMemberOfTrait(i, s, c),
|
||||
);
|
||||
|
||||
// We allow arbitrary const expressions inside of associated consts,
|
||||
// even if they are potentially not const evaluatable.
|
||||
//
|
||||
// Type parameters can already be used and as associated consts are
|
||||
// not used as part of the type system, this is far less surprising.
|
||||
self.with_constant_rib(IsRepeatExpr::No, HasGenericParams::Yes, None, |this| {
|
||||
visit::walk_assoc_item(this, item, AssocCtxt::Impl)
|
||||
});
|
||||
self.visit_ty(ty);
|
||||
if let Some(expr) = default {
|
||||
// We allow arbitrary const expressions inside of associated consts,
|
||||
// even if they are potentially not const evaluatable.
|
||||
//
|
||||
// Type parameters can already be used and as associated consts are
|
||||
// not used as part of the type system, this is far less surprising.
|
||||
self.with_constant_rib(IsRepeatExpr::No, HasGenericParams::Yes, None, |this| {
|
||||
this.visit_expr(expr)
|
||||
});
|
||||
}
|
||||
}
|
||||
AssocItemKind::Fn(box Fn { generics, .. }) => {
|
||||
debug!("resolve_implementation AssocItemKind::Fn");
|
||||
|
@ -2223,9 +2223,18 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
||||
]
|
||||
.contains(&Some(did))
|
||||
{
|
||||
let (span, span_type) = match &trait_ref.bound_generic_params {
|
||||
[] => (trait_ref.span.shrink_to_lo(), ForLifetimeSpanType::BoundEmpty),
|
||||
[.., bound] => (bound.span.shrink_to_hi(), ForLifetimeSpanType::BoundTail),
|
||||
let (span, span_type) = if let Some(bound) =
|
||||
trait_ref.bound_generic_params.iter().rfind(|param| {
|
||||
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
|
||||
.push(MissingLifetimeSpot::HigherRanked { span, span_type });
|
||||
|
@ -755,7 +755,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
let next_early_index = self.next_early_index();
|
||||
let lifetime_span: Option<Span> =
|
||||
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,
|
||||
});
|
||||
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) {
|
||||
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::BrAnon(_) | ty::BrEnv => "an anonymous lifetime".to_string(),
|
||||
};
|
||||
|
||||
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
|
||||
// in the return type but **also** be unconstrained is
|
||||
// if it only appears in "associated types" in the
|
||||
|
@ -628,24 +628,40 @@ fn compare_number_of_generics<'tcx>(
|
||||
let mut err_occurred = None;
|
||||
for (kind, trait_count, impl_count) in matchings {
|
||||
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_item = tcx.hir().expect_trait_item(def_id);
|
||||
if trait_item.generics.params.is_empty() {
|
||||
(Some(vec![trait_item.generics.span]), vec![])
|
||||
} else {
|
||||
let arg_spans: Vec<Span> =
|
||||
trait_item.generics.params.iter().map(|p| p.span).collect();
|
||||
let impl_trait_spans: Vec<Span> = trait_item
|
||||
.generics
|
||||
.params
|
||||
.iter()
|
||||
.filter_map(|p| match p.kind {
|
||||
GenericParamKind::Type { synthetic: true, .. } => Some(p.span),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
(Some(arg_spans), impl_trait_spans)
|
||||
}
|
||||
let arg_spans: Vec<Span> = arg_spans(trait_.kind, trait_item.generics);
|
||||
let impl_trait_spans: Vec<Span> = trait_item
|
||||
.generics
|
||||
.params
|
||||
.iter()
|
||||
.filter_map(|p| match p.kind {
|
||||
GenericParamKind::Type { synthetic: true, .. } => Some(p.span),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
(Some(arg_spans), impl_trait_spans)
|
||||
} else {
|
||||
(trait_span.map(|s| vec![s]), vec![])
|
||||
};
|
||||
@ -660,23 +676,7 @@ fn compare_number_of_generics<'tcx>(
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
let spans = if impl_item.generics.params.is_empty() {
|
||||
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 spans = arg_spans(impl_.kind, impl_item.generics);
|
||||
let span = spans.first().copied();
|
||||
|
||||
let mut err = tcx.sess.struct_span_err_with_code(
|
||||
|
@ -45,7 +45,7 @@ where
|
||||
}
|
||||
|
||||
fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
|
||||
//~^ ERROR: missing lifetime specifier
|
||||
//~^ ERROR `'_` cannot be used here [E0637]
|
||||
//~| ERROR: missing lifetime specifier
|
||||
DocumentImpl {}
|
||||
}
|
||||
|
@ -1,14 +1,8 @@
|
||||
error[E0106]: missing lifetime specifier
|
||||
error[E0637]: `'_` cannot be used here
|
||||
--> $DIR/issue-70304.rs:47:41
|
||||
|
|
||||
LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
|
||||
| ^^ 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 create_doc() -> impl Document<Cursor<'static> = DocCursorImpl<'_>> {
|
||||
| ~~~~~~~
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $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
|
||||
|
||||
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>) { }
|
||||
//~^ ERROR missing lifetime specifier
|
||||
//~^ ERROR `'_` cannot be used here [E0637]
|
||||
|
||||
fn bar(x: &impl for<'a> Foo<Item<'a> = &'_ u32>) { }
|
||||
//~^ 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
|
||||
|
|
||||
LL | fn foo(x: &impl Foo<Item<'_> = u32>) { }
|
||||
| ^^ expected named lifetime parameter
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | fn foo<'a>(x: &impl Foo<Item<'a> = u32>) { }
|
||||
| ++++ ~~
|
||||
| ^^ `'_` is a reserved lifetime name
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $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
|
||||
|
||||
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
|
||||
|
||||
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>;
|
||||
| -- --
|
||||
@ -16,7 +16,9 @@ LL | type B<'a, 'b>;
|
||||
| expected 0 type parameters
|
||||
...
|
||||
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
|
||||
--> $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);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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,)>`
|
||||
note: this closure does not fulfill the lifetime requirements
|
||||
--> $DIR/issue-71955.rs:45:24
|
||||
@ -61,7 +61,7 @@ error[E0308]: mismatched types
|
||||
LL | foo(baz, "string", |s| s.0.len() == 5);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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<'_>,)>`
|
||||
note: this closure does not fulfill the lifetime requirements
|
||||
--> $DIR/issue-71955.rs:48:24
|
||||
|
@ -6,8 +6,8 @@ trait SomeTrait<'a> {
|
||||
|
||||
fn give_me_ice<T>() {
|
||||
callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
|
||||
//~^ ERROR the trait bound `T: SomeTrait<'_>` 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]
|
||||
//~| ERROR the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied [E0277]
|
||||
}
|
||||
|
||||
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
|
||||
|
|
||||
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`
|
||||
|
|
||||
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
|
||||
|
|
||||
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`
|
||||
|
|
||||
LL | fn give_me_ice<T: SomeTrait<'_>>() {
|
||||
| +++++++++++++++
|
||||
LL | fn give_me_ice<T: for<'r> SomeTrait<'r>>() {
|
||||
| +++++++++++++++++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -13,6 +13,10 @@ impl StaticTrait for Box<dyn Debug> { }
|
||||
trait NotStaticTrait { }
|
||||
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) {
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
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>) {
|
||||
| -- - `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
|
||||
|
|
||||
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
|
||||
--> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:3
|
||||
|
Loading…
Reference in New Issue
Block a user