]>
Commit | Line | Data |
---|---|---|
9ffffee4 FG |
1 | use crate::errors::{ |
2 | note_and_explain, FullfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent, | |
3 | RefLongerThanData, RegionOriginNote, WhereClauseSuggestions, | |
4 | }; | |
5 | use crate::fluent_generated as fluent; | |
2b03887a FG |
6 | use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt}; |
7 | use crate::infer::{self, SubregionOrigin}; | |
f2b60f7d | 8 | use rustc_errors::{ |
9ffffee4 | 9 | AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, |
f2b60f7d | 10 | }; |
9c376795 | 11 | use rustc_hir::def_id::{DefId, LocalDefId}; |
5869c6ff | 12 | use rustc_middle::traits::ObligationCauseCode; |
ba9703b0 | 13 | use rustc_middle::ty::error::TypeError; |
9c376795 FG |
14 | use rustc_middle::ty::{self, IsSuggestable, Region}; |
15 | use rustc_span::symbol::kw; | |
60c5eb7d | 16 | |
f2b60f7d FG |
17 | use super::ObligationCauseAsDiagArg; |
18 | ||
2b03887a | 19 | impl<'tcx> TypeErrCtxt<'_, 'tcx> { |
5e7ed085 | 20 | pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) { |
8bb4bdeb | 21 | match *origin { |
f2b60f7d FG |
22 | infer::Subtype(ref trace) => RegionOriginNote::WithRequirement { |
23 | span: trace.cause.span, | |
24 | requirement: ObligationCauseAsDiagArg(trace.cause.clone()), | |
487cf647 | 25 | expected_found: self.values_str(trace.values).map(|(e, f, _, _)| (e, f)), |
8bb4bdeb | 26 | } |
f2b60f7d | 27 | .add_to_diagnostic(err), |
2b03887a FG |
28 | infer::Reborrow(span) => { |
29 | RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err) | |
30 | } | |
8bb4bdeb | 31 | infer::RelateObjectBound(span) => { |
2b03887a | 32 | RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound } |
f2b60f7d | 33 | .add_to_diagnostic(err); |
8bb4bdeb | 34 | } |
8bb4bdeb | 35 | infer::ReferenceOutlivesReferent(ty, span) => { |
f2b60f7d | 36 | RegionOriginNote::WithName { |
dfeec247 | 37 | span, |
2b03887a | 38 | msg: fluent::infer_reference_outlives_referent, |
f2b60f7d FG |
39 | name: &self.ty_to_string(ty), |
40 | continues: false, | |
41 | } | |
42 | .add_to_diagnostic(err); | |
8bb4bdeb | 43 | } |
f2b60f7d FG |
44 | infer::RelateParamBound(span, ty, opt_span) => { |
45 | RegionOriginNote::WithName { | |
dfeec247 | 46 | span, |
2b03887a | 47 | msg: fluent::infer_relate_param_bound, |
f2b60f7d FG |
48 | name: &self.ty_to_string(ty), |
49 | continues: opt_span.is_some(), | |
50 | } | |
51 | .add_to_diagnostic(err); | |
94222f64 | 52 | if let Some(span) = opt_span { |
2b03887a | 53 | RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 } |
f2b60f7d | 54 | .add_to_diagnostic(err); |
94222f64 | 55 | } |
8bb4bdeb XL |
56 | } |
57 | infer::RelateRegionParamBound(span) => { | |
2b03887a | 58 | RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound } |
f2b60f7d | 59 | .add_to_diagnostic(err); |
8bb4bdeb | 60 | } |
064997fb | 61 | infer::CompareImplItemObligation { span, .. } => { |
2b03887a | 62 | RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation } |
f2b60f7d | 63 | .add_to_diagnostic(err); |
c295e0f8 | 64 | } |
5099ac24 FG |
65 | infer::CheckAssociatedTypeBounds { ref parent, .. } => { |
66 | self.note_region_origin(err, &parent); | |
67 | } | |
f2b60f7d FG |
68 | infer::AscribeUserTypeProvePredicate(span) => { |
69 | RegionOriginNote::Plain { | |
70 | span, | |
2b03887a | 71 | msg: fluent::infer_ascribe_user_type_prove_predicate, |
f2b60f7d FG |
72 | } |
73 | .add_to_diagnostic(err); | |
74 | } | |
8bb4bdeb XL |
75 | } |
76 | } | |
77 | ||
dfeec247 XL |
78 | pub(super) fn report_concrete_failure( |
79 | &self, | |
dfeec247 XL |
80 | origin: SubregionOrigin<'tcx>, |
81 | sub: Region<'tcx>, | |
82 | sup: Region<'tcx>, | |
5e7ed085 | 83 | ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { |
9ffffee4 | 84 | let mut err = match origin { |
e1599b0c | 85 | infer::Subtype(box trace) => { |
8bb4bdeb | 86 | let terr = TypeError::RegionsDoesNotOutlive(sup, sub); |
f2b60f7d | 87 | let mut err = self.report_and_explain_type_error(trace, terr); |
5099ac24 | 88 | match (*sub, *sup) { |
5869c6ff XL |
89 | (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {} |
90 | (ty::RePlaceholder(_), _) => { | |
91 | note_and_explain_region( | |
92 | self.tcx, | |
93 | &mut err, | |
94 | "", | |
95 | sup, | |
96 | " doesn't meet the lifetime requirements", | |
94222f64 | 97 | None, |
5869c6ff XL |
98 | ); |
99 | } | |
100 | (_, ty::RePlaceholder(_)) => { | |
101 | note_and_explain_region( | |
102 | self.tcx, | |
103 | &mut err, | |
104 | "the required lifetime does not necessarily outlive ", | |
105 | sub, | |
106 | "", | |
94222f64 | 107 | None, |
5869c6ff XL |
108 | ); |
109 | } | |
110 | _ => { | |
94222f64 | 111 | note_and_explain_region(self.tcx, &mut err, "", sup, "...", None); |
5869c6ff XL |
112 | note_and_explain_region( |
113 | self.tcx, | |
114 | &mut err, | |
115 | "...does not necessarily outlive ", | |
116 | sub, | |
117 | "", | |
94222f64 | 118 | None, |
5869c6ff XL |
119 | ); |
120 | } | |
121 | } | |
ea8adc8c | 122 | err |
8bb4bdeb XL |
123 | } |
124 | infer::Reborrow(span) => { | |
9ffffee4 | 125 | let reference_valid = note_and_explain::RegionExplanation::new( |
dfeec247 | 126 | self.tcx, |
dfeec247 | 127 | sub, |
94222f64 | 128 | None, |
9ffffee4 FG |
129 | note_and_explain::PrefixKind::RefValidFor, |
130 | note_and_explain::SuffixKind::Continues, | |
dfeec247 | 131 | ); |
9ffffee4 | 132 | let content_valid = note_and_explain::RegionExplanation::new( |
dfeec247 | 133 | self.tcx, |
dfeec247 | 134 | sup, |
94222f64 | 135 | None, |
9ffffee4 FG |
136 | note_and_explain::PrefixKind::ContentValidFor, |
137 | note_and_explain::SuffixKind::Empty, | |
dfeec247 | 138 | ); |
9ffffee4 FG |
139 | OutlivesContent { |
140 | span, | |
141 | notes: reference_valid.into_iter().chain(content_valid).collect(), | |
142 | } | |
143 | .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic) | |
8bb4bdeb | 144 | } |
8bb4bdeb | 145 | infer::RelateObjectBound(span) => { |
9ffffee4 | 146 | let object_valid = note_and_explain::RegionExplanation::new( |
94222f64 | 147 | self.tcx, |
94222f64 | 148 | sub, |
94222f64 | 149 | None, |
9ffffee4 FG |
150 | note_and_explain::PrefixKind::TypeObjValidFor, |
151 | note_and_explain::SuffixKind::Empty, | |
94222f64 | 152 | ); |
9ffffee4 | 153 | let pointer_valid = note_and_explain::RegionExplanation::new( |
dfeec247 | 154 | self.tcx, |
dfeec247 | 155 | sup, |
94222f64 | 156 | None, |
9ffffee4 FG |
157 | note_and_explain::PrefixKind::SourcePointerValidFor, |
158 | note_and_explain::SuffixKind::Empty, | |
dfeec247 | 159 | ); |
9ffffee4 FG |
160 | OutlivesBound { |
161 | span, | |
162 | notes: object_valid.into_iter().chain(pointer_valid).collect(), | |
163 | } | |
164 | .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic) | |
8bb4bdeb | 165 | } |
94222f64 | 166 | infer::RelateParamBound(span, ty, opt_span) => { |
9ffffee4 FG |
167 | let prefix = match *sub { |
168 | ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy, | |
169 | _ => note_and_explain::PrefixKind::TypeOutlive, | |
170 | }; | |
171 | let suffix = if opt_span.is_some() { | |
172 | note_and_explain::SuffixKind::ReqByBinding | |
173 | } else { | |
174 | note_and_explain::SuffixKind::Empty | |
175 | }; | |
176 | let note = note_and_explain::RegionExplanation::new( | |
177 | self.tcx, sub, opt_span, prefix, suffix, | |
dfeec247 | 178 | ); |
9ffffee4 FG |
179 | FullfillReqLifetime { span, ty: self.resolve_vars_if_possible(ty), note } |
180 | .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic) | |
8bb4bdeb XL |
181 | } |
182 | infer::RelateRegionParamBound(span) => { | |
9ffffee4 | 183 | let param_instantiated = note_and_explain::RegionExplanation::new( |
dfeec247 | 184 | self.tcx, |
dfeec247 | 185 | sup, |
94222f64 | 186 | None, |
9ffffee4 FG |
187 | note_and_explain::PrefixKind::LfParamInstantiatedWith, |
188 | note_and_explain::SuffixKind::Empty, | |
dfeec247 | 189 | ); |
9ffffee4 | 190 | let param_must_outlive = note_and_explain::RegionExplanation::new( |
dfeec247 | 191 | self.tcx, |
dfeec247 | 192 | sub, |
94222f64 | 193 | None, |
9ffffee4 FG |
194 | note_and_explain::PrefixKind::LfParamMustOutlive, |
195 | note_and_explain::SuffixKind::Empty, | |
dfeec247 | 196 | ); |
9ffffee4 FG |
197 | LfBoundNotSatisfied { |
198 | span, | |
199 | notes: param_instantiated.into_iter().chain(param_must_outlive).collect(), | |
200 | } | |
201 | .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic) | |
8bb4bdeb | 202 | } |
8bb4bdeb | 203 | infer::ReferenceOutlivesReferent(ty, span) => { |
9ffffee4 | 204 | let pointer_valid = note_and_explain::RegionExplanation::new( |
94222f64 | 205 | self.tcx, |
94222f64 | 206 | sub, |
94222f64 | 207 | None, |
9ffffee4 FG |
208 | note_and_explain::PrefixKind::PointerValidFor, |
209 | note_and_explain::SuffixKind::Empty, | |
94222f64 | 210 | ); |
9ffffee4 | 211 | let data_valid = note_and_explain::RegionExplanation::new( |
dfeec247 | 212 | self.tcx, |
dfeec247 | 213 | sup, |
94222f64 | 214 | None, |
9ffffee4 FG |
215 | note_and_explain::PrefixKind::DataValidFor, |
216 | note_and_explain::SuffixKind::Empty, | |
dfeec247 | 217 | ); |
9ffffee4 FG |
218 | RefLongerThanData { |
219 | span, | |
220 | ty: self.resolve_vars_if_possible(ty), | |
221 | notes: pointer_valid.into_iter().chain(data_valid).collect(), | |
222 | } | |
223 | .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic) | |
8bb4bdeb | 224 | } |
9c376795 FG |
225 | infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => { |
226 | let mut err = self.report_extra_impl_obligation( | |
3c0e092e XL |
227 | span, |
228 | impl_item_def_id, | |
229 | trait_item_def_id, | |
230 | &format!("`{}: {}`", sup, sub), | |
9c376795 FG |
231 | ); |
232 | // We should only suggest rewriting the `where` clause if the predicate is within that `where` clause | |
233 | if let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) | |
234 | && generics.where_clause_span.contains(span) | |
235 | { | |
236 | self.suggest_copy_trait_method_bounds( | |
237 | trait_item_def_id, | |
238 | impl_item_def_id, | |
239 | &mut err, | |
240 | ); | |
241 | } | |
242 | err | |
243 | } | |
5099ac24 FG |
244 | infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => { |
245 | let mut err = self.report_concrete_failure(*parent, sub, sup); | |
5099ac24 | 246 | let trait_item_span = self.tcx.def_span(trait_item_def_id); |
5e7ed085 | 247 | let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); |
5099ac24 FG |
248 | err.span_label( |
249 | trait_item_span, | |
250 | format!("definition of `{}` from trait", item_name), | |
251 | ); | |
9c376795 FG |
252 | self.suggest_copy_trait_method_bounds( |
253 | trait_item_def_id, | |
254 | impl_item_def_id, | |
255 | &mut err, | |
256 | ); | |
5099ac24 FG |
257 | err |
258 | } | |
f2b60f7d | 259 | infer::AscribeUserTypeProvePredicate(span) => { |
9ffffee4 | 260 | let instantiated = note_and_explain::RegionExplanation::new( |
f2b60f7d | 261 | self.tcx, |
f2b60f7d | 262 | sup, |
f2b60f7d | 263 | None, |
9ffffee4 FG |
264 | note_and_explain::PrefixKind::LfInstantiatedWith, |
265 | note_and_explain::SuffixKind::Empty, | |
f2b60f7d | 266 | ); |
9ffffee4 | 267 | let must_outlive = note_and_explain::RegionExplanation::new( |
f2b60f7d | 268 | self.tcx, |
f2b60f7d | 269 | sub, |
f2b60f7d | 270 | None, |
9ffffee4 FG |
271 | note_and_explain::PrefixKind::LfMustOutlive, |
272 | note_and_explain::SuffixKind::Empty, | |
f2b60f7d | 273 | ); |
9ffffee4 FG |
274 | LfBoundNotSatisfied { |
275 | span, | |
276 | notes: instantiated.into_iter().chain(must_outlive).collect(), | |
277 | } | |
278 | .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic) | |
f2b60f7d | 279 | } |
9ffffee4 FG |
280 | }; |
281 | if sub.is_error() || sup.is_error() { | |
282 | err.delay_as_bug(); | |
8bb4bdeb | 283 | } |
9ffffee4 | 284 | err |
8bb4bdeb | 285 | } |
0731742a | 286 | |
9c376795 FG |
287 | pub fn suggest_copy_trait_method_bounds( |
288 | &self, | |
289 | trait_item_def_id: DefId, | |
290 | impl_item_def_id: LocalDefId, | |
291 | err: &mut Diagnostic, | |
292 | ) { | |
293 | // FIXME(compiler-errors): Right now this is only being used for region | |
294 | // predicate mismatches. Ideally, we'd use it for *all* predicate mismatches, | |
295 | // but right now it's not really very smart when it comes to implicit `Sized` | |
296 | // predicates and bounds on the trait itself. | |
297 | ||
298 | let Some(impl_def_id) = | |
299 | self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx) else { return; }; | |
300 | let Some(trait_ref) = self | |
301 | .tcx | |
302 | .impl_trait_ref(impl_def_id) | |
303 | else { return; }; | |
304 | let trait_substs = trait_ref | |
305 | .subst_identity() | |
306 | // Replace the explicit self type with `Self` for better suggestion rendering | |
307 | .with_self_ty(self.tcx, self.tcx.mk_ty_param(0, kw::SelfUpper)) | |
308 | .substs; | |
309 | let trait_item_substs = | |
310 | ty::InternalSubsts::identity_for_item(self.tcx, impl_item_def_id.to_def_id()) | |
311 | .rebase_onto(self.tcx, impl_def_id, trait_substs); | |
312 | ||
313 | let Ok(trait_predicates) = self | |
314 | .tcx | |
315 | .explicit_predicates_of(trait_item_def_id) | |
316 | .instantiate_own(self.tcx, trait_item_substs) | |
317 | .map(|(pred, _)| { | |
318 | if pred.is_suggestable(self.tcx, false) { | |
319 | Ok(pred.to_string()) | |
320 | } else { | |
321 | Err(()) | |
322 | } | |
323 | }) | |
324 | .collect::<Result<Vec<_>, ()>>() else { return; }; | |
325 | ||
326 | let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else { return; }; | |
327 | ||
9ffffee4 FG |
328 | let suggestion = if trait_predicates.is_empty() { |
329 | WhereClauseSuggestions::Remove { span: generics.where_clause_span } | |
9c376795 FG |
330 | } else { |
331 | let space = if generics.where_clause_span.is_empty() { " " } else { "" }; | |
9ffffee4 FG |
332 | WhereClauseSuggestions::CopyPredicates { |
333 | span: generics.where_clause_span, | |
334 | space, | |
335 | trait_predicates: trait_predicates.join(", "), | |
336 | } | |
337 | }; | |
338 | err.subdiagnostic(suggestion); | |
9c376795 FG |
339 | } |
340 | ||
0731742a XL |
341 | pub(super) fn report_placeholder_failure( |
342 | &self, | |
0731742a XL |
343 | placeholder_origin: SubregionOrigin<'tcx>, |
344 | sub: Region<'tcx>, | |
345 | sup: Region<'tcx>, | |
5e7ed085 | 346 | ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { |
0731742a | 347 | // I can't think how to do better than this right now. -nikomatsakis |
5869c6ff | 348 | debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure"); |
0731742a | 349 | match placeholder_origin { |
5869c6ff XL |
350 | infer::Subtype(box ref trace) |
351 | if matches!( | |
a2a8927a | 352 | &trace.cause.code().peel_derives(), |
5869c6ff | 353 | ObligationCauseCode::BindingObligation(..) |
f2b60f7d | 354 | | ObligationCauseCode::ExprBindingObligation(..) |
5869c6ff XL |
355 | ) => |
356 | { | |
357 | // Hack to get around the borrow checker because trace.cause has an `Rc`. | |
f2b60f7d FG |
358 | if let ObligationCauseCode::BindingObligation(_, span) |
359 | | ObligationCauseCode::ExprBindingObligation(_, span, ..) = | |
a2a8927a | 360 | &trace.cause.code().peel_derives() |
5869c6ff XL |
361 | { |
362 | let span = *span; | |
363 | let mut err = self.report_concrete_failure(placeholder_origin, sub, sup); | |
364 | err.span_note(span, "the lifetime requirement is introduced here"); | |
365 | err | |
366 | } else { | |
367 | unreachable!() | |
368 | } | |
369 | } | |
e1599b0c | 370 | infer::Subtype(box trace) => { |
0731742a | 371 | let terr = TypeError::RegionsPlaceholderMismatch; |
f2b60f7d | 372 | return self.report_and_explain_type_error(trace, terr); |
0731742a | 373 | } |
5869c6ff | 374 | _ => return self.report_concrete_failure(placeholder_origin, sub, sup), |
0731742a XL |
375 | } |
376 | } | |
8bb4bdeb | 377 | } |