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