improve the suggestion of generic_bound_failure

This commit is contained in:
Ali MJ Al-Nasrawy 2023-09-08 01:35:51 +00:00
parent 6d271692b0
commit 5be0b2283a
28 changed files with 696 additions and 384 deletions

View File

@ -66,13 +66,12 @@
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::Node;
use rustc_middle::dep_graph::DepContext;
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
use rustc_middle::ty::{
self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
TypeVisitable, TypeVisitableExt,
self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable,
TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
};
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
@ -2317,126 +2316,6 @@ pub fn construct_generic_bound_failure(
bound_kind: GenericKind<'tcx>,
sub: Region<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
// Attempt to obtain the span of the parameter so we can
// suggest adding an explicit lifetime bound to it.
let generics = self.tcx.generics_of(generic_param_scope);
// type_param_span is (span, has_bounds)
let mut is_synthetic = false;
let mut ast_generics = None;
let type_param_span = match bound_kind {
GenericKind::Param(ref param) => {
// Account for the case where `param` corresponds to `Self`,
// which doesn't have the expected type argument.
if !(generics.has_self && param.index == 0) {
let type_param = generics.type_param(param, self.tcx);
is_synthetic = type_param.kind.is_synthetic();
type_param.def_id.as_local().map(|def_id| {
// Get the `hir::Param` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: 'a'b`,
// instead we suggest `T: 'a + 'b` in that case.
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
ast_generics = self.tcx.hir().get_generics(hir_id.owner.def_id);
let bounds =
ast_generics.and_then(|g| g.bounds_span_for_suggestions(def_id));
// `sp` only covers `T`, change it so that it covers
// `T:` when appropriate
if let Some(span) = bounds {
(span, true)
} else {
let sp = self.tcx.def_span(def_id);
(sp.shrink_to_hi(), false)
}
})
} else {
None
}
}
_ => None,
};
let new_lt = {
let mut possible = (b'a'..=b'z').map(|c| format!("'{}", c as char));
let lts_names =
iter::successors(Some(generics), |g| g.parent.map(|p| self.tcx.generics_of(p)))
.flat_map(|g| &g.params)
.filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
.map(|p| p.name.as_str())
.collect::<Vec<_>>();
possible
.find(|candidate| !lts_names.contains(&&candidate[..]))
.unwrap_or("'lt".to_string())
};
let mut add_lt_suggs: Vec<Option<_>> = vec![];
if is_synthetic {
if let Some(ast_generics) = ast_generics {
let named_lifetime_param_exist = ast_generics.params.iter().any(|p| {
matches!(
p.kind,
hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
)
});
if named_lifetime_param_exist && let [param, ..] = ast_generics.params
{
add_lt_suggs.push(Some((
self.tcx.def_span(param.def_id).shrink_to_lo(),
format!("{new_lt}, "),
)));
} else {
add_lt_suggs
.push(Some((ast_generics.span.shrink_to_hi(), format!("<{new_lt}>"))));
}
}
} else {
if let [param, ..] = &generics.params[..] && let Some(def_id) = param.def_id.as_local()
{
add_lt_suggs
.push(Some((self.tcx.def_span(def_id).shrink_to_lo(), format!("{new_lt}, "))));
}
}
if let Some(ast_generics) = ast_generics {
for p in ast_generics.params {
if p.is_elided_lifetime() {
if self
.tcx
.sess
.source_map()
.span_to_prev_source(p.span.shrink_to_hi())
.ok()
.is_some_and(|s| *s.as_bytes().last().unwrap() == b'&')
{
add_lt_suggs
.push(Some(
(
p.span.shrink_to_hi(),
if let Ok(snip) = self.tcx.sess.source_map().span_to_next_source(p.span)
&& snip.starts_with(' ')
{
new_lt.to_string()
} else {
format!("{new_lt} ")
}
)
));
} else {
add_lt_suggs.push(Some((p.span.shrink_to_hi(), format!("<{new_lt}>"))));
}
}
}
}
let labeled_user_string = match bound_kind {
GenericKind::Param(ref p) => format!("the parameter type `{p}`"),
GenericKind::Alias(ref p) => match p.kind(self.tcx) {
ty::AliasKind::Projection | ty::AliasKind::Inherent => {
format!("the associated type `{p}`")
}
ty::AliasKind::Weak => format!("the type alias `{p}`"),
ty::AliasKind::Opaque => format!("the opaque type `{p}`"),
},
};
if let Some(SubregionOrigin::CompareImplItemObligation {
span,
impl_item_def_id,
@ -2451,165 +2330,33 @@ pub fn construct_generic_bound_failure(
);
}
fn binding_suggestion<'tcx, S: fmt::Display>(
err: &mut Diagnostic,
type_param_span: Option<(Span, bool)>,
bound_kind: GenericKind<'tcx>,
sub: S,
add_lt_suggs: Vec<Option<(Span, String)>>,
) {
let msg = "consider adding an explicit lifetime bound";
if let Some((sp, has_lifetimes)) = type_param_span {
let suggestion =
if has_lifetimes { format!(" + {sub}") } else { format!(": {sub}") };
let mut suggestions = vec![(sp, suggestion)];
for add_lt_sugg in add_lt_suggs.into_iter().flatten() {
suggestions.push(add_lt_sugg);
let labeled_user_string = match bound_kind {
GenericKind::Param(ref p) => format!("the parameter type `{p}`"),
GenericKind::Alias(ref p) => match p.kind(self.tcx) {
ty::AliasKind::Projection | ty::AliasKind::Inherent => {
format!("the associated type `{p}`")
}
err.multipart_suggestion_verbose(
format!("{msg}..."),
suggestions,
Applicability::MaybeIncorrect, // Issue #41966
);
} else {
let consider = format!("{msg} `{bound_kind}: {sub}`...");
err.help(consider);
}
}
let new_binding_suggestion =
|err: &mut Diagnostic, type_param_span: Option<(Span, bool)>| {
let msg = "consider introducing an explicit lifetime bound";
if let Some((sp, has_lifetimes)) = type_param_span {
let suggestion =
if has_lifetimes { format!(" + {new_lt}") } else { format!(": {new_lt}") };
let mut sugg =
vec![(sp, suggestion), (span.shrink_to_hi(), format!(" + {new_lt}"))];
for lt in add_lt_suggs.clone().into_iter().flatten() {
sugg.push(lt);
sugg.rotate_right(1);
}
// `MaybeIncorrect` due to issue #41966.
err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
}
};
#[derive(Debug)]
enum SubOrigin<'hir> {
GAT(&'hir hir::Generics<'hir>),
Impl,
Trait,
Fn,
Unknown,
}
let sub_origin = 'origin: {
match *sub {
ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. }) => {
let node = self.tcx.hir().get_if_local(def_id).unwrap();
match node {
Node::GenericParam(param) => {
for h in self.tcx.hir().parent_iter(param.hir_id) {
break 'origin match h.1 {
Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Type(..),
generics,
..
})
| Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Type(..),
generics,
..
}) => SubOrigin::GAT(generics),
Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Fn(..),
..
})
| Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(..),
..
})
| Node::Item(hir::Item {
kind: hir::ItemKind::Fn(..), ..
}) => SubOrigin::Fn,
Node::Item(hir::Item {
kind: hir::ItemKind::Trait(..),
..
}) => SubOrigin::Trait,
Node::Item(hir::Item {
kind: hir::ItemKind::Impl(..), ..
}) => SubOrigin::Impl,
_ => continue,
};
}
}
_ => {}
}
}
_ => {}
}
SubOrigin::Unknown
ty::AliasKind::Weak => format!("the type alias `{p}`"),
ty::AliasKind::Opaque => format!("the opaque type `{p}`"),
},
};
debug!(?sub_origin);
let mut err = match (*sub, sub_origin) {
// In the case of GATs, we have to be careful. If we a type parameter `T` on an impl,
// but a lifetime `'a` on an associated type, then we might need to suggest adding
// `where T: 'a`. Importantly, this is on the GAT span, not on the `T` declaration.
(ty::ReEarlyBound(ty::EarlyBoundRegion { name: _, .. }), SubOrigin::GAT(generics)) => {
// Does the required lifetime have a nice name we can print?
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0309,
"{} may not live long enough",
labeled_user_string
);
let pred = format!("{bound_kind}: {sub}");
let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred,);
err.span_suggestion(
generics.tail_span_for_predicate_suggestion(),
"consider adding a where clause",
suggestion,
Applicability::MaybeIncorrect,
);
err
}
(
ty::ReEarlyBound(ty::EarlyBoundRegion { name, .. })
| ty::ReFree(ty::FreeRegion { bound_region: ty::BrNamed(_, name), .. }),
_,
) if name != kw::UnderscoreLifetime => {
// Does the required lifetime have a nice name we can print?
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0309,
"{} may not live long enough",
labeled_user_string
);
// Explicitly use the name instead of `sub`'s `Display` impl. The `Display` impl
// for the bound is not suitable for suggestions when `-Zverbose` is set because it
// uses `Debug` output, so we handle it specially here so that suggestions are
// always correct.
binding_suggestion(&mut err, type_param_span, bound_kind, name, vec![]);
err
}
(ty::ReStatic, _) => {
// Does the required lifetime have a nice name we can print?
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0310,
"{} may not live long enough",
labeled_user_string
);
binding_suggestion(&mut err, type_param_span, bound_kind, "'static", vec![]);
err
}
let mut err = match sub.kind() {
ty::ReEarlyBound(_) | ty::ReFree(_) if sub.has_name() => struct_span_err!(
self.tcx.sess,
span,
E0309,
"{} may not live long enough",
labeled_user_string
),
ty::ReStatic => struct_span_err!(
self.tcx.sess,
span,
E0310,
"{} may not live long enough",
labeled_user_string
),
_ => {
// If not, be less specific.
let mut err = struct_span_err!(
self.tcx.sess,
span,
@ -2625,37 +2372,192 @@ enum SubOrigin<'hir> {
"...",
None,
);
if let Some(infer::RelateParamBound(_, t, _)) = origin {
let t = self.resolve_vars_if_possible(t);
match t.kind() {
// We've got:
// fn get_later<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
// suggest:
// fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
ty::Closure(..) | ty::Alias(ty::Opaque, ..) => {
new_binding_suggestion(&mut err, type_param_span);
}
_ => {
binding_suggestion(
&mut err,
type_param_span,
bound_kind,
new_lt,
add_lt_suggs,
);
}
}
}
err
}
};
'suggestion: {
let msg = "consider adding an explicit lifetime bound";
if (bound_kind, sub).has_infer_regions()
|| (bound_kind, sub).has_placeholders()
|| !bound_kind.is_suggestable(self.tcx, false)
{
let lt_name = sub.get_name_or_anon().to_string();
err.help(format!("{msg} `{bound_kind}: {lt_name}`..."));
break 'suggestion;
}
let mut generic_param_scope = generic_param_scope;
while self.tcx.def_kind(generic_param_scope) == DefKind::OpaqueTy {
generic_param_scope = self.tcx.local_parent(generic_param_scope);
}
// type_param_sugg_span is (span, has_bounds)
let (type_scope, type_param_sugg_span) = match bound_kind {
GenericKind::Param(ref param) => {
let generics = self.tcx.generics_of(generic_param_scope);
let def_id = generics.type_param(param, self.tcx).def_id.expect_local();
let scope = self.tcx.local_def_id_to_hir_id(def_id).owner.def_id;
// Get the `hir::Param` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: 'a'b`,
// instead we suggest `T: 'a + 'b` in that case.
let hir_generics = self.tcx.hir().get_generics(scope).unwrap();
let sugg_span = match hir_generics.bounds_span_for_suggestions(def_id) {
Some(span) => Some((span, true)),
// If `param` corresponds to `Self`, no usable suggestion span.
None if generics.has_self && param.index == 0 => None,
None => Some((self.tcx.def_span(def_id).shrink_to_hi(), false)),
};
(scope, sugg_span)
}
_ => (generic_param_scope, None),
};
let suggestion_scope = {
let lifetime_scope = match sub.kind() {
ty::ReStatic => hir::def_id::CRATE_DEF_ID,
_ => match self.tcx.is_suitable_region(sub) {
Some(info) => info.def_id,
None => generic_param_scope,
},
};
match self.tcx.is_descendant_of(type_scope.into(), lifetime_scope.into()) {
true => type_scope,
false => lifetime_scope,
}
};
let mut suggs = vec![];
let lt_name = self.suggest_name_region(sub, &mut suggs);
if let Some((sp, has_lifetimes)) = type_param_sugg_span
&& suggestion_scope == type_scope
{
let suggestion =
if has_lifetimes { format!(" + {lt_name}") } else { format!(": {lt_name}") };
suggs.push((sp, suggestion))
} else {
let generics = self.tcx.hir().get_generics(suggestion_scope).unwrap();
let pred = format!("{bound_kind}: {lt_name}");
let suggestion = format!("{} {}", generics.add_where_or_trailing_comma(), pred,);
suggs.push((generics.tail_span_for_predicate_suggestion(), suggestion))
}
err.multipart_suggestion_verbose(
format!("{msg}..."),
suggs,
Applicability::MaybeIncorrect, // Issue #41966
);
}
if let Some(origin) = origin {
self.note_region_origin(&mut err, &origin);
}
err
}
pub fn suggest_name_region(
&self,
lifetime: Region<'tcx>,
add_lt_suggs: &mut Vec<(Span, String)>,
) -> String {
struct LifetimeReplaceVisitor<'tcx, 'a> {
tcx: TyCtxt<'tcx>,
needle: hir::LifetimeName,
new_lt: &'a str,
add_lt_suggs: &'a mut Vec<(Span, String)>,
}
impl<'hir, 'tcx> hir::intravisit::Visitor<'hir> for LifetimeReplaceVisitor<'tcx, '_> {
fn visit_lifetime(&mut self, lt: &'hir hir::Lifetime) {
if lt.res == self.needle {
let (pos, span) = lt.suggestion_position();
let new_lt = &self.new_lt;
let sugg = match pos {
hir::LifetimeSuggestionPosition::Normal => format!("{new_lt}"),
hir::LifetimeSuggestionPosition::Ampersand => format!("{new_lt} "),
hir::LifetimeSuggestionPosition::ElidedPath => format!("<{new_lt}>"),
hir::LifetimeSuggestionPosition::ElidedPathArgument => {
format!("{new_lt}, ")
}
hir::LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lt}"),
};
self.add_lt_suggs.push((span, sugg));
}
}
fn visit_ty(&mut self, ty: &'hir hir::Ty<'hir>) {
let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind else {
return hir::intravisit::walk_ty(self, ty);
};
let opaque_ty = self.tcx.hir().item(item_id).expect_opaque_ty();
if let Some(&(_, b)) =
opaque_ty.lifetime_mapping.iter().find(|&(a, _)| a.res == self.needle)
{
let prev_needle =
std::mem::replace(&mut self.needle, hir::LifetimeName::Param(b));
for bound in opaque_ty.bounds {
self.visit_param_bound(bound);
}
self.needle = prev_needle;
}
}
}
let (lifetime_def_id, lifetime_scope) = match self.tcx.is_suitable_region(lifetime) {
Some(info) if !lifetime.has_name() => {
(info.boundregion.get_id().unwrap().expect_local(), info.def_id)
}
_ => return lifetime.get_name_or_anon().to_string(),
};
let new_lt = {
let generics = self.tcx.generics_of(lifetime_scope);
let mut used_names =
iter::successors(Some(generics), |g| g.parent.map(|p| self.tcx.generics_of(p)))
.flat_map(|g| &g.params)
.filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
.map(|p| p.name)
.collect::<Vec<_>>();
if let Some(hir_id) = self.tcx.opt_local_def_id_to_hir_id(lifetime_scope) {
// consider late-bound lifetimes ...
used_names.extend(self.tcx.late_bound_vars(hir_id).into_iter().filter_map(|p| {
match p {
ty::BoundVariableKind::Region(lt) => lt.get_name(),
_ => None,
}
}))
}
(b'a'..=b'z')
.map(|c| format!("'{}", c as char))
.find(|candidate| !used_names.iter().any(|e| e.as_str() == candidate))
.unwrap_or("'lt".to_string())
};
let mut visitor = LifetimeReplaceVisitor {
tcx: self.tcx,
needle: hir::LifetimeName::Param(lifetime_def_id),
add_lt_suggs,
new_lt: &new_lt,
};
match self.tcx.hir().expect_owner(lifetime_scope) {
hir::OwnerNode::Item(i) => visitor.visit_item(i),
hir::OwnerNode::ForeignItem(i) => visitor.visit_foreign_item(i),
hir::OwnerNode::ImplItem(i) => visitor.visit_impl_item(i),
hir::OwnerNode::TraitItem(i) => visitor.visit_trait_item(i),
hir::OwnerNode::Crate(_) => bug!("OwnerNode::Crate doesn't not have generics"),
}
let ast_generics = self.tcx.hir().get_generics(lifetime_scope).unwrap();
let sugg = ast_generics
.span_for_lifetime_suggestion()
.map(|span| (span, format!("{new_lt}, ")))
.unwrap_or_else(|| (ast_generics.span, format!("<{new_lt}>")));
add_lt_suggs.push(sugg);
new_lt
}
fn report_sub_sup_conflict(
&self,
var_origin: RegionVariableOrigin,

View File

@ -1057,16 +1057,21 @@ pub fn local_crate_exports_generics(self) -> bool {
}
/// Returns the `DefId` and the `BoundRegionKind` corresponding to the given region.
pub fn is_suitable_region(self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
let (suitable_region_binding_scope, bound_region) = match *region {
ty::ReFree(ref free_region) => {
(free_region.scope.expect_local(), free_region.bound_region)
pub fn is_suitable_region(self, mut region: Region<'tcx>) -> Option<FreeRegionInfo> {
let (suitable_region_binding_scope, bound_region) = loop {
let def_id = match region.kind() {
ty::ReFree(fr) => fr.bound_region.get_id()?.as_local()?,
ty::ReEarlyBound(ebr) => ebr.def_id.expect_local(),
_ => return None, // not a free region
};
let scope = self.local_parent(def_id);
if self.def_kind(scope) == DefKind::OpaqueTy {
// Lifetime params of opaque types are synthetic and thus irrelevant to
// diagnostics. Map them back to their origin!
region = self.map_rpit_lifetime_to_fn_lifetime(def_id);
continue;
}
ty::ReEarlyBound(ref ebr) => (
self.local_parent(ebr.def_id.expect_local()),
ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name),
),
_ => return None, // not a free region
break (scope, ty::BrNamed(def_id.into(), self.item_name(def_id.into())));
};
let is_impl_item = match self.hir().find_by_def_id(suitable_region_binding_scope) {
@ -1074,7 +1079,7 @@ pub fn is_suitable_region(self, region: Region<'tcx>) -> Option<FreeRegionInfo>
Some(Node::ImplItem(..)) => {
self.is_bound_region_in_impl_item(suitable_region_binding_scope)
}
_ => return None,
_ => false,
};
Some(FreeRegionInfo {

View File

@ -2,9 +2,12 @@ error[E0309]: the parameter type `T` may not live long enough
--> $DIR/regionck-1.rs:9:30
|
LL | type NoTyOutliv<'a, T> = &'a T;
| ^^^^^- help: consider adding a where clause: `where T: 'a`
| |
| ...so that the reference type `&'a T` does not outlive the data it points at
| ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
LL | type NoTyOutliv<'a, T: 'a> = &'a T;
| ++++
error[E0491]: in type `&'a &'b ()`, reference has a longer lifetime than the data it references
--> $DIR/regionck-1.rs:10:31

View File

@ -14,6 +14,10 @@ note: ...so that the reference type `&(T, U)` does not outlive the data it point
|
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | async fn foo<'a>(&'a self) -> &'a (T, U) where T: Debug + Sized, U: Hash, U: 'a;
| ++++ ++ ++ +++++++
error[E0311]: the parameter type `T` may not live long enough
--> $DIR/async-generics-and-bounds.rs:12:5
@ -31,6 +35,10 @@ note: ...so that the reference type `&(T, U)` does not outlive the data it point
|
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | async fn foo<'a>(&'a self) -> &'a (T, U) where T: Debug + Sized, U: Hash, T: 'a;
| ++++ ++ ++ +++++++
error: aborting due to 2 previous errors

View File

@ -14,6 +14,10 @@ note: ...so that the reference type `&(T, U)` does not outlive the data it point
|
LL | async fn foo(&self) -> &(T, U);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | async fn foo<'a>(&'a self) -> &'a (T, U) where U: 'a;
| ++++ ++ ++ +++++++++++
error[E0311]: the parameter type `T` may not live long enough
--> $DIR/async-generics.rs:9:5
@ -31,6 +35,10 @@ note: ...so that the reference type `&(T, U)` does not outlive the data it point
|
LL | async fn foo(&self) -> &(T, U);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | async fn foo<'a>(&'a self) -> &'a (T, U) where T: 'a;
| ++++ ++ ++ +++++++++++
error: aborting due to 2 previous errors

View File

@ -2,7 +2,7 @@
#![allow(warnings)]
fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() {
fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
with_restriction::<T>(x) //~ ERROR E0311
}

View File

@ -16,8 +16,8 @@ LL | with_restriction::<T>(x)
| ^^^^^^^^^^^^^^^^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() {
| +++ ++++ ++
LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
| +++ ++++ ++ ++
error: aborting due to previous error

View File

@ -2,9 +2,12 @@ error[E0309]: the parameter type `T` may not live long enough
--> $DIR/issue-84931.rs:14:21
|
LL | type Item<'a> = &'a mut T;
| ^^^^^^^^^- help: consider adding a where clause: `where T: 'a`
| |
| ...so that the reference type `&'a mut T` does not outlive the data it points at
| ^^^^^^^^^ ...so that the reference type `&'a mut T` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound...
|
LL | type Item<'a> = &'a mut T where T: 'a;
| +++++++++++
error: aborting due to previous error

View File

@ -17,8 +17,8 @@ LL | fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
|
help: consider adding an explicit lifetime bound...
|
LL | impl<K: 'a> Nested<K> {
| ++++
LL | fn generic_in_parent<'a, L: X<&'a Nested<K>>>() where K: 'a {
| +++++++++++
error[E0309]: the parameter type `M` may not live long enough
--> $DIR/lifetime-doesnt-live-long-enough.rs:44:36
@ -39,17 +39,19 @@ LL | fn foo<'a, L: X<&'a Nested<K>>>();
|
help: consider adding an explicit lifetime bound...
|
LL | trait X<K: 'a>: Sized {
| ++++
LL | fn foo<'a, L: X<&'a Nested<K>>>() where K: 'a;
| +++++++++++
error[E0309]: the parameter type `Self` may not live long enough
--> $DIR/lifetime-doesnt-live-long-enough.rs:28:19
|
LL | fn bar<'a, L: X<&'a Nested<Self>>>();
| ^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<Self>` does not outlive the data it points at
|
= help: consider adding an explicit lifetime bound `Self: 'a`...
= note: ...so that the reference type `&'a Nested<Self>` does not outlive the data it points at
help: consider adding an explicit lifetime bound...
|
LL | fn bar<'a, L: X<&'a Nested<Self>>>() where Self: 'a;
| ++++++++++++++
error[E0309]: the parameter type `L` may not live long enough
--> $DIR/lifetime-doesnt-live-long-enough.rs:32:22

View File

@ -2,7 +2,7 @@
#![allow(warnings)]
fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() {
fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
with_restriction::<T>(x) //~ ERROR the parameter type `T` may not live long enough
}

View File

@ -16,8 +16,8 @@ LL | with_restriction::<T>(x)
| ^^^^^^^^^^^^^^^^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() {
| +++ ++++ ++
LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
| +++ ++++ ++ ++
error: aborting due to previous error

View File

@ -26,10 +26,12 @@ error[E0309]: the associated type `<T as Iterator>::Item` may not live long enou
--> $DIR/projection-no-regions-closure.rs:25:31
|
LL | with_signature(x, |mut y| Box::new(y.next()))
| ^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^ ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
|
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
= note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
help: consider adding an explicit lifetime bound...
|
LL | T: Iterator, <T as Iterator>::Item: 'a
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: external requirements
--> $DIR/projection-no-regions-closure.rs:34:23
@ -83,10 +85,12 @@ error[E0309]: the associated type `<T as Iterator>::Item` may not live long enou
--> $DIR/projection-no-regions-closure.rs:42:31
|
LL | with_signature(x, |mut y| Box::new(y.next()))
| ^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^ ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
|
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
= note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
help: consider adding an explicit lifetime bound...
|
LL | T: 'b + Iterator, <T as Iterator>::Item: 'a
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: external requirements
--> $DIR/projection-no-regions-closure.rs:52:23

View File

@ -2,19 +2,23 @@ error[E0309]: the associated type `<T as Iterator>::Item` may not live long enou
--> $DIR/projection-no-regions-fn.rs:13:5
|
LL | Box::new(x.next())
| ^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^ ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
|
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
= note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
help: consider adding an explicit lifetime bound...
|
LL | T: Iterator, <T as Iterator>::Item: 'a
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough
--> $DIR/projection-no-regions-fn.rs:28:5
|
LL | Box::new(x.next())
| ^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^ ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
|
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
= note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
help: consider adding an explicit lifetime bound...
|
LL | T: 'b + Iterator, <T as Iterator>::Item: 'a
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors

View File

@ -2,37 +2,45 @@ error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:15:5
|
LL | Box::new(item)
| ^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
|
= help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'static`...
= note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
help: consider adding an explicit lifetime bound...
|
LL | fn bad1<T: Iter>(v: T) -> Box<dyn X + 'static> where <T as Iter>::Item: 'static
| ++++++++++++++++++++++++++++++++
error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:22:5
|
LL | Box::new(item)
| ^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
|
= help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'static`...
= note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
help: consider adding an explicit lifetime bound...
|
LL | where Box<T::Item> : X, <T as Iter>::Item: 'static
| ++++++++++++++++++++++++++++
error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:28:5
|
LL | Box::new(item)
| ^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
|
= help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'a`...
= note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
help: consider adding an explicit lifetime bound...
|
LL | fn bad3<'a, T: Iter>(v: T) -> Box<dyn X + 'a> where <T as Iter>::Item: 'a
| +++++++++++++++++++++++++++
error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
--> $DIR/regions-close-associated-type-into-object.rs:35:5
|
LL | Box::new(item)
| ^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
|
= help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'a`...
= note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
help: consider adding an explicit lifetime bound...
|
LL | where Box<T::Item> : X, <T as Iter>::Item: 'a
| +++++++++++++++++++++++
error: aborting due to 4 previous errors

View File

@ -2,10 +2,12 @@ error[E0309]: the parameter type `Self` may not live long enough
--> $DIR/regions-infer-bound-from-trait-self.rs:46:9
|
LL | check_bound(x, self)
| ^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^ ...so that the type `Self` will meet its required lifetime bounds
|
= help: consider adding an explicit lifetime bound `Self: 'a`...
= note: ...so that the type `Self` will meet its required lifetime bounds
help: consider adding an explicit lifetime bound...
|
LL | trait InheritsFromNothing<'a> : Sized where Self: 'a {
| ++++++++++++++
error: aborting due to previous error

View File

@ -2,7 +2,7 @@
#![allow(warnings)]
fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized` must be valid for the anonymous lifetime defined here...
fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + 'a { //~ NOTE the parameter type `impl Sized` must be valid for the anonymous lifetime defined here...
//~^ HELP consider adding an explicit lifetime bound
(d, p)
//~^ ERROR the parameter type `impl Sized` may not live long enough
@ -15,14 +15,14 @@ fn foo1<'b>(d: impl Sized + 'b, p: &'b mut ()) -> impl Sized + '_ {
//~^ ERROR the parameter type `impl Sized` may not live long enough
}
fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here...
fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + 'b { //~ NOTE the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here...
//~^ HELP consider adding an explicit lifetime bound
(d, p)
//~^ ERROR the parameter type `impl Sized + 'a` may not live long enough
//~| NOTE ...so that the type `impl Sized + 'a` will meet its required lifetime bounds
}
fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + 'a { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
//~^ HELP consider adding an explicit lifetime bound
(d, p)
//~^ ERROR the parameter type `T` may not live long enough
@ -35,7 +35,7 @@ fn bar1<'b, T : Sized + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ {
//~^ ERROR the parameter type `T` may not live long enough
}
fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + 'b { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
//~^ HELP consider adding an explicit lifetime bound
(d, p)
//~^ ERROR the parameter type `T` may not live long enough

View File

@ -16,8 +16,8 @@ LL | (d, p)
| ^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + '_ {
| ++++ ++++ ++
LL | fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + 'a {
| ++++ ++++ ++ ~~
error[E0309]: the parameter type `impl Sized` may not live long enough
--> $DIR/issue-105544.rs:14:5
@ -48,8 +48,8 @@ LL | (d, p)
| ^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + '_ {
| +++ ++++ ++
LL | fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + 'b {
| +++ ++++ ++ ~~
error[E0311]: the parameter type `T` may not live long enough
--> $DIR/issue-105544.rs:27:5
@ -69,8 +69,8 @@ LL | (d, p)
| ^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + '_ {
| +++ ++++ ++
LL | fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + 'a {
| +++ ++++ ++ ~~
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/issue-105544.rs:34:5
@ -101,8 +101,8 @@ LL | (d, p)
| ^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ {
| +++ ++++ ++
LL | fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + 'b {
| +++ ++++ ++ ~~
error: aborting due to 6 previous errors

View File

@ -19,11 +19,16 @@ trait Test {
fn test(&self);
}
fn func<'a, T: Test + 'a>(foo: &'a Foo<'a>, t: T) {
fn func<'a, T: Test + 'a>(_dummy: &Foo, foo: &Foo<'a>, t: T) {
foo.bar(move |_| {
//~^ ERROR the parameter type `T` may not live long enough
t.test();
});
}
// Test that the suggested fix does not overconstrain `func`. See #115375.
fn test_func<'a, T: Test + 'a>(dummy: &Foo, foo: &Foo<'a>, t: T) {
func(dummy, foo, t);
}
fn main() {}

View File

@ -19,11 +19,16 @@ trait Test {
fn test(&self);
}
fn func<T: Test>(foo: &Foo, t: T) {
fn func<T: Test>(_dummy: &Foo, foo: &Foo, t: T) {
foo.bar(move |_| {
//~^ ERROR the parameter type `T` may not live long enough
t.test();
});
}
// Test that the suggested fix does not overconstrain `func`. See #115375.
fn test_func<'a, T: Test + 'a>(dummy: &Foo, foo: &Foo<'a>, t: T) {
func(dummy, foo, t);
}
fn main() {}

View File

@ -8,10 +8,10 @@ LL | | });
| |______^
|
note: the parameter type `T` must be valid for the anonymous lifetime defined here...
--> $DIR/missing-lifetimes-in-signature-2.rs:22:24
--> $DIR/missing-lifetimes-in-signature-2.rs:22:38
|
LL | fn func<T: Test>(foo: &Foo, t: T) {
| ^^^
LL | fn func<T: Test>(_dummy: &Foo, foo: &Foo, t: T) {
| ^^^
note: ...so that the type `T` will meet its required lifetime bounds
--> $DIR/missing-lifetimes-in-signature-2.rs:23:5
|
@ -22,8 +22,8 @@ LL | | });
| |______^
help: consider adding an explicit lifetime bound...
|
LL | fn func<'a, T: Test + 'a>(foo: &'a Foo<'a>, t: T) {
| +++ ++++ ++ ++++
LL | fn func<'a, T: Test + 'a>(_dummy: &Foo, foo: &Foo<'a>, t: T) {
| +++ ++++ ++++
error: aborting due to previous error

View File

@ -49,7 +49,7 @@ LL | | }
| |_____^
help: consider adding an explicit lifetime bound...
|
LL ~ fn bar<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_
LL ~ fn bar<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
LL | where
LL ~ G: Get<T> + 'a,
|
@ -78,8 +78,8 @@ LL | | }
| |_____^
help: consider adding an explicit lifetime bound...
|
LL | fn qux<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + '_
| +++ ++++ ++
LL | fn qux<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + 'b
| +++ ++++ ++ ~~
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:61:9
@ -105,8 +105,8 @@ LL | | }
| |_________^
help: consider adding an explicit lifetime bound...
|
LL | fn qux<'c, 'b, G: Get<T> + 'b + 'c, T>(g: G, dest: &'c mut T) -> impl FnOnce() + '_ {
| +++ ++++ ++
LL | fn qux<'c, 'b, G: Get<T> + 'b + 'c, T>(g: G, dest: &'c mut T) -> impl FnOnce() + 'c {
| +++ ++++ ++ ~~
error[E0311]: the parameter type `G` may not live long enough
--> $DIR/missing-lifetimes-in-signature.rs:73:5
@ -134,8 +134,8 @@ LL | | }
| |_____^
help: consider adding an explicit lifetime bound...
|
LL | fn bat<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + '_ + 'a
| +++ ++++ ++
LL | fn bat<'b, 'a, G: 'a + 'b, T>(g: G, dest: &'b mut T) -> impl FnOnce() + 'b + 'a
| +++ ++++ ++ ~~
error[E0621]: explicit lifetime required in the type of `dest`
--> $DIR/missing-lifetimes-in-signature.rs:73:5

View File

@ -0,0 +1,47 @@
// Make sure we suggest the bound `T: 'a` in the correct scope:
// trait, impl or associated fn.
// run-rustfix
struct Inv<'a>(Option<*mut &'a u8>);
fn check_bound<'a, A: 'a>(_: A, _: Inv<'a>) {}
trait Trait1<'a>: Sized where Self: 'a {
fn foo(self, lt: Inv<'a>) {
check_bound(self, lt)
//~^ ERROR parameter type `Self` may not live long enough
}
}
trait Trait2: Sized {
fn foo<'a>(self, lt: Inv<'a>) where Self: 'a {
check_bound(self, lt)
//~^ ERROR parameter type `Self` may not live long enough
}
}
trait Trait3<T> {
fn foo<'a>(arg: T, lt: Inv<'a>) where T: 'a {
check_bound(arg, lt)
//~^ ERROR parameter type `T` may not live long enough
}
}
trait Trait4<'a> {
fn foo<T: 'a>(arg: T, lt: Inv<'a>) {
check_bound(arg, lt)
//~^ ERROR parameter type `T` may not live long enough
}
}
trait Trait5<'a> {
fn foo(self, _: Inv<'a>);
}
impl<'a, T: 'a> Trait5<'a> for T {
fn foo(self, lt: Inv<'a>) {
check_bound(self, lt);
//~^ ERROR parameter type `T` may not live long enough
}
}
fn main() {}

View File

@ -0,0 +1,47 @@
// Make sure we suggest the bound `T: 'a` in the correct scope:
// trait, impl or associated fn.
// run-rustfix
struct Inv<'a>(Option<*mut &'a u8>);
fn check_bound<'a, A: 'a>(_: A, _: Inv<'a>) {}
trait Trait1<'a>: Sized {
fn foo(self, lt: Inv<'a>) {
check_bound(self, lt)
//~^ ERROR parameter type `Self` may not live long enough
}
}
trait Trait2: Sized {
fn foo<'a>(self, lt: Inv<'a>) {
check_bound(self, lt)
//~^ ERROR parameter type `Self` may not live long enough
}
}
trait Trait3<T> {
fn foo<'a>(arg: T, lt: Inv<'a>) {
check_bound(arg, lt)
//~^ ERROR parameter type `T` may not live long enough
}
}
trait Trait4<'a> {
fn foo<T>(arg: T, lt: Inv<'a>) {
check_bound(arg, lt)
//~^ ERROR parameter type `T` may not live long enough
}
}
trait Trait5<'a> {
fn foo(self, _: Inv<'a>);
}
impl<'a, T> Trait5<'a> for T {
fn foo(self, lt: Inv<'a>) {
check_bound(self, lt);
//~^ ERROR parameter type `T` may not live long enough
}
}
fn main() {}

View File

@ -0,0 +1,58 @@
error[E0309]: the parameter type `Self` may not live long enough
--> $DIR/type-param-bound-scope.rs:11:9
|
LL | check_bound(self, lt)
| ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `Self` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | trait Trait1<'a>: Sized where Self: 'a {
| ++++++++++++++
error[E0309]: the parameter type `Self` may not live long enough
--> $DIR/type-param-bound-scope.rs:18:9
|
LL | check_bound(self, lt)
| ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `Self` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn foo<'a>(self, lt: Inv<'a>) where Self: 'a {
| ++++++++++++++
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/type-param-bound-scope.rs:25:9
|
LL | check_bound(arg, lt)
| ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn foo<'a>(arg: T, lt: Inv<'a>) where T: 'a {
| +++++++++++
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/type-param-bound-scope.rs:32:9
|
LL | check_bound(arg, lt)
| ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | fn foo<T: 'a>(arg: T, lt: Inv<'a>) {
| ++++
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/type-param-bound-scope.rs:42:9
|
LL | check_bound(self, lt);
| ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
LL | impl<'a, T: 'a> Trait5<'a> for T {
| ++++
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0309`.

View File

@ -0,0 +1,52 @@
// We want to suggest a bound `T: 'a` but `'a` is elided,
// run-rustfix
// edition: 2018
#![allow(dead_code)]
struct Inv<'a>(Option<*mut &'a u8>);
fn check_bound<'a, A: 'a>(_: A, _: Inv<'a>) {}
struct Elided<'a, T = ()>(Inv<'a>, T);
struct MyTy<X>(X);
impl<'a, X> MyTy<Elided<'a, X>> {
async fn foo<A: 'a>(self, arg: A, _: &str) -> &str {
check_bound(arg, self.0 .0);
//~^ ERROR parameter type `A` may not live long enough
""
}
}
// Make sure the new lifetime name doesn't conflict with
// other early- or late-bound lifetimes in-scope.
impl<'a, A> MyTy<(A, &'a ())> {
async fn foo2<'b>(
arg: A,
lt: Inv<'b>,
) -> (
impl Into<&'b str> + Into<&'b str> + 'b,
impl Into<Option<Elided<'b>>> + 'b,
impl Into<Option<Elided<'b, ()>>>,
) where A: 'b {
check_bound(arg, lt);
//~^ ERROR parameter type `A` may not live long enough
("", None, None)
}
// same as above but there is a late-bound lifetime named `'b`.
async fn bar2<'c, 'b>(_dummy: &'a u8, arg: A, lt: Inv<'c>) where A: 'c {
check_bound(arg, lt);
//~^ ERROR parameter type `A` may not live long enough
}
}
impl<'a, A: 'a> MyTy<Elided<'a, A>> {
async fn foo3(self) {
check_bound(self.0 .1, self.0 .0);
//~^ ERROR parameter type `A` may not live long enough
}
}
fn main() {}

View File

@ -0,0 +1,52 @@
// We want to suggest a bound `T: 'a` but `'a` is elided,
// run-rustfix
// edition: 2018
#![allow(dead_code)]
struct Inv<'a>(Option<*mut &'a u8>);
fn check_bound<'a, A: 'a>(_: A, _: Inv<'a>) {}
struct Elided<'a, T = ()>(Inv<'a>, T);
struct MyTy<X>(X);
impl<X> MyTy<Elided<'_, X>> {
async fn foo<A>(self, arg: A, _: &str) -> &str {
check_bound(arg, self.0 .0);
//~^ ERROR parameter type `A` may not live long enough
""
}
}
// Make sure the new lifetime name doesn't conflict with
// other early- or late-bound lifetimes in-scope.
impl<'a, A> MyTy<(A, &'a ())> {
async fn foo2(
arg: A,
lt: Inv<'_>,
) -> (
impl Into<&str> + Into<&'_ str> + '_,
impl Into<Option<Elided>> + '_,
impl Into<Option<Elided<()>>>,
) {
check_bound(arg, lt);
//~^ ERROR parameter type `A` may not live long enough
("", None, None)
}
// same as above but there is a late-bound lifetime named `'b`.
async fn bar2<'b>(_dummy: &'a u8, arg: A, lt: Inv<'_>) {
check_bound(arg, lt);
//~^ ERROR parameter type `A` may not live long enough
}
}
impl<A> MyTy<Elided<'_, A>> {
async fn foo3(self) {
check_bound(self.0 .1, self.0 .0);
//~^ ERROR parameter type `A` may not live long enough
}
}
fn main() {}

View File

@ -0,0 +1,95 @@
error[E0311]: the parameter type `A` may not live long enough
--> $DIR/type-param-missing-lifetime.rs:16:9
|
LL | check_bound(arg, self.0 .0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the parameter type `A` must be valid for the anonymous lifetime as defined here...
--> $DIR/type-param-missing-lifetime.rs:14:21
|
LL | impl<X> MyTy<Elided<'_, X>> {
| ^^
note: ...so that the type `A` will meet its required lifetime bounds
--> $DIR/type-param-missing-lifetime.rs:16:9
|
LL | check_bound(arg, self.0 .0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider adding an explicit lifetime bound...
|
LL ~ impl<'a, X> MyTy<Elided<'a, X>> {
LL ~ async fn foo<A: 'a>(self, arg: A, _: &str) -> &str {
|
error[E0311]: the parameter type `A` may not live long enough
--> $DIR/type-param-missing-lifetime.rs:33:9
|
LL | check_bound(arg, lt);
| ^^^^^^^^^^^^^^^^^^^^
|
note: the parameter type `A` must be valid for the anonymous lifetime defined here...
--> $DIR/type-param-missing-lifetime.rs:27:13
|
LL | lt: Inv<'_>,
| ^^^^^^^
note: ...so that the type `A` will meet its required lifetime bounds
--> $DIR/type-param-missing-lifetime.rs:33:9
|
LL | check_bound(arg, lt);
| ^^^^^^^^^^^^^^^^^^^^
help: consider adding an explicit lifetime bound...
|
LL ~ async fn foo2<'b>(
LL | arg: A,
LL ~ lt: Inv<'b>,
LL | ) -> (
LL ~ impl Into<&'b str> + Into<&'b str> + 'b,
LL ~ impl Into<Option<Elided<'b>>> + 'b,
LL ~ impl Into<Option<Elided<'b, ()>>>,
LL ~ ) where A: 'b {
|
error[E0311]: the parameter type `A` may not live long enough
--> $DIR/type-param-missing-lifetime.rs:40:9
|
LL | check_bound(arg, lt);
| ^^^^^^^^^^^^^^^^^^^^
|
note: the parameter type `A` must be valid for the anonymous lifetime defined here...
--> $DIR/type-param-missing-lifetime.rs:39:51
|
LL | async fn bar2<'b>(_dummy: &'a u8, arg: A, lt: Inv<'_>) {
| ^^^^^^^
note: ...so that the type `A` will meet its required lifetime bounds
--> $DIR/type-param-missing-lifetime.rs:40:9
|
LL | check_bound(arg, lt);
| ^^^^^^^^^^^^^^^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | async fn bar2<'c, 'b>(_dummy: &'a u8, arg: A, lt: Inv<'c>) where A: 'c {
| +++ ~~ +++++++++++
error[E0311]: the parameter type `A` may not live long enough
--> $DIR/type-param-missing-lifetime.rs:47:9
|
LL | check_bound(self.0 .1, self.0 .0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the parameter type `A` must be valid for the anonymous lifetime as defined here...
--> $DIR/type-param-missing-lifetime.rs:45:21
|
LL | impl<A> MyTy<Elided<'_, A>> {
| ^^
note: ...so that the type `A` will meet its required lifetime bounds
--> $DIR/type-param-missing-lifetime.rs:47:9
|
LL | check_bound(self.0 .1, self.0 .0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider adding an explicit lifetime bound...
|
LL | impl<'a, A: 'a> MyTy<Elided<'a, A>> {
| +++ ++++ ~~
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0311`.

View File

@ -2,10 +2,12 @@ error[E0309]: the associated type `<Self as SomeTrait<'a>>::Type1` may not live
--> $DIR/wf-trait-associated-type-region.rs:9:18
|
LL | type Type2 = &'a Self::Type1;
| ^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^ ...so that the reference type `&'a <Self as SomeTrait<'a>>::Type1` does not outlive the data it points at
|
= help: consider adding an explicit lifetime bound `<Self as SomeTrait<'a>>::Type1: 'a`...
= note: ...so that the reference type `&'a <Self as SomeTrait<'a>>::Type1` does not outlive the data it points at
help: consider adding an explicit lifetime bound...
|
LL | type Type2 = &'a Self::Type1 where <Self as SomeTrait<'a>>::Type1: 'a;
| ++++++++++++++++++++++++++++++++++++++++
error: aborting due to previous error