1 //! Error Reporting for when the lifetime for a type doesn't match the `impl` selected for a predicate
4 use crate::errors
::{note_and_explain, IntroducesStaticBecauseUnmetLifetimeReq}
;
6 DoesNotOutliveStaticFromImpl
, ImplicitStaticLifetimeSubdiag
, MismatchedStaticLifetime
,
8 use crate::infer
::error_reporting
::nice_region_error
::NiceRegionError
;
9 use crate::infer
::lexical_region_resolve
::RegionResolutionError
;
10 use crate::infer
::{SubregionOrigin, TypeTrace}
;
11 use crate::traits
::ObligationCauseCode
;
12 use rustc_data_structures
::fx
::FxIndexSet
;
13 use rustc_errors
::{ErrorGuaranteed, MultiSpan}
;
15 use rustc_hir
::intravisit
::Visitor
;
16 use rustc_middle
::ty
::TypeVisitor
;
18 impl<'a
, 'tcx
> NiceRegionError
<'a
, 'tcx
> {
19 pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option
<ErrorGuaranteed
> {
20 let error
= self.error
.as_ref()?
;
21 debug
!("try_report_mismatched_static_lifetime {:?}", error
);
23 let RegionResolutionError
::ConcreteFailure(origin
, sub
, sup
) = error
.clone() else {
29 let SubregionOrigin
::Subtype(box TypeTrace { ref cause, .. }
) = origin
else {
32 // If we added a "points at argument expression" obligation, we remove it here, we care
33 // about the original obligation only.
34 let code
= match cause
.code() {
35 ObligationCauseCode
::FunctionArgumentObligation { parent_code, .. }
=> &*parent_code
,
38 let ObligationCauseCode
::MatchImpl(parent
, impl_def_id
) = code
else {
41 let (ObligationCauseCode
::BindingObligation(_
, binding_span
) | ObligationCauseCode
::ExprBindingObligation(_
, binding_span
, ..))
42 = *parent
.code() else {
46 // FIXME: we should point at the lifetime
47 let multi_span
: MultiSpan
= vec
![binding_span
].into();
48 let multispan_subdiag
= IntroducesStaticBecauseUnmetLifetimeReq
{
49 unmet_requirements
: multi_span
,
53 let expl
= note_and_explain
::RegionExplanation
::new(
57 note_and_explain
::PrefixKind
::Empty
,
58 note_and_explain
::SuffixKind
::Continues
,
60 let mut impl_span
= None
;
61 let mut implicit_static_lifetimes
= Vec
::new();
62 if let Some(impl_node
) = self.tcx().hir().get_if_local(*impl_def_id
) {
63 // If an impl is local, then maybe this isn't what they want. Try to
64 // be as helpful as possible with implicit lifetimes.
66 // First, let's get the hir self type of the impl
67 let hir
::Node
::Item(hir
::Item
{
68 kind
: hir
::ItemKind
::Impl(hir
::Impl { self_ty: impl_self_ty, .. }
),
71 bug
!("Node not an impl.");
74 // Next, let's figure out the set of trait objects with implicit static bounds
75 let ty
= self.tcx().type_of(*impl_def_id
);
76 let mut v
= super::static_impl_trait
::TraitObjectVisitor(FxIndexSet
::default());
78 let mut traits
= vec
![];
79 for matching_def_id
in v
.0 {
81 super::static_impl_trait
::HirTraitObjectVisitor(&mut traits
, matching_def_id
);
82 hir_v
.visit_ty(&impl_self_ty
);
85 if traits
.is_empty() {
86 // If there are no trait object traits to point at, either because
87 // there aren't trait objects or because none are implicit, then just
88 // write a single note on the impl itself.
90 impl_span
= Some(self.tcx().def_span(*impl_def_id
));
92 // Otherwise, point at all implicit static lifetimes
95 implicit_static_lifetimes
96 .push(ImplicitStaticLifetimeSubdiag
::Note { span: *span }
);
97 // It would be nice to put this immediately under the above note, but they get
99 implicit_static_lifetimes
100 .push(ImplicitStaticLifetimeSubdiag
::Sugg { span: span.shrink_to_hi() }
);
104 // Otherwise just point out the impl.
106 impl_span
= Some(self.tcx().def_span(*impl_def_id
));
108 let err
= MismatchedStaticLifetime
{
109 cause_span
: cause
.span
,
110 unmet_lifetime_reqs
: multispan_subdiag
,
112 does_not_outlive_static_from_impl
: impl_span
113 .map(|span
| DoesNotOutliveStaticFromImpl
::Spanned { span }
)
114 .unwrap_or(DoesNotOutliveStaticFromImpl
::Unspanned
),
115 implicit_static_lifetimes
,
117 let reported
= self.tcx().sess
.emit_err(err
);