1 //! Error Reporting for when the lifetime for a type doesn't match the `impl` selected for a predicate
4 use crate::infer
::error_reporting
::nice_region_error
::NiceRegionError
;
5 use crate::infer
::error_reporting
::note_and_explain_region
;
6 use crate::infer
::lexical_region_resolve
::RegionResolutionError
;
7 use crate::infer
::{SubregionOrigin, TypeTrace}
;
8 use crate::traits
::ObligationCauseCode
;
9 use rustc_data_structures
::stable_set
::FxHashSet
;
10 use rustc_errors
::{Applicability, ErrorReported}
;
12 use rustc_hir
::intravisit
::Visitor
;
13 use rustc_middle
::ty
::{self, TypeVisitor}
;
14 use rustc_span
::MultiSpan
;
16 impl<'a
, 'tcx
> NiceRegionError
<'a
, 'tcx
> {
17 pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option
<ErrorReported
> {
18 let error
= self.error
.as_ref()?
;
19 debug
!("try_report_mismatched_static_lifetime {:?}", error
);
21 let (origin
, sub
, sup
) = match error
.clone() {
22 RegionResolutionError
::ConcreteFailure(origin
, sub
, sup
) => (origin
, sub
, sup
),
25 if *sub
!= ty
::RegionKind
::ReStatic
{
28 let cause
= match origin
{
29 SubregionOrigin
::Subtype(box TypeTrace { ref cause, .. }
) => cause
,
32 let (parent
, impl_def_id
) = match &cause
.code
{
33 ObligationCauseCode
::MatchImpl(parent
, impl_def_id
) => (parent
, impl_def_id
),
36 let binding_span
= match **parent
{
37 ObligationCauseCode
::BindingObligation(_def_id
, binding_span
) => binding_span
,
40 let mut err
= self.tcx().sess
.struct_span_err(cause
.span
, "incompatible lifetime on type");
41 // FIXME: we should point at the lifetime
42 let mut multi_span
: MultiSpan
= vec
![binding_span
].into();
44 .push_span_label(binding_span
, "introduces a `'static` lifetime requirement".into());
45 err
.span_note(multi_span
, "because this has an unmet lifetime requirement");
46 note_and_explain_region(self.tcx(), &mut err
, "", sup
, "...");
47 if let Some(impl_node
) = self.tcx().hir().get_if_local(*impl_def_id
) {
48 // If an impl is local, then maybe this isn't what they want. Try to
49 // be as helpful as possible with implicit lifetimes.
51 // First, let's get the hir self type of the impl
52 let impl_self_ty
= match impl_node
{
53 hir
::Node
::Item(hir
::Item
{
54 kind
: hir
::ItemKind
::Impl(hir
::Impl { self_ty, .. }
),
57 _
=> bug
!("Node not an impl."),
60 // Next, let's figure out the set of trait objects with implict static bounds
61 let ty
= self.tcx().type_of(*impl_def_id
);
62 let mut v
= super::static_impl_trait
::TraitObjectVisitor(FxHashSet
::default());
64 let mut traits
= vec
![];
65 for matching_def_id
in v
.0 {
67 super::static_impl_trait
::HirTraitObjectVisitor(&mut traits
, matching_def_id
);
68 hir_v
.visit_ty(&impl_self_ty
);
71 if traits
.is_empty() {
72 // If there are no trait object traits to point at, either because
73 // there aren't trait objects or because none are implicit, then just
74 // write a single note on the impl itself.
76 let impl_span
= self.tcx().def_span(*impl_def_id
);
77 err
.span_note(impl_span
, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
79 // Otherwise, point at all implicit static lifetimes
81 err
.note("...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
83 err
.span_note(*span
, "this has an implicit `'static` lifetime requirement");
84 // It would be nice to put this immediately under the above note, but they get
86 err
.span_suggestion_verbose(
88 "consider relaxing the implicit `'static` requirement",
90 Applicability
::MaybeIncorrect
,
95 // Otherwise just point out the impl.
97 let impl_span
= self.tcx().def_span(*impl_def_id
);
98 err
.span_note(impl_span
, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`");