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, ErrorGuaranteed};
12 use rustc_hir::intravisit::Visitor;
13 use rustc_middle::ty::TypeVisitor;
14 use rustc_span::MultiSpan;
16 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
17 pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorGuaranteed> {
18 let error = self.error.as_ref()?;
19 debug!("try_report_mismatched_static_lifetime {:?}", error);
21 let RegionResolutionError::ConcreteFailure(origin, sub, sup) = error.clone() else {
27 let SubregionOrigin::Subtype(box TypeTrace { ref cause, .. }) = origin else {
30 // If we added a "points at argument expression" obligation, we remove it here, we care
31 // about the original obligation only.
32 let code = match cause.code() {
33 ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => &*parent_code,
36 let ObligationCauseCode::MatchImpl(parent, impl_def_id) = code else {
39 let ObligationCauseCode::BindingObligation(_def_id, binding_span) = *parent.code() else {
42 let mut err = self.tcx().sess.struct_span_err(cause.span, "incompatible lifetime on type");
43 // FIXME: we should point at the lifetime
44 let mut multi_span: MultiSpan = vec![binding_span].into();
46 .push_span_label(binding_span, "introduces a `'static` lifetime requirement".into());
47 err.span_note(multi_span, "because this has an unmet lifetime requirement");
48 note_and_explain_region(self.tcx(), &mut err, "", sup, "...", Some(binding_span));
49 if let Some(impl_node) = self.tcx().hir().get_if_local(*impl_def_id) {
50 // If an impl is local, then maybe this isn't what they want. Try to
51 // be as helpful as possible with implicit lifetimes.
53 // First, let's get the hir self type of the impl
54 let hir::Node::Item(hir::Item {
55 kind: hir::ItemKind::Impl(hir::Impl { self_ty: impl_self_ty, .. }),
58 bug!("Node not an impl.");
61 // Next, let's figure out the set of trait objects with implicit static bounds
62 let ty = self.tcx().type_of(*impl_def_id);
63 let mut v = super::static_impl_trait::TraitObjectVisitor(FxHashSet::default());
65 let mut traits = vec![];
66 for matching_def_id in v.0 {
68 super::static_impl_trait::HirTraitObjectVisitor(&mut traits, matching_def_id);
69 hir_v.visit_ty(&impl_self_ty);
72 if traits.is_empty() {
73 // If there are no trait object traits to point at, either because
74 // there aren't trait objects or because none are implicit, then just
75 // write a single note on the impl itself.
77 let impl_span = self.tcx().def_span(*impl_def_id);
78 err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
80 // Otherwise, point at all implicit static lifetimes
82 err.note("...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
84 err.span_note(*span, "this has an implicit `'static` lifetime requirement");
85 // It would be nice to put this immediately under the above note, but they get
87 err.span_suggestion_verbose(
89 "consider relaxing the implicit `'static` requirement",
91 Applicability::MaybeIncorrect,
96 // Otherwise just point out the impl.
98 let impl_span = self.tcx().def_span(*impl_def_id);
99 err.span_note(impl_span, "...does not necessarily outlive the static lifetime introduced by the compatible `impl`");
101 let reported = err.emit();