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_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
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::error::TypeError;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self,
|
self,
|
||||||
@ -1685,12 +1685,26 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
let hir = &self.tcx.hir();
|
let hir = &self.tcx.hir();
|
||||||
// Attempt to obtain the span of the parameter so we can
|
// Attempt to obtain the span of the parameter so we can
|
||||||
// suggest adding an explicit lifetime bound to it.
|
// suggest adding an explicit lifetime bound to it.
|
||||||
let generics = self
|
let generics =
|
||||||
.in_progress_tables
|
self.in_progress_tables.and_then(|table| table.borrow().hir_owner).map(|table_owner| {
|
||||||
.and_then(|table| table.borrow().hir_owner)
|
let hir_id = hir.as_local_hir_id(table_owner);
|
||||||
.map(|table_owner| self.tcx.generics_of(table_owner.to_def_id()));
|
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) {
|
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`,
|
// Account for the case where `param` corresponds to `Self`,
|
||||||
// which doesn't have the expected type argument.
|
// which doesn't have the expected type argument.
|
||||||
if !(generics.has_self && param.index == 0) {
|
if !(generics.has_self && param.index == 0) {
|
||||||
@ -1727,21 +1741,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
};
|
};
|
||||||
let new_lt = generics
|
let new_lt = generics
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|g| {
|
.and_then(|(parent_g, g)| {
|
||||||
let possible = ["'a", "'b", "'c", "'d", "'e", "'f", "'g", "'h", "'i", "'j", "'k"];
|
let possible = ["'a", "'b", "'c", "'d", "'e", "'f", "'g", "'h", "'i", "'j", "'k"];
|
||||||
let lts_names = g
|
let mut lts_names = g
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
|
.filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
|
||||||
.map(|p| p.name.as_str())
|
.map(|p| p.name.as_str())
|
||||||
.collect::<Vec<_>>();
|
.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<_>>();
|
let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::<Vec<_>>();
|
||||||
possible.iter().filter(|&candidate| !lts.contains(&*candidate)).next().map(|s| *s)
|
possible.iter().filter(|&candidate| !lts.contains(&*candidate)).next().map(|s| *s)
|
||||||
})
|
})
|
||||||
.unwrap_or("'lt");
|
.unwrap_or("'lt");
|
||||||
let add_lt_sugg = generics
|
let add_lt_sugg = generics
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|g| g.params.first())
|
.and_then(|(_, g)| g.params.first())
|
||||||
.and_then(|param| param.def_id.as_local())
|
.and_then(|param| param.def_id.as_local())
|
||||||
.map(|def_id| {
|
.map(|def_id| {
|
||||||
(hir.span(hir.as_local_hir_id(def_id)).shrink_to_lo(), format!("{}, ", new_lt))
|
(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), _) => (
|
(Some(ret_span), _) => (
|
||||||
ty_sub.span,
|
ty_sub.span,
|
||||||
ret_span,
|
ret_span,
|
||||||
"this parameter and the return type are declared \
|
"this parameter and the return type are declared with different lifetimes..."
|
||||||
with different lifetimes..."
|
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
format!("...but data{} is returned here", span_label_var1),
|
format!("...but data{} is returned here", span_label_var1),
|
||||||
),
|
),
|
||||||
(_, Some(ret_span)) => (
|
(_, Some(ret_span)) => (
|
||||||
ty_sup.span,
|
ty_sup.span,
|
||||||
ret_span,
|
ret_span,
|
||||||
"this parameter and the return type are declared \
|
"this parameter and the return type are declared with different lifetimes..."
|
||||||
with different lifetimes..."
|
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
format!("...but data{} is returned here", span_label_var1),
|
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
|
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
|
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...
|
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:58: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 | / fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
|
||||||
LL | |
|
LL | |
|
||||||
@ -74,7 +91,7 @@ LL | | }
|
|||||||
| |_^
|
| |_^
|
||||||
|
|
||||||
error[E0621]: explicit lifetime required in the type of `dest`
|
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
|
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`
|
| ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
|
||||||
@ -85,14 +102,14 @@ LL | | }
|
|||||||
| |_____^ lifetime `'a` required
|
| |_____^ lifetime `'a` required
|
||||||
|
|
||||||
error[E0309]: the parameter type `G` may not live long enough
|
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
|
LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: consider adding an explicit lifetime bound `G: '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.
|
Some errors have detailed explanations: E0261, E0309, E0621.
|
||||||
For more information about an error, try `rustc --explain E0261`.
|
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`:
|
// After applying suggestion for `qux`:
|
||||||
fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
|
fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
|
||||||
//~^ ERROR explicit lifetime required in the type of `dest`
|
//~^ 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
|
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`
|
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
|
LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
|
||||||
| ------ ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
|
| ------ ^^^^^^^^^^^^^^^^^^^^^^^ 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`
|
| help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
|
||||||
|
|
||||||
error[E0309]: the parameter type `G` may not live long enough
|
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
|
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`
|
| 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.
|
Some errors have detailed explanations: E0261, E0309, E0621.
|
||||||
For more information about an error, try `rustc --explain E0261`.
|
For more information about an error, try `rustc --explain E0261`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user