]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / compiler / rustc_infer / src / infer / error_reporting / nice_region_error / mismatched_static_lifetime.rs
1 //! Error Reporting for when the lifetime for a type doesn't match the `impl` selected for a predicate
2 //! to hold.
3
4 use crate::errors::{note_and_explain, IntroducesStaticBecauseUnmetLifetimeReq};
5 use crate::errors::{
6 DoesNotOutliveStaticFromImpl, ImplicitStaticLifetimeSubdiag, MismatchedStaticLifetime,
7 };
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};
14 use rustc_hir as hir;
15 use rustc_hir::intravisit::Visitor;
16 use rustc_middle::ty::TypeVisitor;
17
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);
22
23 let RegionResolutionError::ConcreteFailure(origin, sub, sup) = error.clone() else {
24 return None;
25 };
26 if !sub.is_static() {
27 return None;
28 }
29 let SubregionOrigin::Subtype(box TypeTrace { ref cause, .. }) = origin else {
30 return None;
31 };
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,
36 code => code,
37 };
38 let ObligationCauseCode::MatchImpl(parent, impl_def_id) = code else {
39 return None;
40 };
41 let (ObligationCauseCode::BindingObligation(_, binding_span) | ObligationCauseCode::ExprBindingObligation(_, binding_span, ..))
42 = *parent.code() else {
43 return None;
44 };
45
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,
50 binding_span,
51 };
52
53 let expl = note_and_explain::RegionExplanation::new(
54 self.tcx(),
55 sup,
56 Some(binding_span),
57 note_and_explain::PrefixKind::Empty,
58 note_and_explain::SuffixKind::Continues,
59 );
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.
65
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, .. }),
69 ..
70 }) = impl_node else {
71 bug!("Node not an impl.");
72 };
73
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());
77 v.visit_ty(ty);
78 let mut traits = vec![];
79 for matching_def_id in v.0 {
80 let mut hir_v =
81 super::static_impl_trait::HirTraitObjectVisitor(&mut traits, matching_def_id);
82 hir_v.visit_ty(&impl_self_ty);
83 }
84
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.
89
90 impl_span = Some(self.tcx().def_span(*impl_def_id));
91 } else {
92 // Otherwise, point at all implicit static lifetimes
93
94 for span in &traits {
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
98 // pushed to the end.
99 implicit_static_lifetimes
100 .push(ImplicitStaticLifetimeSubdiag::Sugg { span: span.shrink_to_hi() });
101 }
102 }
103 } else {
104 // Otherwise just point out the impl.
105
106 impl_span = Some(self.tcx().def_span(*impl_def_id));
107 }
108 let err = MismatchedStaticLifetime {
109 cause_span: cause.span,
110 unmet_lifetime_reqs: multispan_subdiag,
111 expl,
112 does_not_outlive_static_from_impl: impl_span
113 .map(|span| DoesNotOutliveStaticFromImpl::Spanned { span })
114 .unwrap_or(DoesNotOutliveStaticFromImpl::Unspanned),
115 implicit_static_lifetimes,
116 };
117 let reported = self.tcx().sess.emit_err(err);
118 Some(reported)
119 }
120 }