parent
9e92106d45
commit
6513148c14
13 changed files with 431 additions and 302 deletions
|
@ -2,227 +2,302 @@
|
||||||
|
|
||||||
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||||
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
||||||
use rustc_errors::{struct_span_err, Applicability, ErrorReported};
|
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
|
||||||
use rustc_hir::{GenericBound, ItemKind, Lifetime, LifetimeName, TyKind};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_middle::ty::RegionKind;
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
|
use rustc_hir::{
|
||||||
|
GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, Path, PolyTraitRef, TraitRef,
|
||||||
|
TyKind,
|
||||||
|
};
|
||||||
|
use rustc_middle::ty::{self, RegionKind, Ty, TypeFoldable, TypeVisitor};
|
||||||
|
|
||||||
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
/// Print the error message for lifetime errors when the return type is a static impl Trait.
|
/// Print the error message for lifetime errors when the return type is a static impl Trait.
|
||||||
pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
|
pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
|
||||||
debug!("try_report_static_impl_trait(error={:?})", self.error);
|
debug!("try_report_static_impl_trait(error={:?})", self.error);
|
||||||
if let Some(RegionResolutionError::SubSupConflict(
|
let tcx = self.tcx();
|
||||||
_,
|
let (var_origin, sub_origin, sub_r, sup_origin, sup_r) = match self.error.as_ref()? {
|
||||||
var_origin,
|
RegionResolutionError::SubSupConflict(
|
||||||
ref sub_origin,
|
_,
|
||||||
sub_r,
|
var_origin,
|
||||||
ref sup_origin,
|
sub_origin,
|
||||||
sup_r,
|
sub_r,
|
||||||
)) = self.error
|
sup_origin,
|
||||||
{
|
sup_r,
|
||||||
debug!(
|
) if **sub_r == RegionKind::ReStatic => {
|
||||||
"try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})",
|
(var_origin, sub_origin, sub_r, sup_origin, sup_r)
|
||||||
var_origin, sub_origin, sub_r, sup_origin, 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);
|
|
||||||
let fn_returns = self.tcx().return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
|
|
||||||
if fn_returns.is_empty() {
|
|
||||||
return None;
|
|
||||||
}
|
}
|
||||||
debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
|
_ => return None,
|
||||||
if *sub_r == RegionKind::ReStatic {
|
};
|
||||||
let sp = var_origin.span();
|
debug!(
|
||||||
let return_sp = sub_origin.span();
|
"try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})",
|
||||||
let param_info = self.find_param_with_region(sup_r, sub_r)?;
|
var_origin, sub_origin, sub_r, sup_origin, sup_r
|
||||||
let (lifetime_name, lifetime) = if sup_r.has_name() {
|
);
|
||||||
(sup_r.to_string(), format!("lifetime `{}`", sup_r))
|
let anon_reg_sup = tcx.is_suitable_region(sup_r)?;
|
||||||
} else {
|
debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
|
||||||
("'_".to_owned(), "an anonymous lifetime `'_`".to_string())
|
let sp = var_origin.span();
|
||||||
};
|
let return_sp = sub_origin.span();
|
||||||
let mut err = struct_span_err!(
|
let param = self.find_param_with_region(sup_r, sub_r)?;
|
||||||
self.tcx().sess,
|
let (lifetime_name, lifetime) = if sup_r.has_name() {
|
||||||
sp,
|
(sup_r.to_string(), format!("lifetime `{}`", sup_r))
|
||||||
E0759,
|
} else {
|
||||||
"cannot infer an appropriate lifetime"
|
("'_".to_owned(), "an anonymous lifetime `'_`".to_string())
|
||||||
);
|
};
|
||||||
|
let mut err = struct_span_err!(tcx.sess, sp, E0759, "cannot infer an appropriate lifetime");
|
||||||
|
err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
|
||||||
|
debug!("try_report_static_impl_trait: param_info={:?}", param);
|
||||||
|
|
||||||
|
// We try to make the output have fewer overlapping spans if possible.
|
||||||
|
if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()))
|
||||||
|
&& sup_origin.span() != return_sp
|
||||||
|
{
|
||||||
|
// FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs`
|
||||||
|
|
||||||
|
// Customize the spans and labels depending on their relative order so
|
||||||
|
// that split sentences flow correctly.
|
||||||
|
if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() {
|
||||||
|
// Avoid the following:
|
||||||
|
//
|
||||||
|
// error: cannot infer an appropriate lifetime
|
||||||
|
// --> $DIR/must_outlive_least_region_or_bound.rs:18:50
|
||||||
|
// |
|
||||||
|
// LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
|
||||||
|
// | ---- ---------^-
|
||||||
|
//
|
||||||
|
// and instead show:
|
||||||
|
//
|
||||||
|
// error: cannot infer an appropriate lifetime
|
||||||
|
// --> $DIR/must_outlive_least_region_or_bound.rs:18:50
|
||||||
|
// |
|
||||||
|
// LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
|
||||||
|
// | ---- ^
|
||||||
err.span_label(
|
err.span_label(
|
||||||
param_info.param_ty_span,
|
sup_origin.span(),
|
||||||
&format!("this data with {}...", lifetime),
|
"...is captured here, requiring it to live as long as `'static`",
|
||||||
);
|
);
|
||||||
debug!("try_report_static_impl_trait: param_info={:?}", param_info);
|
} else {
|
||||||
|
err.span_label(sup_origin.span(), "...is captured here...");
|
||||||
// We try to make the output have fewer overlapping spans if possible.
|
if return_sp < sup_origin.span() {
|
||||||
if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()))
|
err.span_note(
|
||||||
&& sup_origin.span() != return_sp
|
return_sp,
|
||||||
{
|
"...and is required to live as long as `'static` here",
|
||||||
// FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs`
|
);
|
||||||
|
|
||||||
// Customize the spans and labels depending on their relative order so
|
|
||||||
// that split sentences flow correctly.
|
|
||||||
if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() {
|
|
||||||
// Avoid the following:
|
|
||||||
//
|
|
||||||
// error: cannot infer an appropriate lifetime
|
|
||||||
// --> $DIR/must_outlive_least_region_or_bound.rs:18:50
|
|
||||||
// |
|
|
||||||
// LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
|
|
||||||
// | ---- ---------^-
|
|
||||||
//
|
|
||||||
// and instead show:
|
|
||||||
//
|
|
||||||
// error: cannot infer an appropriate lifetime
|
|
||||||
// --> $DIR/must_outlive_least_region_or_bound.rs:18:50
|
|
||||||
// |
|
|
||||||
// LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
|
|
||||||
// | ---- ^
|
|
||||||
err.span_label(
|
|
||||||
sup_origin.span(),
|
|
||||||
"...is captured here, requiring it to live as long as `'static`",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
err.span_label(sup_origin.span(), "...is captured here...");
|
|
||||||
if return_sp < sup_origin.span() {
|
|
||||||
err.span_note(
|
|
||||||
return_sp,
|
|
||||||
"...and is required to live as long as `'static` here",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
err.span_label(
|
|
||||||
return_sp,
|
|
||||||
"...and is required to live as long as `'static` here",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
err.span_label(
|
err.span_label(
|
||||||
return_sp,
|
return_sp,
|
||||||
"...is captured and required to live as long as `'static` here",
|
"...and is required to live as long as `'static` here",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err.span_label(
|
||||||
|
return_sp,
|
||||||
|
"...is captured and required to live as long as `'static` here",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: account for the need of parens in `&(dyn Trait + '_)`
|
self.find_impl_on_dyn_trait(&mut err, param.param_ty);
|
||||||
let consider = "consider changing the";
|
|
||||||
let declare = "to declare that the";
|
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
|
||||||
let arg = match param_info.param.pat.simple_ident() {
|
debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
|
||||||
Some(simple_ident) => format!("argument `{}`", simple_ident),
|
// FIXME: account for the need of parens in `&(dyn Trait + '_)`
|
||||||
None => "the argument".to_string(),
|
let consider = "consider changing the";
|
||||||
};
|
let declare = "to declare that the";
|
||||||
let explicit =
|
let arg = match param.param.pat.simple_ident() {
|
||||||
format!("you can add an explicit `{}` lifetime bound", lifetime_name);
|
Some(simple_ident) => format!("argument `{}`", simple_ident),
|
||||||
let explicit_static =
|
None => "the argument".to_string(),
|
||||||
format!("explicit `'static` bound to the lifetime of {}", arg);
|
};
|
||||||
let captures = format!("captures data from {}", arg);
|
let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name);
|
||||||
let add_static_bound =
|
let explicit_static = format!("explicit `'static` bound to the lifetime of {}", arg);
|
||||||
"alternatively, add an explicit `'static` bound to this reference";
|
let captures = format!("captures data from {}", arg);
|
||||||
let plus_lt = format!(" + {}", lifetime_name);
|
let add_static_bound = "alternatively, add an explicit `'static` bound to this reference";
|
||||||
for fn_return in fn_returns {
|
let plus_lt = format!(" + {}", lifetime_name);
|
||||||
if fn_return.span.desugaring_kind().is_some() {
|
for fn_return in fn_returns {
|
||||||
// Skip `async` desugaring `impl Future`.
|
if fn_return.span.desugaring_kind().is_some() {
|
||||||
continue;
|
// Skip `async` desugaring `impl Future`.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
match fn_return.kind {
|
||||||
|
TyKind::OpaqueDef(item_id, _) => {
|
||||||
|
let item = tcx.hir().item(item_id.id);
|
||||||
|
let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind {
|
||||||
|
opaque
|
||||||
|
} else {
|
||||||
|
err.emit();
|
||||||
|
return Some(ErrorReported);
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(span) = opaque
|
||||||
|
.bounds
|
||||||
|
.iter()
|
||||||
|
.filter_map(|arg| match arg {
|
||||||
|
GenericBound::Outlives(Lifetime {
|
||||||
|
name: LifetimeName::Static,
|
||||||
|
span,
|
||||||
|
..
|
||||||
|
}) => Some(*span),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.next()
|
||||||
|
{
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
span,
|
||||||
|
&format!("{} `impl Trait`'s {}", consider, explicit_static),
|
||||||
|
lifetime_name.clone(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
param.param_ty_span,
|
||||||
|
add_static_bound,
|
||||||
|
param.param_ty.to_string(),
|
||||||
|
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 {
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
fn_return.span.shrink_to_hi(),
|
||||||
|
&format!(
|
||||||
|
"{declare} `impl Trait` {captures}, {explicit}",
|
||||||
|
declare = declare,
|
||||||
|
captures = captures,
|
||||||
|
explicit = explicit,
|
||||||
|
),
|
||||||
|
plus_lt.clone(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
match fn_return.kind {
|
}
|
||||||
TyKind::OpaqueDef(item_id, _) => {
|
TyKind::TraitObject(_, lt) => match lt.name {
|
||||||
let item = self.tcx().hir().item(item_id.id);
|
LifetimeName::ImplicitObjectLifetimeDefault => {
|
||||||
let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind {
|
err.span_suggestion_verbose(
|
||||||
opaque
|
fn_return.span.shrink_to_hi(),
|
||||||
} else {
|
&format!(
|
||||||
err.emit();
|
"{declare} trait object {captures}, {explicit}",
|
||||||
return Some(ErrorReported);
|
declare = declare,
|
||||||
};
|
captures = captures,
|
||||||
|
explicit = explicit,
|
||||||
|
),
|
||||||
|
plus_lt.clone(),
|
||||||
|
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(
|
||||||
|
lt.span,
|
||||||
|
&format!("{} trait object's {}", consider, explicit_static),
|
||||||
|
lifetime_name.clone(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
param.param_ty_span,
|
||||||
|
add_static_bound,
|
||||||
|
param.param_ty.to_string(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err.emit();
|
||||||
|
Some(ErrorReported)
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(span) = opaque
|
/// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default
|
||||||
.bounds
|
/// `'static` obligation. Find `impl` blocks that are implemented
|
||||||
.iter()
|
fn find_impl_on_dyn_trait(&self, err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>) -> bool {
|
||||||
.filter_map(|arg| match arg {
|
let tcx = self.tcx();
|
||||||
GenericBound::Outlives(Lifetime {
|
|
||||||
name: LifetimeName::Static,
|
// Find the trait object types in the argument.
|
||||||
span,
|
let mut v = TraitObjectVisitor(vec![]);
|
||||||
..
|
v.visit_ty(ty);
|
||||||
}) => Some(*span),
|
debug!("TraitObjectVisitor {:?}", v.0);
|
||||||
_ => None,
|
|
||||||
})
|
// Find all the `impl`s in the local scope that can be called on the type parameter.
|
||||||
.next()
|
// FIXME: this doesn't find `impl dyn Trait { /**/ }`.
|
||||||
{
|
let impl_self_tys = tcx
|
||||||
|
.all_traits(LOCAL_CRATE)
|
||||||
|
.iter()
|
||||||
|
.flat_map(|trait_did| tcx.hir().trait_impls(*trait_did))
|
||||||
|
.filter_map(|impl_node| {
|
||||||
|
let impl_did = tcx.hir().local_def_id(*impl_node);
|
||||||
|
if let Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) =
|
||||||
|
tcx.hir().get_if_local(impl_did.to_def_id())
|
||||||
|
{
|
||||||
|
Some(self_ty)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let mut suggested = false;
|
||||||
|
for self_ty in impl_self_tys {
|
||||||
|
if let TyKind::TraitObject(
|
||||||
|
poly_trait_refs,
|
||||||
|
Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. },
|
||||||
|
) = self_ty.kind
|
||||||
|
{
|
||||||
|
for p in poly_trait_refs {
|
||||||
|
if let PolyTraitRef {
|
||||||
|
trait_ref:
|
||||||
|
TraitRef { path: Path { res: Res::Def(DefKind::Trait, did), .. }, .. },
|
||||||
|
..
|
||||||
|
} = p
|
||||||
|
{
|
||||||
|
for found_did in &v.0 {
|
||||||
|
if did == found_did {
|
||||||
|
// We've found an `impl Foo for dyn Bar {}`.
|
||||||
|
// FIXME: we should change this so it also works for
|
||||||
|
// `impl Foo for Box<dyn Bar> {}`.
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
span,
|
self_ty.span.shrink_to_hi(),
|
||||||
&format!("{} `impl Trait`'s {}", consider, explicit_static),
|
"this `impl` introduces an implicit `'static` requirement, \
|
||||||
lifetime_name.clone(),
|
consider changing it",
|
||||||
Applicability::MaybeIncorrect,
|
" + '_".to_string(),
|
||||||
);
|
|
||||||
err.span_suggestion_verbose(
|
|
||||||
param_info.param_ty_span,
|
|
||||||
add_static_bound,
|
|
||||||
param_info.param_ty.to_string(),
|
|
||||||
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 {
|
|
||||||
err.span_suggestion_verbose(
|
|
||||||
fn_return.span.shrink_to_hi(),
|
|
||||||
&format!(
|
|
||||||
"{declare} `impl Trait` {captures}, {explicit}",
|
|
||||||
declare = declare,
|
|
||||||
captures = captures,
|
|
||||||
explicit = explicit,
|
|
||||||
),
|
|
||||||
plus_lt.clone(),
|
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
|
suggested = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyKind::TraitObject(_, lt) => match lt.name {
|
|
||||||
LifetimeName::ImplicitObjectLifetimeDefault => {
|
|
||||||
err.span_suggestion_verbose(
|
|
||||||
fn_return.span.shrink_to_hi(),
|
|
||||||
&format!(
|
|
||||||
"{declare} trait object {captures}, {explicit}",
|
|
||||||
declare = declare,
|
|
||||||
captures = captures,
|
|
||||||
explicit = explicit,
|
|
||||||
),
|
|
||||||
plus_lt.clone(),
|
|
||||||
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(
|
|
||||||
lt.span,
|
|
||||||
&format!("{} trait object's {}", consider, explicit_static),
|
|
||||||
lifetime_name.clone(),
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
err.span_suggestion_verbose(
|
|
||||||
param_info.param_ty_span,
|
|
||||||
add_static_bound,
|
|
||||||
param_info.param_ty.to_string(),
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit();
|
||||||
return Some(ErrorReported);
|
return Some(ErrorReported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
suggested
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collect all the trait objects in a type that could have received an implicit `'static` lifetime.
|
||||||
|
struct TraitObjectVisitor(Vec<DefId>);
|
||||||
|
|
||||||
|
impl TypeVisitor<'_> for TraitObjectVisitor {
|
||||||
|
fn visit_ty(&mut self, t: Ty<'_>) -> bool {
|
||||||
|
match t.kind {
|
||||||
|
ty::Dynamic(preds, RegionKind::ReStatic) => {
|
||||||
|
if let Some(def_id) = preds.principal_def_id() {
|
||||||
|
self.0.push(def_id);
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
_ => t.super_visit_with(self),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ fn baz<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
|
||||||
|
|
||||||
#[cfg(transmute)] // one instantiations: BAD
|
#[cfg(transmute)] // one instantiations: BAD
|
||||||
fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
|
fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
|
||||||
bar(foo, x) //[transmute]~ ERROR E0495
|
bar(foo, x) //[transmute]~ ERROR E0759
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
|
#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
|
||||||
|
|
|
@ -1,26 +1,11 @@
|
||||||
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
--> $DIR/project-fn-ret-contravariant.rs:38:8
|
--> $DIR/project-fn-ret-contravariant.rs:38:8
|
||||||
|
|
|
|
||||||
LL | bar(foo, x)
|
|
||||||
| ^^^
|
|
||||||
|
|
|
||||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 37:8...
|
|
||||||
--> $DIR/project-fn-ret-contravariant.rs:37:8
|
|
||||||
|
|
|
||||||
LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
|
LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
|
||||||
| ^^
|
| ------- this data with lifetime `'a`...
|
||||||
note: ...so that reference does not outlive borrowed content
|
|
||||||
--> $DIR/project-fn-ret-contravariant.rs:38:13
|
|
||||||
|
|
|
||||||
LL | bar(foo, x)
|
LL | bar(foo, x)
|
||||||
| ^
|
| ----^^^---- ...is captured and required to live as long as `'static` here
|
||||||
= note: but, the lifetime must be valid for the static lifetime...
|
|
||||||
note: ...so that reference does not outlive borrowed content
|
|
||||||
--> $DIR/project-fn-ret-contravariant.rs:38:4
|
|
||||||
|
|
|
||||||
LL | bar(foo, x)
|
|
||||||
| ^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0495`.
|
For more information about this error, try `rustc --explain E0759`.
|
||||||
|
|
|
@ -46,7 +46,7 @@ fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
|
||||||
// Cannot instantiate `foo` with any lifetime other than `'a`,
|
// Cannot instantiate `foo` with any lifetime other than `'a`,
|
||||||
// since it is provided as input.
|
// since it is provided as input.
|
||||||
|
|
||||||
bar(foo, x) //[transmute]~ ERROR E0495
|
bar(foo, x) //[transmute]~ ERROR E0759
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
|
#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
|
||||||
|
|
|
@ -1,30 +1,12 @@
|
||||||
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
--> $DIR/project-fn-ret-invariant.rs:49:9
|
--> $DIR/project-fn-ret-invariant.rs:49:9
|
||||||
|
|
|
|
||||||
LL | bar(foo, x)
|
|
||||||
| ^^^
|
|
||||||
|
|
|
||||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 45:8...
|
|
||||||
--> $DIR/project-fn-ret-invariant.rs:45:8
|
|
||||||
|
|
|
||||||
LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
|
LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
|
||||||
| ^^
|
| -------- this data with lifetime `'a`...
|
||||||
note: ...so that the expression is assignable
|
...
|
||||||
--> $DIR/project-fn-ret-invariant.rs:49:14
|
|
||||||
|
|
|
||||||
LL | bar(foo, x)
|
LL | bar(foo, x)
|
||||||
| ^
|
| ----^^^---- ...is captured and required to live as long as `'static` here
|
||||||
= note: expected `Type<'_>`
|
|
||||||
found `Type<'a>`
|
|
||||||
= note: but, the lifetime must be valid for the static lifetime...
|
|
||||||
note: ...so that the expression is assignable
|
|
||||||
--> $DIR/project-fn-ret-invariant.rs:49:5
|
|
||||||
|
|
|
||||||
LL | bar(foo, x)
|
|
||||||
| ^^^^^^^^^^^
|
|
||||||
= note: expected `Type<'static>`
|
|
||||||
found `Type<'_>`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0495`.
|
For more information about this error, try `rustc --explain E0759`.
|
||||||
|
|
|
@ -1,30 +1,17 @@
|
||||||
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
--> $DIR/dyn-trait.rs:20:16
|
--> $DIR/dyn-trait.rs:20:16
|
||||||
|
|
|
|
||||||
LL | static_val(x);
|
|
||||||
| ^
|
|
||||||
|
|
|
||||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 19:26...
|
|
||||||
--> $DIR/dyn-trait.rs:19:26
|
|
||||||
|
|
|
||||||
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
|
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
|
||||||
| ^^
|
| ------------------- this data with lifetime `'a`...
|
||||||
note: ...so that the expression is assignable
|
|
||||||
--> $DIR/dyn-trait.rs:20:16
|
|
||||||
|
|
|
||||||
LL | static_val(x);
|
LL | static_val(x);
|
||||||
| ^
|
| ^ ...is captured here...
|
||||||
= note: expected `std::boxed::Box<dyn std::fmt::Debug>`
|
|
|
||||||
found `std::boxed::Box<(dyn std::fmt::Debug + 'a)>`
|
note: ...and is required to live as long as `'static` here
|
||||||
= note: but, the lifetime must be valid for the static lifetime...
|
|
||||||
note: ...so that the types are compatible
|
|
||||||
--> $DIR/dyn-trait.rs:20:5
|
--> $DIR/dyn-trait.rs:20:5
|
||||||
|
|
|
|
||||||
LL | static_val(x);
|
LL | static_val(x);
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
= note: expected `StaticTrait`
|
|
||||||
found `StaticTrait`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0495`.
|
For more information about this error, try `rustc --explain E0759`.
|
||||||
|
|
|
@ -1,28 +1,11 @@
|
||||||
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
--> $DIR/constant-in-expr-inherent-1.rs:8:5
|
--> $DIR/constant-in-expr-inherent-1.rs:8:5
|
||||||
|
|
|
|
||||||
LL | <Foo<'a>>::C
|
|
||||||
| ^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 7:8...
|
|
||||||
--> $DIR/constant-in-expr-inherent-1.rs:7:8
|
|
||||||
|
|
|
||||||
LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
|
LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
|
||||||
| ^^
|
| ------- this data with lifetime `'a`...
|
||||||
note: ...so that the types are compatible
|
|
||||||
--> $DIR/constant-in-expr-inherent-1.rs:8:5
|
|
||||||
|
|
|
||||||
LL | <Foo<'a>>::C
|
LL | <Foo<'a>>::C
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||||
= note: expected `Foo<'_>`
|
|
||||||
found `Foo<'a>`
|
|
||||||
= note: but, the lifetime must be valid for the static lifetime...
|
|
||||||
note: ...so that reference does not outlive borrowed content
|
|
||||||
--> $DIR/constant-in-expr-inherent-1.rs:8:5
|
|
||||||
|
|
|
||||||
LL | <Foo<'a>>::C
|
|
||||||
| ^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0495`.
|
For more information about this error, try `rustc --explain E0759`.
|
||||||
|
|
|
@ -1,29 +1,11 @@
|
||||||
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
--> $DIR/regions-addr-of-self.rs:7:37
|
--> $DIR/regions-addr-of-self.rs:7:37
|
||||||
|
|
|
|
||||||
|
LL | pub fn chase_cat(&mut self) {
|
||||||
|
| --------- this data with an anonymous lifetime `'_`...
|
||||||
LL | let p: &'static mut usize = &mut self.cats_chased;
|
LL | let p: &'static mut usize = &mut self.cats_chased;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||||
|
|
|
||||||
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
|
|
||||||
--> $DIR/regions-addr-of-self.rs:6:5
|
|
||||||
|
|
|
||||||
LL | / pub fn chase_cat(&mut self) {
|
|
||||||
LL | | let p: &'static mut usize = &mut self.cats_chased;
|
|
||||||
LL | | *p += 1;
|
|
||||||
LL | | }
|
|
||||||
| |_____^
|
|
||||||
note: ...so that reference does not outlive borrowed content
|
|
||||||
--> $DIR/regions-addr-of-self.rs:7:37
|
|
||||||
|
|
|
||||||
LL | let p: &'static mut usize = &mut self.cats_chased;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= note: but, the lifetime must be valid for the static lifetime...
|
|
||||||
note: ...so that reference does not outlive borrowed content
|
|
||||||
--> $DIR/regions-addr-of-self.rs:7:37
|
|
||||||
|
|
|
||||||
LL | let p: &'static mut usize = &mut self.cats_chased;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0495`.
|
For more information about this error, try `rustc --explain E0759`.
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
trait OtherTrait<'a> {}
|
||||||
|
impl<'a> OtherTrait<'a> for &'a () {}
|
||||||
|
|
||||||
|
trait ObjectTrait {}
|
||||||
|
|
||||||
|
impl dyn ObjectTrait {
|
||||||
|
fn use_self(&self) -> &() { panic!() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||||
|
val.use_self() //~ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,18 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs:11:9
|
||||||
|
|
|
||||||
|
LL | val.use_self()
|
||||||
|
| ^^^^^^^^ lifetime mismatch
|
||||||
|
|
|
||||||
|
= note: expected reference `&(dyn ObjectTrait + 'static)`
|
||||||
|
found reference `&(dyn ObjectTrait + 'a)`
|
||||||
|
note: the lifetime `'a` as defined on the function body at 10:11...
|
||||||
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-without-suggestion.rs:10:11
|
||||||
|
|
|
||||||
|
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||||
|
| ^^
|
||||||
|
= note: ...does not necessarily outlive the static lifetime
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
|
@ -0,0 +1,37 @@
|
||||||
|
// run-rustfix
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
mod foo {
|
||||||
|
trait OtherTrait<'a> {}
|
||||||
|
impl<'a> OtherTrait<'a> for &'a () {}
|
||||||
|
|
||||||
|
trait ObjectTrait {}
|
||||||
|
trait MyTrait {
|
||||||
|
fn use_self(&self) -> &();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MyTrait for dyn ObjectTrait + '_ {
|
||||||
|
fn use_self(&self) -> &() { panic!() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||||
|
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod bar {
|
||||||
|
trait ObjectTrait {}
|
||||||
|
trait MyTrait {
|
||||||
|
fn use_self(&self) -> &();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MyTrait for dyn ObjectTrait + '_ {
|
||||||
|
fn use_self(&self) -> &() { panic!() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
|
||||||
|
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,37 @@
|
||||||
|
// run-rustfix
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
mod foo {
|
||||||
|
trait OtherTrait<'a> {}
|
||||||
|
impl<'a> OtherTrait<'a> for &'a () {}
|
||||||
|
|
||||||
|
trait ObjectTrait {}
|
||||||
|
trait MyTrait {
|
||||||
|
fn use_self(&self) -> &();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MyTrait for dyn ObjectTrait {
|
||||||
|
fn use_self(&self) -> &() { panic!() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||||
|
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod bar {
|
||||||
|
trait ObjectTrait {}
|
||||||
|
trait MyTrait {
|
||||||
|
fn use_self(&self) -> &();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MyTrait for dyn ObjectTrait {
|
||||||
|
fn use_self(&self) -> &() { panic!() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
|
||||||
|
val.use_self() //~ ERROR cannot infer an appropriate lifetime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,29 @@
|
||||||
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:18:13
|
||||||
|
|
|
||||||
|
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||||
|
| ------------------- this data with lifetime `'a`...
|
||||||
|
LL | val.use_self()
|
||||||
|
| ^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||||
|
|
|
||||||
|
help: this `impl` introduces an implicit `'static` requirement, consider changing it
|
||||||
|
|
|
||||||
|
LL | impl MyTrait for dyn ObjectTrait + '_ {
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error[E0759]: cannot infer an appropriate lifetime
|
||||||
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:33:13
|
||||||
|
|
|
||||||
|
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
|
||||||
|
| ------------------- this data with lifetime `'a`...
|
||||||
|
LL | val.use_self()
|
||||||
|
| ^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||||
|
|
|
||||||
|
help: this `impl` introduces an implicit `'static` requirement, consider changing it
|
||||||
|
|
|
||||||
|
LL | impl MyTrait for dyn ObjectTrait + '_ {
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0759`.
|
Loading…
Add table
Reference in a new issue