|
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