Use a more accurate Span
for 'static
obligation from return type
This commit is contained in:
parent
ee0fd105d8
commit
10a74ac2e0
12 changed files with 85 additions and 79 deletions
|
@ -10,7 +10,8 @@ use rustc_hir::def_id::DefId;
|
|||
use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor};
|
||||
use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind};
|
||||
use rustc_middle::ty::{
|
||||
self, AssocItemContainer, RegionKind, Ty, TyCtxt, TypeFoldable, TypeVisitor,
|
||||
self, AssocItemContainer, RegionKind, StaticLifetimeVisitor, Ty, TyCtxt, TypeFoldable,
|
||||
TypeVisitor,
|
||||
};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{MultiSpan, Span};
|
||||
|
@ -186,10 +187,27 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
let parent_id = tcx.hir().get_parent_item(*hir_id);
|
||||
if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id) {
|
||||
let mut span: MultiSpan = fn_decl.output.span().into();
|
||||
span.push_span_label(
|
||||
fn_decl.output.span(),
|
||||
"requirement introduced by this return type".to_string(),
|
||||
);
|
||||
let mut add_label = true;
|
||||
if let hir::FnRetTy::Return(ty) = fn_decl.output {
|
||||
let mut v = StaticLifetimeVisitor(vec![], tcx.hir());
|
||||
v.visit_ty(ty);
|
||||
if !v.0.is_empty() {
|
||||
span = v.0.clone().into();
|
||||
for sp in v.0 {
|
||||
span.push_span_label(
|
||||
sp,
|
||||
"`'static` requirement introduced here".to_string(),
|
||||
);
|
||||
}
|
||||
add_label = false;
|
||||
}
|
||||
}
|
||||
if add_label {
|
||||
span.push_span_label(
|
||||
fn_decl.output.span(),
|
||||
"requirement introduced by this return type".to_string(),
|
||||
);
|
||||
}
|
||||
span.push_span_label(
|
||||
cause.span,
|
||||
"because of this returned expression".to_string(),
|
||||
|
|
|
@ -1481,40 +1481,8 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
scope_def_id: LocalDefId,
|
||||
) -> Vec<&'tcx hir::Ty<'tcx>> {
|
||||
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
|
||||
let hir_output = match self.hir().get(hir_id) {
|
||||
Node::Item(hir::Item {
|
||||
kind:
|
||||
ItemKind::Fn(
|
||||
hir::FnSig {
|
||||
decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
|
||||
..
|
||||
},
|
||||
..,
|
||||
),
|
||||
..
|
||||
})
|
||||
| Node::ImplItem(hir::ImplItem {
|
||||
kind:
|
||||
hir::ImplItemKind::Fn(
|
||||
hir::FnSig {
|
||||
decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
|
||||
..
|
||||
},
|
||||
_,
|
||||
),
|
||||
..
|
||||
})
|
||||
| Node::TraitItem(hir::TraitItem {
|
||||
kind:
|
||||
hir::TraitItemKind::Fn(
|
||||
hir::FnSig {
|
||||
decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
|
||||
..
|
||||
},
|
||||
_,
|
||||
),
|
||||
..
|
||||
}) => ty,
|
||||
let hir_output = match self.hir().fn_decl_by_hir_id(hir_id) {
|
||||
Some(hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }) => ty,
|
||||
_ => return vec![],
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate};
|
||||
use rustc_span::Span;
|
||||
|
||||
impl<'tcx> TyS<'tcx> {
|
||||
/// Similar to `TyS::is_primitive`, but also considers inferred numeric values to be primitive.
|
||||
|
@ -432,3 +433,22 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
|
|||
hir::intravisit::walk_ty(self, ty);
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for.
|
||||
pub struct StaticLifetimeVisitor<'tcx>(pub Vec<Span>, pub crate::hir::map::Map<'tcx>);
|
||||
|
||||
impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'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_lifetime(&mut self, lt: &'v hir::Lifetime) {
|
||||
if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static =
|
||||
lt.name
|
||||
{
|
||||
self.0.push(lt.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,10 +8,10 @@ LL | bar(foo, x)
|
|||
| ^^^ - ...is captured and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/project-fn-ret-invariant.rs:45:32
|
||||
--> $DIR/project-fn-ret-invariant.rs:45:37
|
||||
|
|
||||
LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
|
||||
| ^^^^^^^^^^^^^ requirement introduced by this return type
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
...
|
||||
LL | bar(foo, x)
|
||||
| ----------- because of this returned expression
|
||||
|
|
|
@ -141,12 +141,12 @@ LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
|
|||
| this data with an anonymous lifetime `'_`...
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:14:24
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:14:28
|
||||
|
|
||||
LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
|
||||
| ^^^^^^^^^^^^^^ ----------- because of this returned expression
|
||||
| |
|
||||
| requirement introduced by this return type
|
||||
| ^^^^^^^^^ ----------- because of this returned expression
|
||||
| |
|
||||
| `'static` requirement introduced here
|
||||
help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
LL | fn elided3(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) }
|
||||
|
@ -161,12 +161,12 @@ LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
|
|||
| this data with lifetime `'a`...
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:16:33
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:16:37
|
||||
|
|
||||
LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
|
||||
| ^^^^^^^^^^^^^^ ----------- because of this returned expression
|
||||
| |
|
||||
| requirement introduced by this return type
|
||||
| ^^^^^^^^^ ----------- because of this returned expression
|
||||
| |
|
||||
| `'static` requirement introduced here
|
||||
help: to declare that the trait object captures data from argument `x`, you can add an explicit `'a` lifetime bound
|
||||
|
|
||||
LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) }
|
||||
|
@ -181,12 +181,12 @@ LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
|||
| this data with an anonymous lifetime `'_`...
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:18:24
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:18:40
|
||||
|
|
||||
LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- because of this returned expression
|
||||
| |
|
||||
| requirement introduced by this return type
|
||||
| ^^^^^^^ ----------- because of this returned expression
|
||||
| |
|
||||
| `'static` requirement introduced here
|
||||
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
|
||||
|
|
||||
LL | fn elided4(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) }
|
||||
|
@ -203,12 +203,12 @@ LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
|||
| ------- this data with lifetime `'a`... ^ ...is captured and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:20:33
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:20:49
|
||||
|
|
||||
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- because of this returned expression
|
||||
| |
|
||||
| requirement introduced by this return type
|
||||
| ^^^^^^^ ----------- because of this returned expression
|
||||
| |
|
||||
| `'static` requirement introduced here
|
||||
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
|
||||
|
|
||||
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) }
|
||||
|
|
|
@ -8,10 +8,10 @@ LL | ss.r
|
|||
| ^^^^ ...is captured and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/object-lifetime-default-from-box-error.rs:14:33
|
||||
--> $DIR/object-lifetime-default-from-box-error.rs:14:37
|
||||
|
|
||||
LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
|
||||
| ^^^^^^^^^^^^^^^^^^ requirement introduced by this return type
|
||||
| ^^^^^^^^^^^^^ `'static` requirement introduced here
|
||||
...
|
||||
LL | ss.r
|
||||
| ---- because of this returned expression
|
||||
|
|
|
@ -24,10 +24,10 @@ LL | Box::new(v)
|
|||
| ^ ...is captured and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/region-object-lifetime-in-coercion.rs:12:19
|
||||
--> $DIR/region-object-lifetime-in-coercion.rs:12:33
|
||||
|
|
||||
LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
LL | Box::new(v)
|
||||
| ----------- because of this returned expression
|
||||
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
|
||||
|
@ -49,10 +49,10 @@ LL | Box::new(v)
|
|||
| ^ ...is captured and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/region-object-lifetime-in-coercion.rs:16:19
|
||||
--> $DIR/region-object-lifetime-in-coercion.rs:16:23
|
||||
|
|
||||
LL | fn c(v: &[u8]) -> Box<dyn Foo> {
|
||||
| ^^^^^^^^^^^^ requirement introduced by this return type
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
...
|
||||
LL | Box::new(v)
|
||||
| ----------- because of this returned expression
|
||||
|
|
|
@ -7,10 +7,10 @@ LL | Box::new(B(&*v)) as Box<dyn X>
|
|||
| ^^^ ...is captured and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/regions-close-object-into-object-2.rs:8:48
|
||||
--> $DIR/regions-close-object-into-object-2.rs:8:60
|
||||
|
|
||||
LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
LL | Box::new(B(&*v)) as Box<dyn X>
|
||||
| ------------------------------ because of this returned expression
|
||||
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
|
||||
|
|
|
@ -7,10 +7,10 @@ LL | Box::new(B(&*v)) as Box<dyn X>
|
|||
| ^^^ ...is captured and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/regions-close-object-into-object-4.rs:8:40
|
||||
--> $DIR/regions-close-object-into-object-4.rs:8:52
|
||||
|
|
||||
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
LL | Box::new(B(&*v)) as Box<dyn X>
|
||||
| ------------------------------ because of this returned expression
|
||||
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
|
||||
|
|
|
@ -8,10 +8,10 @@ LL | Box::new(move || { *x })
|
|||
| ^^^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/regions-proc-bound-capture.rs:7:30
|
||||
--> $DIR/regions-proc-bound-capture.rs:7:59
|
||||
|
|
||||
LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
LL | // This is illegal, because the region bound on `proc` is 'static.
|
||||
LL | Box::new(move || { *x })
|
||||
| ------------------------ because of this returned expression
|
||||
|
|
|
@ -47,10 +47,10 @@ note: ...and is required to live as long as `'static` here
|
|||
LL | y.get_b() // ERROR
|
||||
| ^^^^^^^^^
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/type-checking-test-4.rs:26:40
|
||||
--> $DIR/type-checking-test-4.rs:26:48
|
||||
|
|
||||
LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
...
|
||||
LL | y.get_b() // ERROR
|
||||
| --------- because of this returned expression
|
||||
|
@ -64,10 +64,10 @@ LL | <_ as Bar>::get_b(x) // ERROR
|
|||
| ^^^^^^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/type-checking-test-4.rs:32:40
|
||||
--> $DIR/type-checking-test-4.rs:32:48
|
||||
|
|
||||
LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
LL | <_ as Bar>::get_b(x) // ERROR
|
||||
| -------------------- because of this returned expression
|
||||
|
||||
|
@ -80,10 +80,10 @@ LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR
|
|||
| ----------^^------------- ...is captured and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/type-checking-test-4.rs:37:40
|
||||
--> $DIR/type-checking-test-4.rs:37:48
|
||||
|
|
||||
LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR
|
||||
| ---------------------------- because of this returned expression
|
||||
|
||||
|
@ -109,10 +109,10 @@ note: ...and is required to live as long as `'static` here
|
|||
LL | z.get_b() // ERROR
|
||||
| ^^^^^^^^^
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/type-checking-test-4.rs:42:40
|
||||
--> $DIR/type-checking-test-4.rs:42:48
|
||||
|
|
||||
LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
...
|
||||
LL | z.get_b() // ERROR
|
||||
| --------- because of this returned expression
|
||||
|
|
|
@ -10,10 +10,10 @@ LL | Box::new(items.iter())
|
|||
| ...is captured and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/dyn-trait-underscore.rs:6:25
|
||||
--> $DIR/dyn-trait-underscore.rs:6:29
|
||||
|
|
||||
LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ requirement introduced by this return type
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ `'static` requirement introduced here
|
||||
LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
|
||||
LL | Box::new(items.iter())
|
||||
| ---------------------- because of this returned expression
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue