|
9 | 9 | use crate::{errors, path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding};
|
10 | 10 | use crate::{BindingKey, Used};
|
11 | 11 | use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
|
12 |
| -use crate::{ResolutionError, Resolver, Segment, UseError}; |
| 12 | +use crate::{ResolutionError, Resolver, Segment, TyCtxt, UseError}; |
13 | 13 |
|
14 | 14 | use rustc_ast::ptr::P;
|
15 | 15 | use rustc_ast::visit::{visit_opt, walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
|
@@ -1703,10 +1703,28 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
1703 | 1703 | break;
|
1704 | 1704 | }
|
1705 | 1705 | }
|
1706 |
| - self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError { |
1707 |
| - span: lifetime.ident.span, |
1708 |
| - suggestion, |
1709 |
| - }); |
| 1706 | + |
| 1707 | + // Is it caused by user trying to implement a lending iterator? |
| 1708 | + if !self.in_func_body |
| 1709 | + && let Some((module, _)) = &self.current_trait_ref |
| 1710 | + && let Some(ty) = &self.diag_metadata.current_self_type |
| 1711 | + && let crate::ModuleKind::Def(DefKind::Trait, trait_id, _) = module.kind |
| 1712 | + && def_id_matches_path( |
| 1713 | + self.r.tcx, |
| 1714 | + trait_id, |
| 1715 | + &["core", "iter", "traits", "iterator", "Iterator"], |
| 1716 | + ) |
| 1717 | + { |
| 1718 | + self.r.dcx().emit_err(errors::LendingIteratorReportError { |
| 1719 | + lifetime: lifetime.ident.span, |
| 1720 | + ty: ty.span(), |
| 1721 | + }); |
| 1722 | + } else { |
| 1723 | + self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError { |
| 1724 | + span: lifetime.ident.span, |
| 1725 | + suggestion, |
| 1726 | + }); |
| 1727 | + } |
1710 | 1728 | } else {
|
1711 | 1729 | self.r.dcx().emit_err(errors::ExplicitAnonymousLivetimeReportError {
|
1712 | 1730 | span: lifetime.ident.span,
|
@@ -4824,3 +4842,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
4824 | 4842 | }
|
4825 | 4843 | }
|
4826 | 4844 | }
|
| 4845 | + |
| 4846 | +/// Check if definition matches a path |
| 4847 | +fn def_id_matches_path(tcx: TyCtxt<'_>, mut def_id: DefId, expected_path: &[&str]) -> bool { |
| 4848 | + let mut path = expected_path.iter().rev(); |
| 4849 | + while let (Some(parent), Some(next_step)) = (tcx.opt_parent(def_id), path.next()) { |
| 4850 | + if !tcx.opt_item_name(def_id).map_or(false, |n| n.as_str() == *next_step) { |
| 4851 | + return false; |
| 4852 | + } |
| 4853 | + def_id = parent; |
| 4854 | + } |
| 4855 | + return true; |
| 4856 | +} |
0 commit comments