A custom error message for lending iterators
This commit is contained in:
parent
464987730a
commit
d6e4fe569c
@ -234,6 +234,10 @@ resolve_items_in_traits_are_not_importable =
|
||||
resolve_label_with_similar_name_reachable =
|
||||
a label with a similar name is reachable
|
||||
|
||||
resolve_lending_iterator_report_error =
|
||||
associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type.
|
||||
.note = you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type.
|
||||
|
||||
resolve_lifetime_param_in_enum_discriminant =
|
||||
lifetime parameters may not be used in enum discriminant values
|
||||
|
||||
|
@ -882,6 +882,15 @@ pub(crate) struct ElidedAnonymousLivetimeReportError {
|
||||
pub(crate) suggestion: Option<ElidedAnonymousLivetimeReportErrorSuggestion>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(resolve_lending_iterator_report_error)]
|
||||
pub(crate) struct LendingIteratorReportError {
|
||||
#[primary_span]
|
||||
pub(crate) lifetime: Span,
|
||||
#[note]
|
||||
pub(crate) ty: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
resolve_elided_anonymous_lifetime_report_error_suggestion,
|
||||
|
@ -9,7 +9,7 @@
|
||||
use crate::{errors, path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding};
|
||||
use crate::{BindingKey, Used};
|
||||
use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
|
||||
use crate::{ResolutionError, Resolver, Segment, UseError};
|
||||
use crate::{ResolutionError, Resolver, Segment, TyCtxt, UseError};
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::{visit_opt, walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
|
||||
@ -1703,10 +1703,28 @@ fn resolve_anonymous_lifetime(&mut self, lifetime: &Lifetime, elided: bool) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError {
|
||||
span: lifetime.ident.span,
|
||||
suggestion,
|
||||
});
|
||||
|
||||
// Is it caused by user trying to implement a lending iterator?
|
||||
if !self.in_func_body
|
||||
&& let Some((module, _)) = &self.current_trait_ref
|
||||
&& let Some(ty) = &self.diag_metadata.current_self_type
|
||||
&& let crate::ModuleKind::Def(DefKind::Trait, trait_id, _) = module.kind
|
||||
&& def_id_matches_path(
|
||||
self.r.tcx,
|
||||
trait_id,
|
||||
&["core", "iter", "traits", "iterator", "Iterator"],
|
||||
)
|
||||
{
|
||||
self.r.dcx().emit_err(errors::LendingIteratorReportError {
|
||||
lifetime: lifetime.ident.span,
|
||||
ty: ty.span(),
|
||||
});
|
||||
} else {
|
||||
self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError {
|
||||
span: lifetime.ident.span,
|
||||
suggestion,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
self.r.dcx().emit_err(errors::ExplicitAnonymousLivetimeReportError {
|
||||
span: lifetime.ident.span,
|
||||
@ -4824,3 +4842,15 @@ pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if definition matches a path
|
||||
fn def_id_matches_path(tcx: TyCtxt<'_>, mut def_id: DefId, expected_path: &[&str]) -> bool {
|
||||
let mut path = expected_path.iter().rev();
|
||||
while let (Some(parent), Some(next_step)) = (tcx.opt_parent(def_id), path.next()) {
|
||||
if !tcx.opt_item_name(def_id).map_or(false, |n| n.as_str() == *next_step) {
|
||||
return false;
|
||||
}
|
||||
def_id = parent;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
12
tests/ui/lifetimes/no_lending_iterators.rs
Normal file
12
tests/ui/lifetimes/no_lending_iterators.rs
Normal file
@ -0,0 +1,12 @@
|
||||
struct Data(String);
|
||||
|
||||
impl Iterator for Data {
|
||||
type Item = &str;
|
||||
//~^ ERROR 4:17: 4:18: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type.
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
Some(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
14
tests/ui/lifetimes/no_lending_iterators.stderr
Normal file
14
tests/ui/lifetimes/no_lending_iterators.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type.
|
||||
--> $DIR/no_lending_iterators.rs:4:17
|
||||
|
|
||||
LL | type Item = &str;
|
||||
| ^
|
||||
|
|
||||
note: you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type.
|
||||
--> $DIR/no_lending_iterators.rs:3:19
|
||||
|
|
||||
LL | impl Iterator for Data {
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
Loading…
Reference in New Issue
Block a user