-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Tweak output of missing lifetime on associated type #135602
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
364475b
3155687
02b8028
6fcc9f5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; | |
use rustc_data_structures::unord::{UnordMap, UnordSet}; | ||
use rustc_errors::codes::*; | ||
use rustc_errors::{ | ||
Applicability, DiagArgValue, ErrorGuaranteed, IntoDiagArg, StashKey, Suggestions, | ||
Applicability, Diag, DiagArgValue, ErrorGuaranteed, IntoDiagArg, StashKey, Suggestions, | ||
pluralize, | ||
}; | ||
use rustc_hir::def::Namespace::{self, *}; | ||
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; | ||
|
@@ -377,6 +378,7 @@ enum LifetimeBinderKind { | |
Function, | ||
Closure, | ||
ImplBlock, | ||
ImplAssocType, | ||
} | ||
|
||
impl LifetimeBinderKind { | ||
|
@@ -387,6 +389,7 @@ impl LifetimeBinderKind { | |
PolyTrait => "bound", | ||
WhereBound => "bound", | ||
Item | ConstItem => "item", | ||
ImplAssocType => "associated type", | ||
ImplBlock => "impl block", | ||
Function => "function", | ||
Closure => "closure", | ||
|
@@ -1887,9 +1890,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { | |
ty: ty.span, | ||
}); | ||
} else { | ||
self.r.dcx().emit_err(errors::AnonymousLifetimeNonGatReportError { | ||
lifetime: lifetime.ident.span, | ||
}); | ||
let mut err = self.r.dcx().create_err( | ||
errors::AnonymousLifetimeNonGatReportError { | ||
lifetime: lifetime.ident.span, | ||
}, | ||
); | ||
self.point_at_impl_lifetimes(&mut err, i, lifetime.ident.span); | ||
err.emit(); | ||
} | ||
} else { | ||
self.r.dcx().emit_err(errors::ElidedAnonymousLifetimeReportError { | ||
|
@@ -1926,6 +1933,47 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { | |
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None); | ||
} | ||
|
||
fn point_at_impl_lifetimes(&mut self, err: &mut Diag<'_>, i: usize, lifetime: Span) { | ||
let Some((rib, span)) = self.lifetime_ribs[..i] | ||
.iter() | ||
.rev() | ||
.skip(1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can't recall and removing it made no change :) |
||
.filter_map(|rib| match rib.kind { | ||
LifetimeRibKind::Generics { span, kind: LifetimeBinderKind::ImplBlock, .. } => { | ||
Some((rib, span)) | ||
} | ||
_ => None, | ||
}) | ||
.next() | ||
estebank marked this conversation as resolved.
Show resolved
Hide resolved
|
||
else { | ||
return; | ||
}; | ||
if !rib.bindings.is_empty() { | ||
err.span_label( | ||
span, | ||
format!( | ||
"there {} named lifetime{} specified on the impl block you could use", | ||
if rib.bindings.len() == 1 { "is a" } else { "are" }, | ||
pluralize!(rib.bindings.len()), | ||
), | ||
); | ||
if rib.bindings.len() == 1 { | ||
err.span_suggestion_verbose( | ||
lifetime.shrink_to_hi(), | ||
"consider using the lifetime from the impl block", | ||
format!("{} ", rib.bindings.keys().next().unwrap()), | ||
Applicability::MaybeIncorrect, | ||
); | ||
} | ||
} else { | ||
err.span_label( | ||
span, | ||
"you could add a lifetime on the impl block, if the trait or the self type can \ | ||
have one", | ||
); | ||
} | ||
} | ||
|
||
#[instrument(level = "debug", skip(self))] | ||
fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) { | ||
let id = self.r.next_node_id(); | ||
|
@@ -3360,7 +3408,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { | |
&generics.params, | ||
RibKind::AssocItem, | ||
item.id, | ||
LifetimeBinderKind::Item, | ||
LifetimeBinderKind::ImplAssocType, | ||
generics.span, | ||
|this| { | ||
this.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
struct S; | ||
struct T; | ||
|
||
impl<'a> IntoIterator for &S { | ||
//~^ ERROR E0207 | ||
//~| NOTE there is a named lifetime specified on the impl block you could use | ||
//~| NOTE unconstrained lifetime parameter | ||
//~| HELP consider using the named lifetime here instead of an implict lifetime | ||
type Item = &T; | ||
//~^ ERROR in the trait associated type | ||
//~| HELP consider using the lifetime from the impl block | ||
//~| NOTE this lifetime must come from the implemented type | ||
type IntoIter = std::collections::btree_map::Values<'a, i32, T>; | ||
|
||
fn into_iter(self) -> Self::IntoIter { | ||
todo!() | ||
} | ||
} | ||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type | ||
--> $DIR/missing-lifetime-in-assoc-type-1.rs:9:17 | ||
| | ||
LL | impl<'a> IntoIterator for &S { | ||
| ---- there is a named lifetime specified on the impl block you could use | ||
... | ||
LL | type Item = &T; | ||
| ^ this lifetime must come from the implemented type | ||
| | ||
help: consider using the lifetime from the impl block | ||
| | ||
LL | type Item = &'a T; | ||
| ++ | ||
|
||
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates | ||
--> $DIR/missing-lifetime-in-assoc-type-1.rs:4:6 | ||
| | ||
LL | impl<'a> IntoIterator for &S { | ||
| ^^ unconstrained lifetime parameter | ||
| | ||
help: consider using the named lifetime here instead of an implict lifetime | ||
| | ||
LL | impl<'a> IntoIterator for &'a S { | ||
| ++ | ||
Comment on lines
+15
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0207`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
struct S; | ||
struct T; | ||
|
||
impl IntoIterator for &S { | ||
type Item = &T; | ||
//~^ ERROR in the trait associated type | ||
type IntoIter = std::collections::btree_map::Values<'a, i32, T>; | ||
//~^ ERROR use of undeclared lifetime name `'a` | ||
|
||
fn into_iter(self) -> Self::IntoIter { | ||
todo!() | ||
} | ||
} | ||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type | ||
--> $DIR/missing-lifetime-in-assoc-type-2.rs:5:17 | ||
| | ||
LL | impl IntoIterator for &S { | ||
| - you could add a lifetime on the impl block, if the trait or the self type can have one | ||
LL | type Item = &T; | ||
| ^ this lifetime must come from the implemented type | ||
|
||
error[E0261]: use of undeclared lifetime name `'a` | ||
--> $DIR/missing-lifetime-in-assoc-type-2.rs:7:57 | ||
| | ||
LL | type IntoIter = std::collections::btree_map::Values<'a, i32, T>; | ||
| ^^ undeclared lifetime | ||
| | ||
help: consider introducing lifetime `'a` here | ||
| | ||
LL | impl<'a> IntoIterator for &S { | ||
| ++++ | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0261`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
struct S; | ||
struct T; | ||
|
||
impl IntoIterator for &S { | ||
type Item = &T; | ||
//~^ ERROR in the trait associated type | ||
type IntoIter = std::collections::btree_map::Values<i32, T>; | ||
//~^ ERROR missing lifetime specifier | ||
|
||
fn into_iter(self) -> Self::IntoIter { | ||
todo!() | ||
} | ||
} | ||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type | ||
--> $DIR/missing-lifetime-in-assoc-type-3.rs:5:17 | ||
| | ||
LL | impl IntoIterator for &S { | ||
| - you could add a lifetime on the impl block, if the trait or the self type can have one | ||
LL | type Item = &T; | ||
| ^ this lifetime must come from the implemented type | ||
|
||
error[E0106]: missing lifetime specifier | ||
--> $DIR/missing-lifetime-in-assoc-type-3.rs:7:56 | ||
| | ||
LL | type IntoIter = std::collections::btree_map::Values<i32, T>; | ||
| ^ expected named lifetime parameter | ||
| | ||
help: consider introducing a named lifetime parameter | ||
| | ||
LL ~ impl<'a> IntoIterator for &S { | ||
LL | type Item = &T; | ||
LL | | ||
LL ~ type IntoIter = std::collections::btree_map::Values<'a, i32, T>; | ||
| | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0106`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
struct S; | ||
struct T; | ||
|
||
impl IntoIterator for &S { | ||
type Item = &T; | ||
//~^ ERROR in the trait associated type | ||
type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>; | ||
//~^ ERROR lifetime parameters or bounds on associated type `IntoIter` do not match the trait declaration | ||
|
||
fn into_iter(self) -> Self::IntoIter { | ||
todo!() | ||
} | ||
} | ||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type | ||
--> $DIR/missing-lifetime-in-assoc-type-4.rs:5:17 | ||
| | ||
LL | impl IntoIterator for &S { | ||
| - you could add a lifetime on the impl block, if the trait or the self type can have one | ||
LL | type Item = &T; | ||
| ^ this lifetime must come from the implemented type | ||
|
||
error[E0195]: lifetime parameters or bounds on associated type `IntoIter` do not match the trait declaration | ||
--> $DIR/missing-lifetime-in-assoc-type-4.rs:7:18 | ||
| | ||
LL | type IntoIter<'a> = std::collections::btree_map::Values<'a, i32, T>; | ||
| ^^^^ lifetimes do not match associated type in trait | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0195`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
struct S; | ||
struct T; | ||
|
||
impl<'a> IntoIterator for &'_ S { | ||
//~^ ERROR E0207 | ||
//~| NOTE there is a named lifetime specified on the impl block you could use | ||
//~| NOTE unconstrained lifetime parameter | ||
//~| HELP consider using the named lifetime here instead of an implict lifetime | ||
type Item = &T; | ||
//~^ ERROR in the trait associated type | ||
//~| HELP consider using the lifetime from the impl block | ||
//~| NOTE this lifetime must come from the implemented type | ||
type IntoIter = std::collections::btree_map::Values<'a, i32, T>; | ||
|
||
fn into_iter(self) -> Self::IntoIter { | ||
todo!() | ||
} | ||
} | ||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type | ||
--> $DIR/missing-lifetime-in-assoc-type-5.rs:9:17 | ||
| | ||
LL | impl<'a> IntoIterator for &'_ S { | ||
| ---- there is a named lifetime specified on the impl block you could use | ||
... | ||
LL | type Item = &T; | ||
| ^ this lifetime must come from the implemented type | ||
| | ||
help: consider using the lifetime from the impl block | ||
| | ||
LL | type Item = &'a T; | ||
| ++ | ||
|
||
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates | ||
--> $DIR/missing-lifetime-in-assoc-type-5.rs:4:6 | ||
| | ||
LL | impl<'a> IntoIterator for &'_ S { | ||
| ^^ unconstrained lifetime parameter | ||
| | ||
help: consider using the named lifetime here instead of an implict lifetime | ||
| | ||
LL - impl<'a> IntoIterator for &'_ S { | ||
LL + impl<'a> IntoIterator for &'a S { | ||
| | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0207`. |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a comment to the
Item
variant explaining which items it covers? Is it only trait assoc types now? If so better rename it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added