|
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