rustc_trait_selection/error_reporting/infer/nice_region_error/
different_lifetimes.rs1use rustc_errors::{Diag, ErrorGuaranteed, Subdiagnostic};
5use rustc_hir::Ty;
6use rustc_hir::def_id::LocalDefId;
7use rustc_middle::ty::{Region, TyCtxt};
8use tracing::debug;
9
10use crate::error_reporting::infer::nice_region_error::NiceRegionError;
11use crate::error_reporting::infer::nice_region_error::find_anon_type::find_anon_type;
12use crate::error_reporting::infer::nice_region_error::util::AnonymousParamInfo;
13use crate::errors::{AddLifetimeParamsSuggestion, LifetimeMismatch, LifetimeMismatchLabels};
14use crate::infer::{RegionResolutionError, SubregionOrigin};
15
16impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
17 pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorGuaranteed> {
54 let (span, sub, sup) = self.regions()?;
55
56 if let Some(RegionResolutionError::ConcreteFailure(
57 SubregionOrigin::ReferenceOutlivesReferent(..),
58 ..,
59 )) = self.error
60 {
61 return None;
63 }
64
65 let sup_info = self.tcx().is_suitable_region(self.generic_param_scope, sup)?;
67
68 let sub_info = self.tcx().is_suitable_region(self.generic_param_scope, sub)?;
69
70 let ty_sup = find_anon_type(self.tcx(), self.generic_param_scope, sup)?;
71
72 let ty_sub = find_anon_type(self.tcx(), self.generic_param_scope, sub)?;
73
74 debug!("try_report_anon_anon_conflict: found_param1={:?} sup={:?}", ty_sub, sup);
75 debug!("try_report_anon_anon_conflict: found_param2={:?} sub={:?}", ty_sup, sub);
76
77 let (ty_sup, ty_fndecl_sup) = ty_sup;
78 let (ty_sub, ty_fndecl_sub) = ty_sub;
79
80 let AnonymousParamInfo { param: anon_param_sup, .. } =
81 self.find_param_with_region(sup, sup)?;
82 let AnonymousParamInfo { param: anon_param_sub, .. } =
83 self.find_param_with_region(sub, sub)?;
84
85 let sup_is_ret_type =
86 self.is_return_type_anon(sup_info.scope, sup_info.region_def_id, ty_fndecl_sup);
87 let sub_is_ret_type =
88 self.is_return_type_anon(sub_info.scope, sub_info.region_def_id, ty_fndecl_sub);
89
90 debug!(
91 "try_report_anon_anon_conflict: sub_is_ret_type={:?} sup_is_ret_type={:?}",
92 sub_is_ret_type, sup_is_ret_type
93 );
94
95 let labels = match (sup_is_ret_type, sub_is_ret_type) {
96 (ret_capture @ Some(ret_span), _) | (_, ret_capture @ Some(ret_span)) => {
97 let param_span =
98 if sup_is_ret_type == ret_capture { ty_sub.span } else { ty_sup.span };
99 LifetimeMismatchLabels::InRet {
100 param_span,
101 ret_span,
102 span,
103 label_var1: anon_param_sup.pat.simple_ident(),
104 }
105 }
106
107 (None, None) => LifetimeMismatchLabels::Normal {
108 hir_equal: ty_sup.hir_id == ty_sub.hir_id,
109 ty_sup: ty_sup.span,
110 ty_sub: ty_sub.span,
111 span,
112 sup: anon_param_sup.pat.simple_ident(),
113 sub: anon_param_sub.pat.simple_ident(),
114 },
115 };
116
117 let suggestion = AddLifetimeParamsSuggestion {
118 tcx: self.tcx(),
119 sub,
120 ty_sup,
121 ty_sub,
122 add_note: true,
123 generic_param_scope: self.generic_param_scope,
124 };
125 let err = LifetimeMismatch { span, labels, suggestion };
126 let reported = self.tcx().dcx().emit_err(err);
127 Some(reported)
128 }
129}
130
131pub fn suggest_adding_lifetime_params<'tcx>(
134 tcx: TyCtxt<'tcx>,
135 err: &mut Diag<'_>,
136 generic_param_scope: LocalDefId,
137 sub: Region<'tcx>,
138 ty_sup: &'tcx Ty<'_>,
139 ty_sub: &'tcx Ty<'_>,
140) {
141 let suggestion = AddLifetimeParamsSuggestion {
142 tcx,
143 sub,
144 ty_sup,
145 ty_sub,
146 add_note: false,
147 generic_param_scope,
148 };
149 suggestion.add_to_diag(err);
150}