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