]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_infer/src/infer/error_reporting/note.rs
New upstream version 1.69.0+dfsg1
[rustc.git] / compiler / rustc_infer / src / infer / error_reporting / note.rs
CommitLineData
9ffffee4
FG
1use crate::errors::{
2 note_and_explain, FullfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent,
3 RefLongerThanData, RegionOriginNote, WhereClauseSuggestions,
4};
5use crate::fluent_generated as fluent;
2b03887a
FG
6use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
7use crate::infer::{self, SubregionOrigin};
f2b60f7d 8use rustc_errors::{
9ffffee4 9 AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
f2b60f7d 10};
9c376795 11use rustc_hir::def_id::{DefId, LocalDefId};
5869c6ff 12use rustc_middle::traits::ObligationCauseCode;
ba9703b0 13use rustc_middle::ty::error::TypeError;
9c376795
FG
14use rustc_middle::ty::{self, IsSuggestable, Region};
15use rustc_span::symbol::kw;
60c5eb7d 16
f2b60f7d
FG
17use super::ObligationCauseAsDiagArg;
18
2b03887a 19impl<'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}