Suggest substituting `'static` lifetime in impl/dyn `Trait + 'static` return types
This commit is contained in:
parent
ff4a2533a0
commit
81c909488e
|
@ -4,6 +4,7 @@ use crate::infer::error_reporting::msg_span_from_free_region;
|
|||
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
||||
use rustc_errors::{Applicability, ErrorReported};
|
||||
use rustc_hir::{GenericBound, ItemKind, Lifetime, LifetimeName, TyKind};
|
||||
use rustc_middle::ty::RegionKind;
|
||||
|
||||
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||
|
@ -20,8 +21,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
) = error.clone()
|
||||
{
|
||||
let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?;
|
||||
let (fn_return_span, is_dyn) =
|
||||
self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?;
|
||||
let fn_return = self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?;
|
||||
let is_dyn = matches!(fn_return.kind, TyKind::TraitObject(..));
|
||||
let fn_return_span = fn_return.span;
|
||||
if sub_r == &RegionKind::ReStatic {
|
||||
let sp = var_origin.span();
|
||||
let return_sp = sub_origin.span();
|
||||
|
@ -67,12 +69,58 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
lifetime,
|
||||
);
|
||||
// FIXME: account for the need of parens in `&(dyn Trait + '_)`
|
||||
err.span_suggestion_verbose(
|
||||
fn_return_span.shrink_to_hi(),
|
||||
&msg,
|
||||
format!(" + {}", lifetime_name),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
match fn_return.kind {
|
||||
TyKind::Def(item_id, _) => {
|
||||
let item = self.tcx().hir().item(item_id.id);
|
||||
let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind {
|
||||
opaque
|
||||
} else {
|
||||
err.emit();
|
||||
return Some(ErrorReported);
|
||||
};
|
||||
let (span, sugg) = opaque
|
||||
.bounds
|
||||
.iter()
|
||||
.filter_map(|arg| match arg {
|
||||
GenericBound::Outlives(Lifetime {
|
||||
name: LifetimeName::Static,
|
||||
span,
|
||||
..
|
||||
}) => Some((*span, lifetime_name.clone())),
|
||||
_ => None,
|
||||
})
|
||||
.next()
|
||||
.unwrap_or_else(|| {
|
||||
(
|
||||
fn_return_span.shrink_to_hi(),
|
||||
format!(" + {}", lifetime_name),
|
||||
)
|
||||
});
|
||||
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
&msg,
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
TyKind::TraitObject(_, lt) => {
|
||||
let (span, sugg) = match lt.name {
|
||||
LifetimeName::ImplicitObjectLifetimeDefault => (
|
||||
fn_return_span.shrink_to_hi(),
|
||||
format!(" + {}", lifetime_name),
|
||||
),
|
||||
_ => (lt.span, lifetime_name),
|
||||
};
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
&msg,
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
return Some(ErrorReported);
|
||||
|
|
|
@ -1383,7 +1383,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn return_type_impl_or_dyn_trait(&self, scope_def_id: DefId) -> Option<(Span, bool)> {
|
||||
pub fn return_type_impl_or_dyn_trait(
|
||||
&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_output = match self.hir().get(hir_id) {
|
||||
Node::Item(hir::Item {
|
||||
|
@ -1429,15 +1432,17 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
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();
|
||||
Some((fn_decl.output.span(), false))
|
||||
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], true));
|
||||
return Some(v.0[0]);
|
||||
}
|
||||
None
|
||||
}
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
|
|
|
@ -236,21 +236,21 @@ pub fn suggest_constraining_type_param(
|
|||
}
|
||||
}
|
||||
|
||||
pub struct TraitObjectVisitor(pub Vec<rustc_span::Span>);
|
||||
impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor {
|
||||
pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>);
|
||||
impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
|
||||
type Map = rustc_hir::intravisit::ErasedMap<'v>;
|
||||
|
||||
fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
|
||||
hir::intravisit::NestedVisitorMap::None
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
|
||||
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
|
||||
if let hir::TyKind::TraitObject(
|
||||
_,
|
||||
hir::Lifetime { name: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. },
|
||||
) = ty.kind
|
||||
{
|
||||
self.0.push(ty.span);
|
||||
self.0.push(ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,34 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
|
|||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:12:69
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:9:46
|
||||
|
|
||||
LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
|
||||
| - ^ returning this value requires that `'1` must outlive `'static`
|
||||
| |
|
||||
| let's call the lifetime of this reference `'1`
|
||||
|
|
||||
= help: consider replacing `'1` with `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:12:55
|
||||
|
|
||||
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
|
||||
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
|
||||
|
|
||||
= help: consider replacing `'a` with `'static`
|
||||
= help: consider replacing `'a` with `'static`
|
||||
|
||||
error[E0621]: explicit lifetime required in the type of `x`
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:15:41
|
||||
|
|
||||
LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
|
||||
| ---- ^ lifetime `'a` required
|
||||
| |
|
||||
| help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:33:69
|
||||
|
|
||||
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`
|
||||
|
@ -35,7 +62,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
|
|||
= help: consider replacing `'a` with `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:17:61
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:38:61
|
||||
|
|
||||
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`
|
||||
|
@ -45,13 +72,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`
|
||||
|
||||
error[E0310]: the parameter type `T` may not live long enough
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:22:51
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:43:51
|
||||
|
|
||||
LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider adding an explicit lifetime bound `T: 'static`...
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0310`.
|
||||
Some errors have detailed explanations: E0310, E0621.
|
||||
For more information about an error, try `rustc --explain E0310`.
|
||||
|
|
|
@ -6,6 +6,27 @@ fn elided(x: &i32) -> impl Copy { x }
|
|||
fn explicit<'a>(x: &'a i32) -> impl Copy { x }
|
||||
//~^ ERROR cannot infer an appropriate lifetime
|
||||
|
||||
fn elided2(x: &i32) -> impl Copy + 'static { x }
|
||||
//~^ ERROR cannot infer an appropriate lifetime
|
||||
|
||||
fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
|
||||
//~^ ERROR cannot infer an appropriate lifetime
|
||||
|
||||
fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
|
||||
//~^ ERROR explicit lifetime required in the type of `x`
|
||||
|
||||
fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
|
||||
//~^ ERROR cannot infer an appropriate lifetime
|
||||
|
||||
fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
|
||||
//~^ ERROR cannot infer an appropriate lifetime
|
||||
|
||||
fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||
//~^ ERROR explicit lifetime required in the type of `x`
|
||||
|
||||
fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||
//~^ ERROR cannot infer an appropriate lifetime
|
||||
|
||||
trait LifetimeTrait<'a> {}
|
||||
impl<'a> LifetimeTrait<'a> for &'a i32 {}
|
||||
|
||||
|
|
|
@ -27,7 +27,43 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
|
|||
| ^^^^
|
||||
|
||||
error: cannot infer an appropriate lifetime
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:12:69
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:9:46
|
||||
|
|
||||
LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
|
||||
| ---- ------------------- ^ ...and is captured here
|
||||
| | |
|
||||
| | ...is required to be `'static` by this...
|
||||
| data with this lifetime...
|
||||
|
|
||||
help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 9:1
|
||||
|
|
||||
LL | fn elided2(x: &i32) -> impl Copy + '_ { x }
|
||||
| ^^
|
||||
|
||||
error: cannot infer an appropriate lifetime
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:12:55
|
||||
|
|
||||
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
|
||||
| ------- ------------------- ^ ...and is captured here
|
||||
| | |
|
||||
| | ...is required to be `'static` by this...
|
||||
| data with this lifetime...
|
||||
|
|
||||
help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:14
|
||||
|
|
||||
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x }
|
||||
| ^^
|
||||
|
||||
error[E0621]: explicit lifetime required in the type of `x`
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:15:24
|
||||
|
|
||||
LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
|
||||
| ---- ^^^^^^^^^^^^^^ lifetime `'a` required
|
||||
| |
|
||||
| help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
|
||||
|
||||
error: cannot infer an appropriate lifetime
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:33:69
|
||||
|
|
||||
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
|
||||
| ------- -------------------------------- ^ ...and is captured here
|
||||
|
@ -35,13 +71,13 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
|
|||
| | ...is required to be `'static` by this...
|
||||
| data with this lifetime...
|
||||
|
|
||||
help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:15
|
||||
help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 33:15
|
||||
|
|
||||
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x }
|
||||
| ^^^^
|
||||
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x }
|
||||
| ^^
|
||||
|
||||
error[E0623]: lifetime mismatch
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:17:61
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:38:61
|
||||
|
|
||||
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
|
||||
| ------- ^^^^^^^^^^^^^^^^
|
||||
|
@ -50,14 +86,79 @@ 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...
|
||||
|
||||
error[E0310]: the parameter type `T` may not live long enough
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:22:51
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:43:51
|
||||
|
|
||||
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
|
||||
| |
|
||||
| help: consider adding an explicit lifetime bound...: `T: 'static +`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: cannot infer an appropriate lifetime
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:18:50
|
||||
|
|
||||
LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
|
||||
| ---- ---------^-
|
||||
| | | |
|
||||
| | | ...and is captured here
|
||||
| | ...is required to be `'static` by this...
|
||||
| data with this lifetime...
|
||||
|
|
||||
help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 18:1
|
||||
|
|
||||
LL | fn elided3(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) }
|
||||
| ^^^^
|
||||
|
||||
Some errors have detailed explanations: E0310, E0623.
|
||||
error: cannot infer an appropriate lifetime
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:21:59
|
||||
|
|
||||
LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
|
||||
| ------- ---------^-
|
||||
| | | |
|
||||
| | | ...and is captured here
|
||||
| | ...is required to be `'static` by this...
|
||||
| data with this lifetime...
|
||||
|
|
||||
help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 21:14
|
||||
|
|
||||
LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) }
|
||||
| ^^^^
|
||||
|
||||
error[E0621]: explicit lifetime required in the type of `x`
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:24:51
|
||||
|
|
||||
LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||
| ---- ^^^^^^^^^^^ lifetime `'static` required
|
||||
| |
|
||||
| help: add explicit lifetime `'static` to the type of `x`: `&'static i32`
|
||||
|
||||
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:27:69
|
||||
|
|
||||
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||
| ^
|
||||
|
|
||||
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 27:14...
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:27:14
|
||||
|
|
||||
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||
| ^^
|
||||
note: ...so that the expression is assignable
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:27:69
|
||||
|
|
||||
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||
| ^
|
||||
= note: expected `&i32`
|
||||
found `&'a i32`
|
||||
= note: but, the lifetime must be valid for the static lifetime...
|
||||
note: ...so that the expression is assignable
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:27:60
|
||||
|
|
||||
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||
| ^^^^^^^^^^^
|
||||
= note: expected `std::boxed::Box<(dyn std::fmt::Debug + 'static)>`
|
||||
found `std::boxed::Box<dyn std::fmt::Debug>`
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0310, E0495, E0621, E0623.
|
||||
For more information about an error, try `rustc --explain E0310`.
|
||||
|
|
Loading…
Reference in New Issue