Account for enclosing item when suggesting new lifetime name
This commit is contained in:
parent
8f7ee34379
commit
224ad326ea
@ -60,7 +60,7 @@ use rustc_errors::{pluralize, struct_span_err};
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::Node;
|
||||
use rustc_hir::{Item, ItemKind, Node};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::{
|
||||
self,
|
||||
@ -1685,12 +1685,26 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
let hir = &self.tcx.hir();
|
||||
// Attempt to obtain the span of the parameter so we can
|
||||
// suggest adding an explicit lifetime bound to it.
|
||||
let generics = self
|
||||
.in_progress_tables
|
||||
.and_then(|table| table.borrow().hir_owner)
|
||||
.map(|table_owner| self.tcx.generics_of(table_owner.to_def_id()));
|
||||
let generics =
|
||||
self.in_progress_tables.and_then(|table| table.borrow().hir_owner).map(|table_owner| {
|
||||
let hir_id = hir.as_local_hir_id(table_owner);
|
||||
let parent_id = hir.get_parent_item(hir_id);
|
||||
(
|
||||
// Parent item could be a `mod`, so we check the HIR before calling:
|
||||
if let Some(Node::Item(Item {
|
||||
kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
|
||||
..
|
||||
})) = hir.find(parent_id)
|
||||
{
|
||||
Some(self.tcx.generics_of(hir.local_def_id(parent_id).to_def_id()))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
self.tcx.generics_of(table_owner.to_def_id()),
|
||||
)
|
||||
});
|
||||
let type_param_span = match (generics, bound_kind) {
|
||||
(Some(ref generics), GenericKind::Param(ref param)) => {
|
||||
(Some((_, ref generics)), GenericKind::Param(ref param)) => {
|
||||
// Account for the case where `param` corresponds to `Self`,
|
||||
// which doesn't have the expected type argument.
|
||||
if !(generics.has_self && param.index == 0) {
|
||||
@ -1727,21 +1741,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
};
|
||||
let new_lt = generics
|
||||
.as_ref()
|
||||
.and_then(|g| {
|
||||
.and_then(|(parent_g, g)| {
|
||||
let possible = ["'a", "'b", "'c", "'d", "'e", "'f", "'g", "'h", "'i", "'j", "'k"];
|
||||
let lts_names = g
|
||||
let mut lts_names = g
|
||||
.params
|
||||
.iter()
|
||||
.filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
|
||||
.map(|p| p.name.as_str())
|
||||
.collect::<Vec<_>>();
|
||||
if let Some(g) = parent_g {
|
||||
lts_names.extend(
|
||||
g.params
|
||||
.iter()
|
||||
.filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
|
||||
.map(|p| p.name.as_str()),
|
||||
);
|
||||
}
|
||||
let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::<Vec<_>>();
|
||||
possible.iter().filter(|&candidate| !lts.contains(&*candidate)).next().map(|s| *s)
|
||||
})
|
||||
.unwrap_or("'lt");
|
||||
let add_lt_sugg = generics
|
||||
.as_ref()
|
||||
.and_then(|g| g.params.first())
|
||||
.and_then(|(_, g)| g.params.first())
|
||||
.and_then(|param| param.def_id.as_local())
|
||||
.map(|def_id| {
|
||||
(hir.span(hir.as_local_hir_id(def_id)).shrink_to_lo(), format!("{}, ", new_lt))
|
||||
|
@ -121,16 +121,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||
(Some(ret_span), _) => (
|
||||
ty_sub.span,
|
||||
ret_span,
|
||||
"this parameter and the return type are declared \
|
||||
with different lifetimes..."
|
||||
"this parameter and the return type are declared with different lifetimes..."
|
||||
.to_owned(),
|
||||
format!("...but data{} is returned here", span_label_var1),
|
||||
),
|
||||
(_, Some(ret_span)) => (
|
||||
ty_sup.span,
|
||||
ret_span,
|
||||
"this parameter and the return type are declared \
|
||||
with different lifetimes..."
|
||||
"this parameter and the return type are declared with different lifetimes..."
|
||||
.to_owned(),
|
||||
format!("...but data{} is returned here", span_label_var1),
|
||||
),
|
||||
|
@ -56,13 +56,30 @@ LL | | }
|
||||
| |_^
|
||||
|
||||
error[E0311]: the parameter type `G` may not live long enough
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:58:45
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:59:58
|
||||
|
|
||||
LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the method body at 59:5...
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:59:5
|
||||
|
|
||||
LL | / fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
|
||||
LL | |
|
||||
LL | | move || {
|
||||
LL | | *dest = g.get();
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
||||
error[E0311]: the parameter type `G` may not live long enough
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:68:45
|
||||
|
|
||||
LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 58:1...
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:58:1
|
||||
note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 68:1...
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:68:1
|
||||
|
|
||||
LL | / fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
|
||||
LL | |
|
||||
@ -74,7 +91,7 @@ LL | | }
|
||||
| |_^
|
||||
|
||||
error[E0621]: explicit lifetime required in the type of `dest`
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:63:5
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:73:5
|
||||
|
|
||||
LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
|
||||
| ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
|
||||
@ -85,14 +102,14 @@ LL | | }
|
||||
| |_____^ lifetime `'a` required
|
||||
|
||||
error[E0309]: the parameter type `G` may not live long enough
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:69:44
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:79:44
|
||||
|
|
||||
LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider adding an explicit lifetime bound `G: 'a`...
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0261, E0309, E0621.
|
||||
For more information about an error, try `rustc --explain E0261`.
|
||||
|
@ -54,6 +54,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// Same as above, but show that we pay attention to lifetime names from parent item
|
||||
impl<'a> Foo {
|
||||
fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
|
||||
//~^ ERROR the parameter type `G` may not live long enough
|
||||
move || {
|
||||
*dest = g.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// After applying suggestion for `qux`:
|
||||
fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
|
||||
//~^ ERROR explicit lifetime required in the type of `dest`
|
||||
|
@ -87,8 +87,34 @@ help: consider introducing an explicit lifetime bound
|
||||
LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b
|
||||
| ^^^ ^^^^^^^ ^^^^
|
||||
|
||||
error[E0311]: the parameter type `G` may not live long enough
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:59:58
|
||||
|
|
||||
LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the method body at 59:5...
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:59:5
|
||||
|
|
||||
LL | / fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
|
||||
LL | |
|
||||
LL | | move || {
|
||||
LL | | *dest = g.get();
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_____^
|
||||
note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:61:9: 63:10 g:G, dest:&mut T]` will meet its required lifetime bounds
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:59:58
|
||||
|
|
||||
LL | fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
help: consider introducing an explicit lifetime bound
|
||||
|
|
||||
LL | fn qux<'c, 'b, G: 'c + Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'c {
|
||||
| ^^^ ^^^^^^^ ^^^^
|
||||
|
||||
error[E0621]: explicit lifetime required in the type of `dest`
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:58:45
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:68:45
|
||||
|
|
||||
LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
|
||||
| ------ ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
|
||||
@ -96,14 +122,14 @@ LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
|
||||
| help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
|
||||
|
||||
error[E0309]: the parameter type `G` may not live long enough
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:69:44
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:79:44
|
||||
|
|
||||
LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
|
||||
| - ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:74:5: 76:6 g:G, dest:&mut T]` will meet its required lifetime bounds
|
||||
| - ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:84:5: 86:6 g:G, dest:&mut T]` will meet its required lifetime bounds
|
||||
| |
|
||||
| help: consider adding an explicit lifetime bound...: `G: 'a`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0261, E0309, E0621.
|
||||
For more information about an error, try `rustc --explain E0261`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user