|
8 | 8 |
|
9 | 9 | use rustc_ast::visit::walk_list; |
10 | 10 | use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; |
11 | | -use rustc_errors::{codes::*, struct_span_code_err}; |
12 | 11 | use rustc_hir as hir; |
13 | 12 | use rustc_hir::def::{DefKind, Res}; |
14 | 13 | use rustc_hir::def_id::LocalDefId; |
@@ -719,34 +718,42 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { |
719 | 718 | // and ban them. Type variables instantiated inside binders aren't |
720 | 719 | // well-supported at the moment, so this doesn't work. |
721 | 720 | // In the future, this should be fixed and this error should be removed. |
722 | | - let def = self.map.defs.get(&lifetime.hir_id).cloned(); |
723 | | - let Some(ResolvedArg::LateBound(_, _, def_id)) = def else { continue }; |
724 | | - let Some(def_id) = def_id.as_local() else { continue }; |
725 | | - let hir_id = self.tcx.local_def_id_to_hir_id(def_id); |
726 | | - // Ensure that the parent of the def is an item, not HRTB |
727 | | - let parent_id = self.tcx.parent_hir_id(hir_id); |
728 | | - if !parent_id.is_owner() { |
729 | | - struct_span_code_err!( |
730 | | - self.tcx.dcx(), |
731 | | - lifetime.ident.span, |
732 | | - E0657, |
733 | | - "`impl Trait` can only capture lifetimes bound at the fn or impl level" |
734 | | - ) |
735 | | - .emit(); |
736 | | - self.uninsert_lifetime_on_error(lifetime, def.unwrap()); |
737 | | - } |
738 | | - if let hir::Node::Item(hir::Item { |
739 | | - kind: hir::ItemKind::OpaqueTy { .. }, .. |
740 | | - }) = self.tcx.hir_node(parent_id) |
| 721 | + let def = self.map.defs.get(&lifetime.hir_id).copied(); |
| 722 | + let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue }; |
| 723 | + let Some(lifetime_def_id) = lifetime_def_id.as_local() else { continue }; |
| 724 | + let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id); |
| 725 | + |
| 726 | + let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id)) |
741 | 727 | { |
742 | | - self.tcx.dcx().struct_span_err( |
743 | | - lifetime.ident.span, |
744 | | - "higher kinded lifetime bounds on nested opaque types are not supported yet", |
745 | | - ) |
746 | | - .with_span_note(self.tcx.def_span(def_id), "lifetime declared here") |
747 | | - .emit(); |
748 | | - self.uninsert_lifetime_on_error(lifetime, def.unwrap()); |
749 | | - } |
| 728 | + // Opaques do not declare their own lifetimes, so if a lifetime comes from an opaque |
| 729 | + // it must be a reified late-bound lifetime from a trait goal. |
| 730 | + hir::Node::Item(hir::Item { |
| 731 | + kind: hir::ItemKind::OpaqueTy { .. }, .. |
| 732 | + }) => "higher-ranked lifetime from outer `impl Trait`", |
| 733 | + // Other items are fine. |
| 734 | + hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => { |
| 735 | + continue; |
| 736 | + } |
| 737 | + hir::Node::Ty(_) => "higher-ranked lifetime from function pointer", |
| 738 | + _ => "higher-ranked lifetime", |
| 739 | + }; |
| 740 | + |
| 741 | + let (span, label) = if lifetime.ident.span == self.tcx.def_span(lifetime_def_id) |
| 742 | + { |
| 743 | + let opaque_span = self.tcx.def_span(item_id.owner_id); |
| 744 | + (opaque_span, Some(opaque_span)) |
| 745 | + } else { |
| 746 | + (lifetime.ident.span, None) |
| 747 | + }; |
| 748 | + |
| 749 | + // Ensure that the parent of the def is an item, not HRTB |
| 750 | + self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime { |
| 751 | + span, |
| 752 | + label, |
| 753 | + decl_span: self.tcx.def_span(lifetime_def_id), |
| 754 | + bad_place, |
| 755 | + }); |
| 756 | + self.uninsert_lifetime_on_error(lifetime, def.unwrap()); |
750 | 757 | } |
751 | 758 | } |
752 | 759 | _ => intravisit::walk_ty(self, ty), |
|
0 commit comments