|
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; |
@@ -673,34 +672,47 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { |
673 | 672 | // and ban them. Type variables instantiated inside binders aren't |
674 | 673 | // well-supported at the moment, so this doesn't work. |
675 | 674 | // In the future, this should be fixed and this error should be removed. |
676 | | - let def = self.map.defs.get(&lifetime.hir_id).cloned(); |
677 | | - let Some(ResolvedArg::LateBound(_, _, def_id)) = def else { continue }; |
678 | | - let Some(def_id) = def_id.as_local() else { continue }; |
679 | | - let hir_id = self.tcx.local_def_id_to_hir_id(def_id); |
680 | | - // Ensure that the parent of the def is an item, not HRTB |
681 | | - let parent_id = self.tcx.parent_hir_id(hir_id); |
682 | | - if !parent_id.is_owner() { |
683 | | - struct_span_code_err!( |
684 | | - self.tcx.dcx(), |
685 | | - lifetime.ident.span, |
686 | | - E0657, |
687 | | - "`impl Trait` can only capture lifetimes bound at the fn or impl level" |
688 | | - ) |
689 | | - .emit(); |
690 | | - self.uninsert_lifetime_on_error(lifetime, def.unwrap()); |
691 | | - } |
692 | | - if let hir::Node::Item(hir::Item { |
693 | | - kind: hir::ItemKind::OpaqueTy { .. }, .. |
694 | | - }) = self.tcx.hir_node(parent_id) |
| 675 | + let def = self.map.defs.get(&lifetime.hir_id).copied(); |
| 676 | + let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue }; |
| 677 | + let Some(lifetime_def_id) = lifetime_def_id.as_local() else { continue }; |
| 678 | + let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id); |
| 679 | + |
| 680 | + let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id)) |
695 | 681 | { |
696 | | - self.tcx.dcx().struct_span_err( |
697 | | - lifetime.ident.span, |
698 | | - "higher kinded lifetime bounds on nested opaque types are not supported yet", |
699 | | - ) |
700 | | - .with_span_note(self.tcx.def_span(def_id), "lifetime declared here") |
701 | | - .emit(); |
702 | | - self.uninsert_lifetime_on_error(lifetime, def.unwrap()); |
703 | | - } |
| 682 | + // Opaques do not declare their own lifetimes, so if a lifetime comes from an opaque |
| 683 | + // it must be a reified late-bound lifetime from a trait goal. |
| 684 | + hir::Node::Item(hir::Item { |
| 685 | + kind: hir::ItemKind::OpaqueTy { .. }, .. |
| 686 | + }) => "higher-ranked lifetime from outer `impl Trait`", |
| 687 | + // Other items are fine. |
| 688 | + hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => { |
| 689 | + continue; |
| 690 | + } |
| 691 | + hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(_), .. }) => { |
| 692 | + "higher-ranked lifetime from function pointer" |
| 693 | + } |
| 694 | + hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => { |
| 695 | + "higher-ranked lifetime from `dyn` type" |
| 696 | + } |
| 697 | + _ => "higher-ranked lifetime", |
| 698 | + }; |
| 699 | + |
| 700 | + let (span, label) = if lifetime.ident.span == self.tcx.def_span(lifetime_def_id) |
| 701 | + { |
| 702 | + let opaque_span = self.tcx.def_span(item_id.owner_id); |
| 703 | + (opaque_span, Some(opaque_span)) |
| 704 | + } else { |
| 705 | + (lifetime.ident.span, None) |
| 706 | + }; |
| 707 | + |
| 708 | + // Ensure that the parent of the def is an item, not HRTB |
| 709 | + self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime { |
| 710 | + span, |
| 711 | + label, |
| 712 | + decl_span: self.tcx.def_span(lifetime_def_id), |
| 713 | + bad_place, |
| 714 | + }); |
| 715 | + self.uninsert_lifetime_on_error(lifetime, def.unwrap()); |
704 | 716 | } |
705 | 717 | } |
706 | 718 | _ => intravisit::walk_ty(self, ty), |
|
0 commit comments