]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_infer/src/errors/mod.rs
Rollup merge of #106946 - dtolnay:hashlinecolumn, r=m-ou-se
[rust.git] / compiler / rustc_infer / src / errors / mod.rs
1 use hir::GenericParamKind;
2 use rustc_errors::{
3     fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
4     IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage,
5 };
6 use rustc_hir as hir;
7 use rustc_hir::FnRetTy;
8 use rustc_macros::{Diagnostic, Subdiagnostic};
9 use rustc_middle::ty::print::TraitRefPrintOnlyTraitPath;
10 use rustc_middle::ty::{Binder, FnSig, Region, Ty, TyCtxt};
11 use rustc_span::symbol::kw;
12 use rustc_span::Symbol;
13 use rustc_span::{symbol::Ident, BytePos, Span};
14
15 use crate::infer::error_reporting::nice_region_error::placeholder_error::Highlighted;
16 use crate::infer::error_reporting::{
17     need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind},
18     ObligationCauseAsDiagArg,
19 };
20
21 pub mod note_and_explain;
22
23 #[derive(Diagnostic)]
24 #[diag(infer_opaque_hidden_type)]
25 pub struct OpaqueHiddenTypeDiag {
26     #[primary_span]
27     #[label]
28     pub span: Span,
29     #[note(opaque_type)]
30     pub opaque_type: Span,
31     #[note(hidden_type)]
32     pub hidden_type: Span,
33 }
34
35 #[derive(Diagnostic)]
36 #[diag(infer_type_annotations_needed, code = "E0282")]
37 pub struct AnnotationRequired<'a> {
38     #[primary_span]
39     pub span: Span,
40     pub source_kind: &'static str,
41     pub source_name: &'a str,
42     #[label]
43     pub failure_span: Option<Span>,
44     #[subdiagnostic]
45     pub bad_label: Option<InferenceBadError<'a>>,
46     #[subdiagnostic]
47     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
48     #[subdiagnostic]
49     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
50 }
51
52 // Copy of `AnnotationRequired` for E0283
53 #[derive(Diagnostic)]
54 #[diag(infer_type_annotations_needed, code = "E0283")]
55 pub struct AmbigousImpl<'a> {
56     #[primary_span]
57     pub span: Span,
58     pub source_kind: &'static str,
59     pub source_name: &'a str,
60     #[label]
61     pub failure_span: Option<Span>,
62     #[subdiagnostic]
63     pub bad_label: Option<InferenceBadError<'a>>,
64     #[subdiagnostic]
65     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
66     #[subdiagnostic]
67     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
68 }
69
70 // Copy of `AnnotationRequired` for E0284
71 #[derive(Diagnostic)]
72 #[diag(infer_type_annotations_needed, code = "E0284")]
73 pub struct AmbigousReturn<'a> {
74     #[primary_span]
75     pub span: Span,
76     pub source_kind: &'static str,
77     pub source_name: &'a str,
78     #[label]
79     pub failure_span: Option<Span>,
80     #[subdiagnostic]
81     pub bad_label: Option<InferenceBadError<'a>>,
82     #[subdiagnostic]
83     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
84     #[subdiagnostic]
85     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
86 }
87
88 #[derive(Diagnostic)]
89 #[diag(infer_need_type_info_in_generator, code = "E0698")]
90 pub struct NeedTypeInfoInGenerator<'a> {
91     #[primary_span]
92     pub span: Span,
93     pub generator_kind: GeneratorKindAsDiagArg,
94     #[subdiagnostic]
95     pub bad_label: InferenceBadError<'a>,
96 }
97
98 // Used when a better one isn't available
99 #[derive(Subdiagnostic)]
100 #[label(infer_label_bad)]
101 pub struct InferenceBadError<'a> {
102     #[primary_span]
103     pub span: Span,
104     pub bad_kind: &'static str,
105     pub prefix_kind: UnderspecifiedArgKind,
106     pub has_parent: bool,
107     pub prefix: &'a str,
108     pub parent_prefix: &'a str,
109     pub parent_name: String,
110     pub name: String,
111 }
112
113 #[derive(Subdiagnostic)]
114 pub enum SourceKindSubdiag<'a> {
115     #[suggestion(
116         infer_source_kind_subdiag_let,
117         style = "verbose",
118         code = ": {type_name}",
119         applicability = "has-placeholders"
120     )]
121     LetLike {
122         #[primary_span]
123         span: Span,
124         name: String,
125         type_name: String,
126         kind: &'static str,
127         x_kind: &'static str,
128         prefix_kind: UnderspecifiedArgKind,
129         prefix: &'a str,
130         arg_name: String,
131     },
132     #[label(infer_source_kind_subdiag_generic_label)]
133     GenericLabel {
134         #[primary_span]
135         span: Span,
136         is_type: bool,
137         param_name: String,
138         parent_exists: bool,
139         parent_prefix: String,
140         parent_name: String,
141     },
142     #[suggestion(
143         infer_source_kind_subdiag_generic_suggestion,
144         style = "verbose",
145         code = "::<{args}>",
146         applicability = "has-placeholders"
147     )]
148     GenericSuggestion {
149         #[primary_span]
150         span: Span,
151         arg_count: usize,
152         args: String,
153     },
154 }
155
156 #[derive(Subdiagnostic)]
157 pub enum SourceKindMultiSuggestion<'a> {
158     #[multipart_suggestion(
159         infer_source_kind_fully_qualified,
160         style = "verbose",
161         applicability = "has-placeholders"
162     )]
163     FullyQualified {
164         #[suggestion_part(code = "{def_path}({adjustment}")]
165         span_lo: Span,
166         #[suggestion_part(code = "{successor_pos}")]
167         span_hi: Span,
168         def_path: String,
169         adjustment: &'a str,
170         successor_pos: &'a str,
171     },
172     #[multipart_suggestion(
173         infer_source_kind_closure_return,
174         style = "verbose",
175         applicability = "has-placeholders"
176     )]
177     ClosureReturn {
178         #[suggestion_part(code = "{start_span_code}")]
179         start_span: Span,
180         start_span_code: String,
181         #[suggestion_part(code = " }}")]
182         end_span: Option<Span>,
183     },
184 }
185
186 #[derive(Subdiagnostic)]
187 #[suggestion(
188     infer_suggest_add_let_for_letchains,
189     style = "verbose",
190     applicability = "machine-applicable",
191     code = "let "
192 )]
193 pub(crate) struct SuggAddLetForLetChains {
194     #[primary_span]
195     pub span: Span,
196 }
197
198 impl<'a> SourceKindMultiSuggestion<'a> {
199     pub fn new_fully_qualified(
200         span: Span,
201         def_path: String,
202         adjustment: &'a str,
203         successor: (&'a str, BytePos),
204     ) -> Self {
205         Self::FullyQualified {
206             span_lo: span.shrink_to_lo(),
207             span_hi: span.shrink_to_hi().with_hi(successor.1),
208             def_path,
209             adjustment,
210             successor_pos: successor.0,
211         }
212     }
213
214     pub fn new_closure_return(
215         ty_info: String,
216         data: &'a FnRetTy<'a>,
217         should_wrap_expr: Option<Span>,
218     ) -> Self {
219         let (arrow, post) = match data {
220             FnRetTy::DefaultReturn(_) => ("-> ", " "),
221             _ => ("", ""),
222         };
223         let (start_span, start_span_code, end_span) = match should_wrap_expr {
224             Some(end_span) => {
225                 (data.span(), format!("{}{}{}{{ ", arrow, ty_info, post), Some(end_span))
226             }
227             None => (data.span(), format!("{}{}{}", arrow, ty_info, post), None),
228         };
229         Self::ClosureReturn { start_span, start_span_code, end_span }
230     }
231 }
232
233 pub enum RegionOriginNote<'a> {
234     Plain {
235         span: Span,
236         msg: DiagnosticMessage,
237     },
238     WithName {
239         span: Span,
240         msg: DiagnosticMessage,
241         name: &'a str,
242         continues: bool,
243     },
244     WithRequirement {
245         span: Span,
246         requirement: ObligationCauseAsDiagArg<'a>,
247         expected_found: Option<(DiagnosticStyledString, DiagnosticStyledString)>,
248     },
249 }
250
251 impl AddToDiagnostic for RegionOriginNote<'_> {
252     fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
253     where
254         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
255     {
256         let mut label_or_note = |span, msg: DiagnosticMessage| {
257             let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
258             let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
259             let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span);
260             if span_is_primary && sub_count == 0 && expanded_sub_count == 0 {
261                 diag.span_label(span, msg);
262             } else if span_is_primary && expanded_sub_count == 0 {
263                 diag.note(msg);
264             } else {
265                 diag.span_note(span, msg);
266             }
267         };
268         match self {
269             RegionOriginNote::Plain { span, msg } => {
270                 label_or_note(span, msg);
271             }
272             RegionOriginNote::WithName { span, msg, name, continues } => {
273                 label_or_note(span, msg);
274                 diag.set_arg("name", name);
275                 diag.set_arg("continues", continues);
276             }
277             RegionOriginNote::WithRequirement {
278                 span,
279                 requirement,
280                 expected_found: Some((expected, found)),
281             } => {
282                 label_or_note(span, fluent::infer_subtype);
283                 diag.set_arg("requirement", requirement);
284
285                 diag.note_expected_found(&"", expected, &"", found);
286             }
287             RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => {
288                 // FIXME: this really should be handled at some earlier stage. Our
289                 // handling of region checking when type errors are present is
290                 // *terrible*.
291                 label_or_note(span, fluent::infer_subtype_2);
292                 diag.set_arg("requirement", requirement);
293             }
294         };
295     }
296 }
297
298 pub enum LifetimeMismatchLabels {
299     InRet {
300         param_span: Span,
301         ret_span: Span,
302         span: Span,
303         label_var1: Option<Ident>,
304     },
305     Normal {
306         hir_equal: bool,
307         ty_sup: Span,
308         ty_sub: Span,
309         span: Span,
310         sup: Option<Ident>,
311         sub: Option<Ident>,
312     },
313 }
314
315 impl AddToDiagnostic for LifetimeMismatchLabels {
316     fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
317     where
318         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
319     {
320         match self {
321             LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
322                 diag.span_label(param_span, fluent::infer_declared_different);
323                 diag.span_label(ret_span, fluent::infer_nothing);
324                 diag.span_label(span, fluent::infer_data_returned);
325                 diag.set_arg("label_var1_exists", label_var1.is_some());
326                 diag.set_arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
327             }
328             LifetimeMismatchLabels::Normal {
329                 hir_equal,
330                 ty_sup,
331                 ty_sub,
332                 span,
333                 sup: label_var1,
334                 sub: label_var2,
335             } => {
336                 if hir_equal {
337                     diag.span_label(ty_sup, fluent::infer_declared_multiple);
338                     diag.span_label(ty_sub, fluent::infer_nothing);
339                     diag.span_label(span, fluent::infer_data_lifetime_flow);
340                 } else {
341                     diag.span_label(ty_sup, fluent::infer_types_declared_different);
342                     diag.span_label(ty_sub, fluent::infer_nothing);
343                     diag.span_label(span, fluent::infer_data_flows);
344                     diag.set_arg("label_var1_exists", label_var1.is_some());
345                     diag.set_arg(
346                         "label_var1",
347                         label_var1.map(|x| x.to_string()).unwrap_or_default(),
348                     );
349                     diag.set_arg("label_var2_exists", label_var2.is_some());
350                     diag.set_arg(
351                         "label_var2",
352                         label_var2.map(|x| x.to_string()).unwrap_or_default(),
353                     );
354                 }
355             }
356         }
357     }
358 }
359
360 pub struct AddLifetimeParamsSuggestion<'a> {
361     pub tcx: TyCtxt<'a>,
362     pub sub: Region<'a>,
363     pub ty_sup: &'a hir::Ty<'a>,
364     pub ty_sub: &'a hir::Ty<'a>,
365     pub add_note: bool,
366 }
367
368 impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
369     fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
370     where
371         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
372     {
373         let mut mk_suggestion = || {
374             let (
375                 hir::Ty { kind: hir::TyKind::Ref(lifetime_sub, _), .. },
376                 hir::Ty { kind: hir::TyKind::Ref(lifetime_sup, _), .. },
377             ) = (self.ty_sub, self.ty_sup) else {
378                 return false;
379             };
380
381             if !lifetime_sub.is_anonymous() || !lifetime_sup.is_anonymous() {
382                 return false;
383             };
384
385             let Some(anon_reg) = self.tcx.is_suitable_region(self.sub) else {
386                 return false;
387             };
388
389             let hir_id = self.tcx.hir().local_def_id_to_hir_id(anon_reg.def_id);
390
391             let node = self.tcx.hir().get(hir_id);
392             let is_impl = matches!(&node, hir::Node::ImplItem(_));
393             let generics = match node {
394                 hir::Node::Item(&hir::Item {
395                     kind: hir::ItemKind::Fn(_, ref generics, ..),
396                     ..
397                 })
398                 | hir::Node::TraitItem(&hir::TraitItem { ref generics, .. })
399                 | hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => generics,
400                 _ => return false,
401             };
402
403             let suggestion_param_name = generics
404                 .params
405                 .iter()
406                 .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
407                 .map(|p| p.name.ident().name)
408                 .find(|i| *i != kw::UnderscoreLifetime);
409             let introduce_new = suggestion_param_name.is_none();
410             let suggestion_param_name =
411                 suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| "'a".to_owned());
412
413             debug!(?lifetime_sup.ident.span);
414             debug!(?lifetime_sub.ident.span);
415             let make_suggestion = |ident: Ident| {
416                 let sugg = if ident.name == kw::Empty {
417                     format!("{}, ", suggestion_param_name)
418                 } else if ident.name == kw::UnderscoreLifetime && ident.span.is_empty() {
419                     format!("{} ", suggestion_param_name)
420                 } else {
421                     suggestion_param_name.clone()
422                 };
423                 (ident.span, sugg)
424             };
425             let mut suggestions =
426                 vec![make_suggestion(lifetime_sub.ident), make_suggestion(lifetime_sup.ident)];
427
428             if introduce_new {
429                 let new_param_suggestion = if let Some(first) =
430                     generics.params.iter().find(|p| !p.name.ident().span.is_empty())
431                 {
432                     (first.span.shrink_to_lo(), format!("{}, ", suggestion_param_name))
433                 } else {
434                     (generics.span, format!("<{}>", suggestion_param_name))
435                 };
436
437                 suggestions.push(new_param_suggestion);
438             }
439
440             diag.multipart_suggestion(
441                 fluent::infer_lifetime_param_suggestion,
442                 suggestions,
443                 Applicability::MaybeIncorrect,
444             );
445             diag.set_arg("is_impl", is_impl);
446             true
447         };
448         if mk_suggestion() && self.add_note {
449             diag.note(fluent::infer_lifetime_param_suggestion_elided);
450         }
451     }
452 }
453
454 #[derive(Diagnostic)]
455 #[diag(infer_lifetime_mismatch, code = "E0623")]
456 pub struct LifetimeMismatch<'a> {
457     #[primary_span]
458     pub span: Span,
459     #[subdiagnostic]
460     pub labels: LifetimeMismatchLabels,
461     #[subdiagnostic]
462     pub suggestion: AddLifetimeParamsSuggestion<'a>,
463 }
464
465 pub struct IntroducesStaticBecauseUnmetLifetimeReq {
466     pub unmet_requirements: MultiSpan,
467     pub binding_span: Span,
468 }
469
470 impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
471     fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, _: F)
472     where
473         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
474     {
475         self.unmet_requirements
476             .push_span_label(self.binding_span, fluent::infer_msl_introduces_static);
477         diag.span_note(self.unmet_requirements, fluent::infer_msl_unmet_req);
478     }
479 }
480
481 // FIXME(#100717): replace with a `Option<Span>` when subdiagnostic supports that
482 #[derive(Subdiagnostic)]
483 pub enum DoesNotOutliveStaticFromImpl {
484     #[note(infer_does_not_outlive_static_from_impl)]
485     Spanned {
486         #[primary_span]
487         span: Span,
488     },
489     #[note(infer_does_not_outlive_static_from_impl)]
490     Unspanned,
491 }
492
493 #[derive(Subdiagnostic)]
494 pub enum ImplicitStaticLifetimeSubdiag {
495     #[note(infer_implicit_static_lifetime_note)]
496     Note {
497         #[primary_span]
498         span: Span,
499     },
500     #[suggestion(
501         infer_implicit_static_lifetime_suggestion,
502         style = "verbose",
503         code = " + '_",
504         applicability = "maybe-incorrect"
505     )]
506     Sugg {
507         #[primary_span]
508         span: Span,
509     },
510 }
511
512 #[derive(Diagnostic)]
513 #[diag(infer_mismatched_static_lifetime)]
514 pub struct MismatchedStaticLifetime<'a> {
515     #[primary_span]
516     pub cause_span: Span,
517     #[subdiagnostic]
518     pub unmet_lifetime_reqs: IntroducesStaticBecauseUnmetLifetimeReq,
519     #[subdiagnostic]
520     pub expl: Option<note_and_explain::RegionExplanation<'a>>,
521     #[subdiagnostic]
522     pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl,
523     #[subdiagnostic]
524     pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
525 }
526
527 #[derive(Diagnostic)]
528 pub enum ExplicitLifetimeRequired<'a> {
529     #[diag(infer_explicit_lifetime_required_with_ident, code = "E0621")]
530     WithIdent {
531         #[primary_span]
532         #[label]
533         span: Span,
534         simple_ident: Ident,
535         named: String,
536         #[suggestion(
537             infer_explicit_lifetime_required_sugg_with_ident,
538             code = "{new_ty}",
539             applicability = "unspecified"
540         )]
541         new_ty_span: Span,
542         #[skip_arg]
543         new_ty: Ty<'a>,
544     },
545     #[diag(infer_explicit_lifetime_required_with_param_type, code = "E0621")]
546     WithParamType {
547         #[primary_span]
548         #[label]
549         span: Span,
550         named: String,
551         #[suggestion(
552             infer_explicit_lifetime_required_sugg_with_param_type,
553             code = "{new_ty}",
554             applicability = "unspecified"
555         )]
556         new_ty_span: Span,
557         #[skip_arg]
558         new_ty: Ty<'a>,
559     },
560 }
561
562 pub enum TyOrSig<'tcx> {
563     Ty(Highlighted<'tcx, Ty<'tcx>>),
564     ClosureSig(Highlighted<'tcx, Binder<'tcx, FnSig<'tcx>>>),
565 }
566
567 impl IntoDiagnosticArg for TyOrSig<'_> {
568     fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
569         match self {
570             TyOrSig::Ty(ty) => ty.into_diagnostic_arg(),
571             TyOrSig::ClosureSig(sig) => sig.into_diagnostic_arg(),
572         }
573     }
574 }
575
576 #[derive(Subdiagnostic)]
577 pub enum ActualImplExplNotes<'tcx> {
578     #[note(infer_actual_impl_expl_expected_signature_two)]
579     ExpectedSignatureTwo {
580         leading_ellipsis: bool,
581         ty_or_sig: TyOrSig<'tcx>,
582         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
583         lifetime_1: usize,
584         lifetime_2: usize,
585     },
586     #[note(infer_actual_impl_expl_expected_signature_any)]
587     ExpectedSignatureAny {
588         leading_ellipsis: bool,
589         ty_or_sig: TyOrSig<'tcx>,
590         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
591         lifetime_1: usize,
592     },
593     #[note(infer_actual_impl_expl_expected_signature_some)]
594     ExpectedSignatureSome {
595         leading_ellipsis: bool,
596         ty_or_sig: TyOrSig<'tcx>,
597         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
598         lifetime_1: usize,
599     },
600     #[note(infer_actual_impl_expl_expected_signature_nothing)]
601     ExpectedSignatureNothing {
602         leading_ellipsis: bool,
603         ty_or_sig: TyOrSig<'tcx>,
604         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
605     },
606     #[note(infer_actual_impl_expl_expected_passive_two)]
607     ExpectedPassiveTwo {
608         leading_ellipsis: bool,
609         ty_or_sig: TyOrSig<'tcx>,
610         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
611         lifetime_1: usize,
612         lifetime_2: usize,
613     },
614     #[note(infer_actual_impl_expl_expected_passive_any)]
615     ExpectedPassiveAny {
616         leading_ellipsis: bool,
617         ty_or_sig: TyOrSig<'tcx>,
618         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
619         lifetime_1: usize,
620     },
621     #[note(infer_actual_impl_expl_expected_passive_some)]
622     ExpectedPassiveSome {
623         leading_ellipsis: bool,
624         ty_or_sig: TyOrSig<'tcx>,
625         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
626         lifetime_1: usize,
627     },
628     #[note(infer_actual_impl_expl_expected_passive_nothing)]
629     ExpectedPassiveNothing {
630         leading_ellipsis: bool,
631         ty_or_sig: TyOrSig<'tcx>,
632         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
633     },
634     #[note(infer_actual_impl_expl_expected_other_two)]
635     ExpectedOtherTwo {
636         leading_ellipsis: bool,
637         ty_or_sig: TyOrSig<'tcx>,
638         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
639         lifetime_1: usize,
640         lifetime_2: usize,
641     },
642     #[note(infer_actual_impl_expl_expected_other_any)]
643     ExpectedOtherAny {
644         leading_ellipsis: bool,
645         ty_or_sig: TyOrSig<'tcx>,
646         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
647         lifetime_1: usize,
648     },
649     #[note(infer_actual_impl_expl_expected_other_some)]
650     ExpectedOtherSome {
651         leading_ellipsis: bool,
652         ty_or_sig: TyOrSig<'tcx>,
653         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
654         lifetime_1: usize,
655     },
656     #[note(infer_actual_impl_expl_expected_other_nothing)]
657     ExpectedOtherNothing {
658         leading_ellipsis: bool,
659         ty_or_sig: TyOrSig<'tcx>,
660         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
661     },
662     #[note(infer_actual_impl_expl_but_actually_implements_trait)]
663     ButActuallyImplementsTrait {
664         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
665         has_lifetime: bool,
666         lifetime: usize,
667     },
668     #[note(infer_actual_impl_expl_but_actually_implemented_for_ty)]
669     ButActuallyImplementedForTy {
670         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
671         has_lifetime: bool,
672         lifetime: usize,
673         ty: String,
674     },
675     #[note(infer_actual_impl_expl_but_actually_ty_implements)]
676     ButActuallyTyImplements {
677         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
678         has_lifetime: bool,
679         lifetime: usize,
680         ty: String,
681     },
682 }
683
684 pub enum ActualImplExpectedKind {
685     Signature,
686     Passive,
687     Other,
688 }
689
690 pub enum ActualImplExpectedLifetimeKind {
691     Two,
692     Any,
693     Some,
694     Nothing,
695 }
696
697 impl<'tcx> ActualImplExplNotes<'tcx> {
698     pub fn new_expected(
699         kind: ActualImplExpectedKind,
700         lt_kind: ActualImplExpectedLifetimeKind,
701         leading_ellipsis: bool,
702         ty_or_sig: TyOrSig<'tcx>,
703         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
704         lifetime_1: usize,
705         lifetime_2: usize,
706     ) -> Self {
707         match (kind, lt_kind) {
708             (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => {
709                 Self::ExpectedSignatureTwo {
710                     leading_ellipsis,
711                     ty_or_sig,
712                     trait_path,
713                     lifetime_1,
714                     lifetime_2,
715                 }
716             }
717             (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => {
718                 Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
719             }
720             (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => {
721                 Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
722             }
723             (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => {
724                 Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path }
725             }
726             (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => {
727                 Self::ExpectedPassiveTwo {
728                     leading_ellipsis,
729                     ty_or_sig,
730                     trait_path,
731                     lifetime_1,
732                     lifetime_2,
733                 }
734             }
735             (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => {
736                 Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
737             }
738             (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => {
739                 Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
740             }
741             (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => {
742                 Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path }
743             }
744             (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => {
745                 Self::ExpectedOtherTwo {
746                     leading_ellipsis,
747                     ty_or_sig,
748                     trait_path,
749                     lifetime_1,
750                     lifetime_2,
751                 }
752             }
753             (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => {
754                 Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
755             }
756             (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => {
757                 Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
758             }
759             (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => {
760                 Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path }
761             }
762         }
763     }
764 }
765
766 #[derive(Diagnostic)]
767 #[diag(infer_trait_placeholder_mismatch)]
768 pub struct TraitPlaceholderMismatch<'tcx> {
769     #[primary_span]
770     pub span: Span,
771     #[label(label_satisfy)]
772     pub satisfy_span: Option<Span>,
773     #[label(label_where)]
774     pub where_span: Option<Span>,
775     #[label(label_dup)]
776     pub dup_span: Option<Span>,
777     pub def_id: String,
778     pub trait_def_id: String,
779
780     #[subdiagnostic]
781     pub actual_impl_expl_notes: Vec<ActualImplExplNotes<'tcx>>,
782 }
783
784 pub struct ConsiderBorrowingParamHelp {
785     pub spans: Vec<Span>,
786 }
787
788 impl AddToDiagnostic for ConsiderBorrowingParamHelp {
789     fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
790     where
791         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
792     {
793         let mut type_param_span: MultiSpan = self.spans.clone().into();
794         for &span in &self.spans {
795             // Seems like we can't call f() here as Into<DiagnosticMessage> is required
796             type_param_span.push_span_label(span, fluent::infer_tid_consider_borrowing);
797         }
798         let msg = f(diag, fluent::infer_tid_param_help.into());
799         diag.span_help(type_param_span, msg);
800     }
801 }
802
803 #[derive(Subdiagnostic)]
804 #[help(infer_tid_rel_help)]
805 pub struct RelationshipHelp;
806
807 #[derive(Diagnostic)]
808 #[diag(infer_trait_impl_diff)]
809 pub struct TraitImplDiff {
810     #[primary_span]
811     #[label(found)]
812     pub sp: Span,
813     #[label(expected)]
814     pub trait_sp: Span,
815     #[note(expected_found)]
816     pub note: (),
817     #[subdiagnostic]
818     pub param_help: ConsiderBorrowingParamHelp,
819     #[subdiagnostic]
820     // Seems like subdiagnostics are always pushed to the end, so this one
821     // also has to be a subdiagnostic to maintain order.
822     pub rel_help: Option<RelationshipHelp>,
823     pub expected: String,
824     pub found: String,
825 }
826
827 pub struct DynTraitConstraintSuggestion {
828     pub span: Span,
829     pub ident: Ident,
830 }
831
832 impl AddToDiagnostic for DynTraitConstraintSuggestion {
833     fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
834     where
835         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
836     {
837         let mut multi_span: MultiSpan = vec![self.span].into();
838         multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label);
839         multi_span.push_span_label(self.ident.span, fluent::infer_dtcs_introduces_requirement);
840         let msg = f(diag, fluent::infer_dtcs_has_req_note.into());
841         diag.span_note(multi_span, msg);
842         let msg = f(diag, fluent::infer_dtcs_suggestion.into());
843         diag.span_suggestion_verbose(
844             self.span.shrink_to_hi(),
845             msg,
846             " + '_",
847             Applicability::MaybeIncorrect,
848         );
849     }
850 }
851
852 #[derive(Diagnostic)]
853 #[diag(infer_but_calling_introduces, code = "E0772")]
854 pub struct ButCallingIntroduces {
855     #[label(label1)]
856     pub param_ty_span: Span,
857     #[primary_span]
858     #[label(label2)]
859     pub cause_span: Span,
860
861     pub has_param_name: bool,
862     pub param_name: String,
863     pub has_lifetime: bool,
864     pub lifetime: String,
865     pub assoc_item: Symbol,
866     pub has_impl_path: bool,
867     pub impl_path: String,
868 }
869
870 pub struct ReqIntroducedLocations {
871     pub span: MultiSpan,
872     pub spans: Vec<Span>,
873     pub fn_decl_span: Span,
874     pub cause_span: Span,
875     pub add_label: bool,
876 }
877
878 impl AddToDiagnostic for ReqIntroducedLocations {
879     fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, f: F)
880     where
881         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
882     {
883         for sp in self.spans {
884             self.span.push_span_label(sp, fluent::infer_ril_introduced_here);
885         }
886
887         if self.add_label {
888             self.span.push_span_label(self.fn_decl_span, fluent::infer_ril_introduced_by);
889         }
890         self.span.push_span_label(self.cause_span, fluent::infer_ril_because_of);
891         let msg = f(diag, fluent::infer_ril_static_introduced_by.into());
892         diag.span_note(self.span, msg);
893     }
894 }
895
896 pub struct MoreTargeted {
897     pub ident: Symbol,
898 }
899
900 impl AddToDiagnostic for MoreTargeted {
901     fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _f: F)
902     where
903         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
904     {
905         diag.code(rustc_errors::error_code!(E0772));
906         diag.set_primary_message(fluent::infer_more_targeted);
907         diag.set_arg("ident", self.ident);
908     }
909 }
910
911 #[derive(Diagnostic)]
912 #[diag(infer_but_needs_to_satisfy, code = "E0759")]
913 pub struct ButNeedsToSatisfy {
914     #[primary_span]
915     pub sp: Span,
916     #[label(influencer)]
917     pub influencer_point: Span,
918     #[label(used_here)]
919     pub spans: Vec<Span>,
920     #[label(require)]
921     pub require_span_as_label: Option<Span>,
922     #[note(require)]
923     pub require_span_as_note: Option<Span>,
924     #[note(introduced_by_bound)]
925     pub bound: Option<Span>,
926
927     #[subdiagnostic]
928     pub req_introduces_loc: Option<ReqIntroducedLocations>,
929
930     pub has_param_name: bool,
931     pub param_name: String,
932     pub spans_empty: bool,
933     pub has_lifetime: bool,
934     pub lifetime: String,
935 }