Account for multiple impl/dyn Trait in return type when suggesting `'_`
This commit is contained in:
parent
a39c7787ba
commit
562f4967b4
|
@ -26,7 +26,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
region: Region<'tcx>,
|
region: Region<'tcx>,
|
||||||
br: &ty::BoundRegion,
|
br: &ty::BoundRegion,
|
||||||
) -> Option<(&hir::Ty<'_>, &hir::FnDecl<'_>)> {
|
) -> Option<(&hir::Ty<'tcx>, &hir::FnDecl<'tcx>)> {
|
||||||
if let Some(anon_reg) = self.tcx().is_suitable_region(region) {
|
if let Some(anon_reg) = self.tcx().is_suitable_region(region) {
|
||||||
let def_id = anon_reg.def_id;
|
let def_id = anon_reg.def_id;
|
||||||
if let Some(def_id) = def_id.as_local() {
|
if let Some(def_id) = def_id.as_local() {
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
//! where one region is named and the other is anonymous.
|
//! where one region is named and the other is anonymous.
|
||||||
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||||
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
|
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
|
||||||
use rustc_hir::{FnRetTy, TyKind};
|
use rustc_hir::intravisit::Visitor;
|
||||||
|
use rustc_hir::FnRetTy;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
|
|
||||||
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
|
@ -80,12 +81,16 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let FnRetTy::Return(ty) = &fndecl.output {
|
if let FnRetTy::Return(ty) = &fndecl.output {
|
||||||
let mut v = ty::TraitObjectVisitor(vec![]);
|
let mut v = ty::TraitObjectVisitor(vec![], self.tcx().hir());
|
||||||
rustc_hir::intravisit::walk_ty(&mut v, ty);
|
v.visit_ty(ty);
|
||||||
|
|
||||||
debug!("try_report_named_anon_conflict: ret ty {:?}", ty);
|
debug!("try_report_named_anon_conflict: ret ty {:?}", ty);
|
||||||
if sub == &ty::ReStatic
|
if sub == &ty::ReStatic
|
||||||
&& (matches!(ty.kind, TyKind::OpaqueDef(_, _)) || v.0.len() == 1)
|
&& v.0
|
||||||
|
.into_iter()
|
||||||
|
.filter(|t| t.span.desugaring_kind().is_none())
|
||||||
|
.next()
|
||||||
|
.is_some()
|
||||||
{
|
{
|
||||||
debug!("try_report_named_anon_conflict: impl Trait + 'static");
|
debug!("try_report_named_anon_conflict: impl Trait + 'static");
|
||||||
// This is an `impl Trait` or `dyn Trait` return that evaluates de need of
|
// This is an `impl Trait` or `dyn Trait` return that evaluates de need of
|
||||||
|
|
|
@ -26,8 +26,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?;
|
let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?;
|
||||||
debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
|
debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
|
||||||
let fn_return = self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?;
|
let fn_returns = self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id);
|
||||||
debug!("try_report_static_impl_trait: fn_return={:?}", fn_return);
|
if fn_returns.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
|
||||||
if **sub_r == RegionKind::ReStatic {
|
if **sub_r == RegionKind::ReStatic {
|
||||||
let sp = var_origin.span();
|
let sp = var_origin.span();
|
||||||
let return_sp = sub_origin.span();
|
let return_sp = sub_origin.span();
|
||||||
|
@ -98,25 +101,26 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// only apply this suggestion onto functions with
|
// FIXME: account for the need of parens in `&(dyn Trait + '_)`
|
||||||
// explicit non-desugar'able return.
|
let consider = "consider changing the";
|
||||||
if fn_return.span.desugaring_kind().is_none() {
|
let declare = "to declare that the";
|
||||||
// FIXME: account for the need of parens in `&(dyn Trait + '_)`
|
let arg = match param_info.param.pat.simple_ident() {
|
||||||
|
Some(simple_ident) => format!("argument `{}`", simple_ident),
|
||||||
let consider = "consider changing the";
|
None => "the argument".to_string(),
|
||||||
let declare = "to declare that the";
|
};
|
||||||
let arg = match param_info.param.pat.simple_ident() {
|
let explicit =
|
||||||
Some(simple_ident) => format!("argument `{}`", simple_ident),
|
format!("you can add an explicit `{}` lifetime bound", lifetime_name);
|
||||||
None => "the argument".to_string(),
|
let explicit_static =
|
||||||
};
|
format!("explicit `'static` bound to the lifetime of {}", arg);
|
||||||
let explicit =
|
let captures = format!("captures data from {}", arg);
|
||||||
format!("you can add an explicit `{}` lifetime bound", lifetime_name);
|
let add_static_bound =
|
||||||
let explicit_static =
|
"alternatively, add an explicit `'static` bound to this reference";
|
||||||
format!("explicit `'static` bound to the lifetime of {}", arg);
|
let plus_lt = format!(" + {}", lifetime_name);
|
||||||
let captures = format!("captures data from {}", arg);
|
for fn_return in fn_returns {
|
||||||
let add_static_bound =
|
if fn_return.span.desugaring_kind().is_some() {
|
||||||
"alternatively, add an explicit `'static` bound to this reference";
|
// Skip `async` desugaring `impl Future`.
|
||||||
let plus_lt = format!(" + {}", lifetime_name);
|
continue;
|
||||||
|
}
|
||||||
match fn_return.kind {
|
match fn_return.kind {
|
||||||
TyKind::OpaqueDef(item_id, _) => {
|
TyKind::OpaqueDef(item_id, _) => {
|
||||||
let item = self.tcx().hir().item(item_id.id);
|
let item = self.tcx().hir().item(item_id.id);
|
||||||
|
@ -143,7 +147,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
span,
|
span,
|
||||||
&format!("{} `impl Trait`'s {}", consider, explicit_static),
|
&format!("{} `impl Trait`'s {}", consider, explicit_static),
|
||||||
lifetime_name,
|
lifetime_name.clone(),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
|
@ -152,6 +156,19 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
param_info.param_ty.to_string(),
|
param_info.param_ty.to_string(),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
|
} else if let Some(_) = opaque
|
||||||
|
.bounds
|
||||||
|
.iter()
|
||||||
|
.filter_map(|arg| match arg {
|
||||||
|
GenericBound::Outlives(Lifetime { name, span, .. })
|
||||||
|
if name.ident().to_string() == lifetime_name =>
|
||||||
|
{
|
||||||
|
Some(*span)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.next()
|
||||||
|
{
|
||||||
} else {
|
} else {
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
fn_return.span.shrink_to_hi(),
|
fn_return.span.shrink_to_hi(),
|
||||||
|
@ -161,10 +178,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
captures = captures,
|
captures = captures,
|
||||||
explicit = explicit,
|
explicit = explicit,
|
||||||
),
|
),
|
||||||
plus_lt,
|
plus_lt.clone(),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
TyKind::TraitObject(_, lt) => match lt.name {
|
TyKind::TraitObject(_, lt) => match lt.name {
|
||||||
LifetimeName::ImplicitObjectLifetimeDefault => {
|
LifetimeName::ImplicitObjectLifetimeDefault => {
|
||||||
|
@ -176,15 +193,19 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
captures = captures,
|
captures = captures,
|
||||||
explicit = explicit,
|
explicit = explicit,
|
||||||
),
|
),
|
||||||
plus_lt,
|
plus_lt.clone(),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
name if name.ident().to_string() != lifetime_name => {
|
||||||
|
// With this check we avoid suggesting redundant bounds. This
|
||||||
|
// would happen if there are nested impl/dyn traits and only
|
||||||
|
// one of them has the bound we'd suggest already there, like
|
||||||
|
// in `impl Foo<X = dyn Bar> + '_`.
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
lt.span,
|
lt.span,
|
||||||
&format!("{} trait object's {}", consider, explicit_static),
|
&format!("{} trait object's {}", consider, explicit_static),
|
||||||
lifetime_name,
|
lifetime_name.clone(),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
|
@ -194,6 +215,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
|
||||||
use rustc_hir::definitions::{DefPathHash, Definitions};
|
use rustc_hir::definitions::{DefPathHash, Definitions};
|
||||||
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_hir::lang_items::{self, PanicLocationLangItem};
|
use rustc_hir::lang_items::{self, PanicLocationLangItem};
|
||||||
use rustc_hir::{HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate};
|
use rustc_hir::{HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate};
|
||||||
use rustc_index::vec::{Idx, IndexVec};
|
use rustc_index::vec::{Idx, IndexVec};
|
||||||
|
@ -1405,10 +1406,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn return_type_impl_or_dyn_trait(
|
pub fn return_type_impl_or_dyn_trait(&self, scope_def_id: DefId) -> Vec<&'tcx hir::Ty<'tcx>> {
|
||||||
&self,
|
|
||||||
scope_def_id: DefId,
|
|
||||||
) -> Option<&'tcx hir::Ty<'tcx>> {
|
|
||||||
let hir_id = self.hir().as_local_hir_id(scope_def_id.expect_local());
|
let hir_id = self.hir().as_local_hir_id(scope_def_id.expect_local());
|
||||||
let hir_output = match self.hir().get(hir_id) {
|
let hir_output = match self.hir().get(hir_id) {
|
||||||
Node::Item(hir::Item {
|
Node::Item(hir::Item {
|
||||||
|
@ -1444,30 +1442,12 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
),
|
),
|
||||||
..
|
..
|
||||||
}) => ty,
|
}) => ty,
|
||||||
_ => return None,
|
_ => return vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let ret_ty = self.type_of(scope_def_id);
|
let mut v = TraitObjectVisitor(vec![], self.hir());
|
||||||
match ret_ty.kind {
|
v.visit_ty(hir_output);
|
||||||
ty::FnDef(_, _) => {
|
v.0
|
||||||
let sig = ret_ty.fn_sig(*self);
|
|
||||||
let output = self.erase_late_bound_regions(&sig.output());
|
|
||||||
if output.is_impl_trait() {
|
|
||||||
let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
|
|
||||||
if let hir::FnRetTy::Return(ty) = fn_decl.output {
|
|
||||||
return Some(ty);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let mut v = TraitObjectVisitor(vec![]);
|
|
||||||
rustc_hir::intravisit::walk_ty(&mut v, hir_output);
|
|
||||||
if v.0.len() == 1 {
|
|
||||||
return Some(v.0[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn return_type_impl_trait(&self, scope_def_id: DefId) -> Option<(Ty<'tcx>, Span)> {
|
pub fn return_type_impl_trait(&self, scope_def_id: DefId) -> Option<(Ty<'tcx>, Span)> {
|
||||||
|
|
|
@ -236,7 +236,9 @@ pub fn suggest_constraining_type_param(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>);
|
/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for.
|
||||||
|
pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>, pub crate::hir::map::Map<'tcx>);
|
||||||
|
|
||||||
impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
|
impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
|
||||||
type Map = rustc_hir::intravisit::ErasedMap<'v>;
|
type Map = rustc_hir::intravisit::ErasedMap<'v>;
|
||||||
|
|
||||||
|
@ -245,15 +247,24 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
|
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
|
||||||
if let hir::TyKind::TraitObject(
|
match ty.kind {
|
||||||
_,
|
hir::TyKind::TraitObject(
|
||||||
hir::Lifetime {
|
_,
|
||||||
name: hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
|
hir::Lifetime {
|
||||||
..
|
name:
|
||||||
},
|
hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
|
||||||
) = ty.kind
|
..
|
||||||
{
|
},
|
||||||
self.0.push(ty);
|
) => {
|
||||||
|
self.0.push(ty);
|
||||||
|
}
|
||||||
|
hir::TyKind::OpaqueDef(item_id, _) => {
|
||||||
|
self.0.push(ty);
|
||||||
|
let item = self.1.expect_item(item_id.id);
|
||||||
|
hir::intravisit::walk_item(self, item);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
hir::intravisit::walk_ty(self, ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,15 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
|
||||||
| help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
|
| help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
|
||||||
|
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/must_outlive_least_region_or_bound.rs:33:69
|
--> $DIR/must_outlive_least_region_or_bound.rs:30:24
|
||||||
|
|
|
||||||
|
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
|
||||||
|
| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
|
||||||
|
| |
|
||||||
|
| let's call the lifetime of this reference `'1`
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/must_outlive_least_region_or_bound.rs:37:69
|
||||||
|
|
|
|
||||||
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
|
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
|
||||||
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
|
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
|
||||||
|
@ -62,7 +70,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
|
||||||
= help: consider replacing `'a` with `'static`
|
= help: consider replacing `'a` with `'static`
|
||||||
|
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/must_outlive_least_region_or_bound.rs:38:61
|
--> $DIR/must_outlive_least_region_or_bound.rs:42:61
|
||||||
|
|
|
|
||||||
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
|
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
|
||||||
| -- -- lifetime `'b` defined here ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a`
|
| -- -- lifetime `'b` defined here ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a`
|
||||||
|
@ -72,14 +80,14 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
|
||||||
= help: consider adding the following bound: `'b: 'a`
|
= help: consider adding the following bound: `'b: 'a`
|
||||||
|
|
||||||
error[E0310]: the parameter type `T` may not live long enough
|
error[E0310]: the parameter type `T` may not live long enough
|
||||||
--> $DIR/must_outlive_least_region_or_bound.rs:43:51
|
--> $DIR/must_outlive_least_region_or_bound.rs:47:51
|
||||||
|
|
|
|
||||||
LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
|
LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: consider adding an explicit lifetime bound `T: 'static`...
|
= help: consider adding an explicit lifetime bound `T: 'static`...
|
||||||
|
|
||||||
error: aborting due to 8 previous errors
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0310, E0621.
|
Some errors have detailed explanations: E0310, E0621.
|
||||||
For more information about an error, try `rustc --explain E0310`.
|
For more information about an error, try `rustc --explain E0310`.
|
||||||
|
|
|
@ -27,6 +27,10 @@ fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||||
fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||||
//~^ ERROR cannot infer an appropriate lifetime
|
//~^ ERROR cannot infer an appropriate lifetime
|
||||||
|
|
||||||
|
fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
|
||||||
|
//~^ ERROR cannot infer an appropriate lifetime
|
||||||
|
//~| ERROR cannot infer an appropriate lifetime
|
||||||
|
|
||||||
trait LifetimeTrait<'a> {}
|
trait LifetimeTrait<'a> {}
|
||||||
impl<'a> LifetimeTrait<'a> for &'a i32 {}
|
impl<'a> LifetimeTrait<'a> for &'a i32 {}
|
||||||
|
|
||||||
|
|
|
@ -87,13 +87,48 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
|
||||||
| help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
|
| help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
|
||||||
|
|
||||||
error[E0759]: cannot infer an appropriate lifetime
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
--> $DIR/must_outlive_least_region_or_bound.rs:33:69
|
--> $DIR/must_outlive_least_region_or_bound.rs:30:65
|
||||||
|
|
|
||||||
|
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
|
||||||
|
| ---- this data with an anonymous lifetime `'_`... ^ ...is captured here, requiring it to live as long as `'static`
|
||||||
|
|
|
||||||
|
help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound
|
||||||
|
|
|
||||||
|
LL | fn elided5(x: &i32) -> (Box<dyn Debug + '_>, impl Debug) { (Box::new(x), x) }
|
||||||
|
| ^^^^
|
||||||
|
help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound
|
||||||
|
|
|
||||||
|
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) }
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
|
--> $DIR/must_outlive_least_region_or_bound.rs:30:69
|
||||||
|
|
|
||||||
|
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
|
||||||
|
| ---- this data with an anonymous lifetime `'_`... ^ ...is captured here...
|
||||||
|
|
|
||||||
|
note: ...and is required to live as long as `'static` here
|
||||||
|
--> $DIR/must_outlive_least_region_or_bound.rs:30:41
|
||||||
|
|
|
||||||
|
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound
|
||||||
|
|
|
||||||
|
LL | fn elided5(x: &i32) -> (Box<dyn Debug + '_>, impl Debug) { (Box::new(x), x) }
|
||||||
|
| ^^^^
|
||||||
|
help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound
|
||||||
|
|
|
||||||
|
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) }
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
|
--> $DIR/must_outlive_least_region_or_bound.rs:37:69
|
||||||
|
|
|
|
||||||
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
|
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
|
||||||
| ------- this data with lifetime `'a`... ^ ...is captured here...
|
| ------- this data with lifetime `'a`... ^ ...is captured here...
|
||||||
|
|
|
|
||||||
note: ...and is required to live as long as `'static` here
|
note: ...and is required to live as long as `'static` here
|
||||||
--> $DIR/must_outlive_least_region_or_bound.rs:33:34
|
--> $DIR/must_outlive_least_region_or_bound.rs:37:34
|
||||||
|
|
|
|
||||||
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
|
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -107,7 +142,7 @@ LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0623]: lifetime mismatch
|
error[E0623]: lifetime mismatch
|
||||||
--> $DIR/must_outlive_least_region_or_bound.rs:38:61
|
--> $DIR/must_outlive_least_region_or_bound.rs:42:61
|
||||||
|
|
|
|
||||||
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
|
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
|
||||||
| ------- ^^^^^^^^^^^^^^^^
|
| ------- ^^^^^^^^^^^^^^^^
|
||||||
|
@ -116,7 +151,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
|
||||||
| this parameter and the return type are declared with different lifetimes...
|
| this parameter and the return type are declared with different lifetimes...
|
||||||
|
|
||||||
error[E0310]: the parameter type `T` may not live long enough
|
error[E0310]: the parameter type `T` may not live long enough
|
||||||
--> $DIR/must_outlive_least_region_or_bound.rs:43:51
|
--> $DIR/must_outlive_least_region_or_bound.rs:47:51
|
||||||
|
|
|
|
||||||
LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
|
LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
|
||||||
| -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
| -- ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
||||||
|
@ -181,7 +216,7 @@ help: alternatively, add an explicit `'static` bound to this reference
|
||||||
LL | fn explicit4<'a>(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
LL | fn explicit4<'a>(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 12 previous errors
|
error: aborting due to 14 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0310, E0621, E0623, E0759.
|
Some errors have detailed explanations: E0310, E0621, E0623, E0759.
|
||||||
For more information about an error, try `rustc --explain E0310`.
|
For more information about an error, try `rustc --explain E0310`.
|
||||||
|
|
|
@ -6,6 +6,11 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
|
||||||
| | |
|
| | |
|
||||||
| | this data with an anonymous lifetime `'_`...
|
| | this data with an anonymous lifetime `'_`...
|
||||||
| ...is captured here...
|
| ...is captured here...
|
||||||
|
|
|
||||||
|
help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound
|
||||||
|
|
|
||||||
|
LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/trait-object-nested-in-impl-trait.rs:27:23
|
||||||
|
|
|
||||||
|
LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
|
||||||
|
| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
|
||||||
|
| |
|
||||||
|
| let's call the lifetime of this reference `'1`
|
||||||
|
|
|
||||||
|
help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
|
||||||
|
|
|
||||||
|
LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/trait-object-nested-in-impl-trait.rs:39:9
|
||||||
|
|
|
||||||
|
LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
|
||||||
|
| - let's call the lifetime of this reference `'1`
|
||||||
|
LL | / Iter {
|
||||||
|
LL | | current: None,
|
||||||
|
LL | | remaining: self.0.iter(),
|
||||||
|
LL | | }
|
||||||
|
| |_________^ returning this value requires that `'1` must outlive `'static`
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/trait-object-nested-in-impl-trait.rs:50:9
|
||||||
|
|
|
||||||
|
LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
|
||||||
|
| -- lifetime `'a` defined here
|
||||||
|
LL | / Iter {
|
||||||
|
LL | | current: None,
|
||||||
|
LL | | remaining: self.0.iter(),
|
||||||
|
LL | | }
|
||||||
|
| |_________^ returning this value requires that `'a` must outlive `'static`
|
||||||
|
|
|
||||||
|
= help: consider replacing `'a` with `'static`
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/trait-object-nested-in-impl-trait.rs:60:30
|
||||||
|
|
|
||||||
|
LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
|
||||||
|
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'static`
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
|
|
||||||
|
= help: consider replacing `'a` with `'static`
|
||||||
|
help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound
|
||||||
|
|
|
||||||
|
LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
trait Foo {}
|
||||||
|
impl<'a, T: Foo> Foo for &'a T {}
|
||||||
|
impl<T: Foo + ?Sized> Foo for Box<T> {}
|
||||||
|
|
||||||
|
struct Iter<'a, T> {
|
||||||
|
current: Option<Box<dyn Foo + 'a>>,
|
||||||
|
remaining: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> Iterator for Iter<'a, T>
|
||||||
|
where
|
||||||
|
T: Iterator,
|
||||||
|
T::Item: Foo + 'a,
|
||||||
|
{
|
||||||
|
type Item = Box<dyn Foo + 'a>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let result = self.current.take();
|
||||||
|
self.current = Box::new(self.remaining.next()).map(|f| Box::new(f) as _);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bar(Vec<Box<dyn Foo>>);
|
||||||
|
|
||||||
|
impl Bar {
|
||||||
|
fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
|
||||||
|
Iter {
|
||||||
|
current: None,
|
||||||
|
remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Baz(Vec<Box<dyn Foo>>);
|
||||||
|
|
||||||
|
impl Baz {
|
||||||
|
fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
|
||||||
|
Iter {
|
||||||
|
current: None,
|
||||||
|
remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bat(Vec<Box<dyn Foo>>);
|
||||||
|
|
||||||
|
impl Bat {
|
||||||
|
fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
|
||||||
|
Iter {
|
||||||
|
current: None,
|
||||||
|
remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Ban(Vec<Box<dyn Foo>>);
|
||||||
|
|
||||||
|
impl Ban {
|
||||||
|
fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
|
||||||
|
Iter {
|
||||||
|
current: None,
|
||||||
|
remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,95 @@
|
||||||
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
|
--> $DIR/trait-object-nested-in-impl-trait.rs:30:31
|
||||||
|
|
|
||||||
|
LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
|
||||||
|
| ----- this data with an anonymous lifetime `'_`...
|
||||||
|
...
|
||||||
|
LL | remaining: self.0.iter(),
|
||||||
|
| ------ ^^^^
|
||||||
|
| |
|
||||||
|
| ...is captured here...
|
||||||
|
|
|
||||||
|
note: ...and is required to live as long as `'static` here
|
||||||
|
--> $DIR/trait-object-nested-in-impl-trait.rs:27:23
|
||||||
|
|
|
||||||
|
LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound
|
||||||
|
|
|
||||||
|
LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
|
||||||
|
| ^^^^
|
||||||
|
help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound
|
||||||
|
|
|
||||||
|
LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo + '_>> {
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
|
--> $DIR/trait-object-nested-in-impl-trait.rs:41:31
|
||||||
|
|
|
||||||
|
LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
|
||||||
|
| ----- this data with an anonymous lifetime `'_`...
|
||||||
|
...
|
||||||
|
LL | remaining: self.0.iter(),
|
||||||
|
| ------ ^^^^
|
||||||
|
| |
|
||||||
|
| ...is captured here...
|
||||||
|
|
|
||||||
|
note: ...and is required to live as long as `'static` here
|
||||||
|
--> $DIR/trait-object-nested-in-impl-trait.rs:38:23
|
||||||
|
|
|
||||||
|
LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: to declare that the trait object captures data from argument `self`, you can add an explicit `'_` lifetime bound
|
||||||
|
|
|
||||||
|
LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo + '_>> + '_ {
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
|
--> $DIR/trait-object-nested-in-impl-trait.rs:52:31
|
||||||
|
|
|
||||||
|
LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
|
||||||
|
| -------- this data with lifetime `'a`...
|
||||||
|
...
|
||||||
|
LL | remaining: self.0.iter(),
|
||||||
|
| ------ ^^^^
|
||||||
|
| |
|
||||||
|
| ...is captured here...
|
||||||
|
|
|
||||||
|
note: ...and is required to live as long as `'static` here
|
||||||
|
--> $DIR/trait-object-nested-in-impl-trait.rs:49:30
|
||||||
|
|
|
||||||
|
LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: to declare that the trait object captures data from argument `self`, you can add an explicit `'a` lifetime bound
|
||||||
|
|
|
||||||
|
LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo + 'a>> + 'a {
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
|
--> $DIR/trait-object-nested-in-impl-trait.rs:63:31
|
||||||
|
|
|
||||||
|
LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
|
||||||
|
| -------- this data with lifetime `'a`...
|
||||||
|
...
|
||||||
|
LL | remaining: self.0.iter(),
|
||||||
|
| ------ ^^^^
|
||||||
|
| |
|
||||||
|
| ...is captured here...
|
||||||
|
|
|
||||||
|
note: ...and is required to live as long as `'static` here
|
||||||
|
--> $DIR/trait-object-nested-in-impl-trait.rs:60:30
|
||||||
|
|
|
||||||
|
LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound
|
||||||
|
|
|
||||||
|
LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
|
||||||
|
| ^^^^
|
||||||
|
help: to declare that the trait object captures data from argument `self`, you can add an explicit `'a` lifetime bound
|
||||||
|
|
|
||||||
|
LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo + 'a>> {
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0759`.
|
Loading…
Reference in New Issue