• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use hir::GenericParamKind;
2 use rustc_errors::{
3     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::fluent_generated as fluent;
16 use crate::infer::error_reporting::{
17     need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind},
18     nice_region_error::placeholder_error::Highlighted,
19     ObligationCauseAsDiagArg,
20 };
21 
22 pub mod note_and_explain;
23 
24 #[derive(Diagnostic)]
25 #[diag(infer_opaque_hidden_type)]
26 pub struct OpaqueHiddenTypeDiag {
27     #[primary_span]
28     #[label]
29     pub span: Span,
30     #[note(infer_opaque_type)]
31     pub opaque_type: Span,
32     #[note(infer_hidden_type)]
33     pub hidden_type: Span,
34 }
35 
36 #[derive(Diagnostic)]
37 #[diag(infer_type_annotations_needed, code = "E0282")]
38 pub struct AnnotationRequired<'a> {
39     #[primary_span]
40     pub span: Span,
41     pub source_kind: &'static str,
42     pub source_name: &'a str,
43     #[label]
44     pub failure_span: Option<Span>,
45     #[subdiagnostic]
46     pub bad_label: Option<InferenceBadError<'a>>,
47     #[subdiagnostic]
48     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
49     #[subdiagnostic]
50     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
51 }
52 
53 // Copy of `AnnotationRequired` for E0283
54 #[derive(Diagnostic)]
55 #[diag(infer_type_annotations_needed, code = "E0283")]
56 pub struct AmbiguousImpl<'a> {
57     #[primary_span]
58     pub span: Span,
59     pub source_kind: &'static str,
60     pub source_name: &'a str,
61     #[label]
62     pub failure_span: Option<Span>,
63     #[subdiagnostic]
64     pub bad_label: Option<InferenceBadError<'a>>,
65     #[subdiagnostic]
66     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
67     #[subdiagnostic]
68     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
69 }
70 
71 // Copy of `AnnotationRequired` for E0284
72 #[derive(Diagnostic)]
73 #[diag(infer_type_annotations_needed, code = "E0284")]
74 pub struct AmbiguousReturn<'a> {
75     #[primary_span]
76     pub span: Span,
77     pub source_kind: &'static str,
78     pub source_name: &'a str,
79     #[label]
80     pub failure_span: Option<Span>,
81     #[subdiagnostic]
82     pub bad_label: Option<InferenceBadError<'a>>,
83     #[subdiagnostic]
84     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
85     #[subdiagnostic]
86     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
87 }
88 
89 #[derive(Diagnostic)]
90 #[diag(infer_need_type_info_in_generator, code = "E0698")]
91 pub struct NeedTypeInfoInGenerator<'a> {
92     #[primary_span]
93     pub span: Span,
94     pub generator_kind: GeneratorKindAsDiagArg,
95     #[subdiagnostic]
96     pub bad_label: InferenceBadError<'a>,
97 }
98 
99 // Used when a better one isn't available
100 #[derive(Subdiagnostic)]
101 #[label(infer_label_bad)]
102 pub struct InferenceBadError<'a> {
103     #[primary_span]
104     pub span: Span,
105     pub bad_kind: &'static str,
106     pub prefix_kind: UnderspecifiedArgKind,
107     pub has_parent: bool,
108     pub prefix: &'a str,
109     pub parent_prefix: &'a str,
110     pub parent_name: String,
111     pub name: String,
112 }
113 
114 #[derive(Subdiagnostic)]
115 pub enum SourceKindSubdiag<'a> {
116     #[suggestion(
117         infer_source_kind_subdiag_let,
118         style = "verbose",
119         code = ": {type_name}",
120         applicability = "has-placeholders"
121     )]
122     LetLike {
123         #[primary_span]
124         span: Span,
125         name: String,
126         type_name: String,
127         kind: &'static str,
128         x_kind: &'static str,
129         prefix_kind: UnderspecifiedArgKind,
130         prefix: &'a str,
131         arg_name: String,
132     },
133     #[label(infer_source_kind_subdiag_generic_label)]
134     GenericLabel {
135         #[primary_span]
136         span: Span,
137         is_type: bool,
138         param_name: String,
139         parent_exists: bool,
140         parent_prefix: String,
141         parent_name: String,
142     },
143     #[suggestion(
144         infer_source_kind_subdiag_generic_suggestion,
145         style = "verbose",
146         code = "::<{args}>",
147         applicability = "has-placeholders"
148     )]
149     GenericSuggestion {
150         #[primary_span]
151         span: Span,
152         arg_count: usize,
153         args: String,
154     },
155 }
156 
157 #[derive(Subdiagnostic)]
158 pub enum SourceKindMultiSuggestion<'a> {
159     #[multipart_suggestion(
160         infer_source_kind_fully_qualified,
161         style = "verbose",
162         applicability = "has-placeholders"
163     )]
164     FullyQualified {
165         #[suggestion_part(code = "{def_path}({adjustment}")]
166         span_lo: Span,
167         #[suggestion_part(code = "{successor_pos}")]
168         span_hi: Span,
169         def_path: String,
170         adjustment: &'a str,
171         successor_pos: &'a str,
172     },
173     #[multipart_suggestion(
174         infer_source_kind_closure_return,
175         style = "verbose",
176         applicability = "has-placeholders"
177     )]
178     ClosureReturn {
179         #[suggestion_part(code = "{start_span_code}")]
180         start_span: Span,
181         start_span_code: String,
182         #[suggestion_part(code = " }}")]
183         end_span: Option<Span>,
184     },
185 }
186 
187 impl<'a> SourceKindMultiSuggestion<'a> {
new_fully_qualified( span: Span, def_path: String, adjustment: &'a str, successor: (&'a str, BytePos), ) -> Self188     pub fn new_fully_qualified(
189         span: Span,
190         def_path: String,
191         adjustment: &'a str,
192         successor: (&'a str, BytePos),
193     ) -> Self {
194         Self::FullyQualified {
195             span_lo: span.shrink_to_lo(),
196             span_hi: span.shrink_to_hi().with_hi(successor.1),
197             def_path,
198             adjustment,
199             successor_pos: successor.0,
200         }
201     }
202 
new_closure_return( ty_info: String, data: &'a FnRetTy<'a>, should_wrap_expr: Option<Span>, ) -> Self203     pub fn new_closure_return(
204         ty_info: String,
205         data: &'a FnRetTy<'a>,
206         should_wrap_expr: Option<Span>,
207     ) -> Self {
208         let (arrow, post) = match data {
209             FnRetTy::DefaultReturn(_) => ("-> ", " "),
210             _ => ("", ""),
211         };
212         let (start_span, start_span_code, end_span) = match should_wrap_expr {
213             Some(end_span) => {
214                 (data.span(), format!("{}{}{}{{ ", arrow, ty_info, post), Some(end_span))
215             }
216             None => (data.span(), format!("{}{}{}", arrow, ty_info, post), None),
217         };
218         Self::ClosureReturn { start_span, start_span_code, end_span }
219     }
220 }
221 
222 pub enum RegionOriginNote<'a> {
223     Plain {
224         span: Span,
225         msg: DiagnosticMessage,
226     },
227     WithName {
228         span: Span,
229         msg: DiagnosticMessage,
230         name: &'a str,
231         continues: bool,
232     },
233     WithRequirement {
234         span: Span,
235         requirement: ObligationCauseAsDiagArg<'a>,
236         expected_found: Option<(DiagnosticStyledString, DiagnosticStyledString)>,
237     },
238 }
239 
240 impl AddToDiagnostic for RegionOriginNote<'_> {
add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,241     fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
242     where
243         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
244     {
245         let mut label_or_note = |span, msg: DiagnosticMessage| {
246             let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
247             let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
248             let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span);
249             if span_is_primary && sub_count == 0 && expanded_sub_count == 0 {
250                 diag.span_label(span, msg);
251             } else if span_is_primary && expanded_sub_count == 0 {
252                 diag.note(msg);
253             } else {
254                 diag.span_note(span, msg);
255             }
256         };
257         match self {
258             RegionOriginNote::Plain { span, msg } => {
259                 label_or_note(span, msg);
260             }
261             RegionOriginNote::WithName { span, msg, name, continues } => {
262                 label_or_note(span, msg);
263                 diag.set_arg("name", name);
264                 diag.set_arg("continues", continues);
265             }
266             RegionOriginNote::WithRequirement {
267                 span,
268                 requirement,
269                 expected_found: Some((expected, found)),
270             } => {
271                 label_or_note(span, fluent::infer_subtype);
272                 diag.set_arg("requirement", requirement);
273 
274                 diag.note_expected_found(&"", expected, &"", found);
275             }
276             RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => {
277                 // FIXME: this really should be handled at some earlier stage. Our
278                 // handling of region checking when type errors are present is
279                 // *terrible*.
280                 label_or_note(span, fluent::infer_subtype_2);
281                 diag.set_arg("requirement", requirement);
282             }
283         };
284     }
285 }
286 
287 pub enum LifetimeMismatchLabels {
288     InRet {
289         param_span: Span,
290         ret_span: Span,
291         span: Span,
292         label_var1: Option<Ident>,
293     },
294     Normal {
295         hir_equal: bool,
296         ty_sup: Span,
297         ty_sub: Span,
298         span: Span,
299         sup: Option<Ident>,
300         sub: Option<Ident>,
301     },
302 }
303 
304 impl AddToDiagnostic for LifetimeMismatchLabels {
add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,305     fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
306     where
307         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
308     {
309         match self {
310             LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
311                 diag.span_label(param_span, fluent::infer_declared_different);
312                 diag.span_label(ret_span, fluent::infer_nothing);
313                 diag.span_label(span, fluent::infer_data_returned);
314                 diag.set_arg("label_var1_exists", label_var1.is_some());
315                 diag.set_arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
316             }
317             LifetimeMismatchLabels::Normal {
318                 hir_equal,
319                 ty_sup,
320                 ty_sub,
321                 span,
322                 sup: label_var1,
323                 sub: label_var2,
324             } => {
325                 if hir_equal {
326                     diag.span_label(ty_sup, fluent::infer_declared_multiple);
327                     diag.span_label(ty_sub, fluent::infer_nothing);
328                     diag.span_label(span, fluent::infer_data_lifetime_flow);
329                 } else {
330                     diag.span_label(ty_sup, fluent::infer_types_declared_different);
331                     diag.span_label(ty_sub, fluent::infer_nothing);
332                     diag.span_label(span, fluent::infer_data_flows);
333                     diag.set_arg("label_var1_exists", label_var1.is_some());
334                     diag.set_arg(
335                         "label_var1",
336                         label_var1.map(|x| x.to_string()).unwrap_or_default(),
337                     );
338                     diag.set_arg("label_var2_exists", label_var2.is_some());
339                     diag.set_arg(
340                         "label_var2",
341                         label_var2.map(|x| x.to_string()).unwrap_or_default(),
342                     );
343                 }
344             }
345         }
346     }
347 }
348 
349 pub struct AddLifetimeParamsSuggestion<'a> {
350     pub tcx: TyCtxt<'a>,
351     pub sub: Region<'a>,
352     pub ty_sup: &'a hir::Ty<'a>,
353     pub ty_sub: &'a hir::Ty<'a>,
354     pub add_note: bool,
355 }
356 
357 impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,358     fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
359     where
360         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
361     {
362         let mut mk_suggestion = || {
363             let (
364                 hir::Ty { kind: hir::TyKind::Ref(lifetime_sub, _), .. },
365                 hir::Ty { kind: hir::TyKind::Ref(lifetime_sup, _), .. },
366             ) = (self.ty_sub, self.ty_sup) else {
367                 return false;
368             };
369 
370             if !lifetime_sub.is_anonymous() || !lifetime_sup.is_anonymous() {
371                 return false;
372             };
373 
374             let Some(anon_reg) = self.tcx.is_suitable_region(self.sub) else {
375                 return false;
376             };
377 
378             let hir_id = self.tcx.hir().local_def_id_to_hir_id(anon_reg.def_id);
379 
380             let node = self.tcx.hir().get(hir_id);
381             let is_impl = matches!(&node, hir::Node::ImplItem(_));
382             let generics = match node {
383                 hir::Node::Item(&hir::Item {
384                     kind: hir::ItemKind::Fn(_, ref generics, ..),
385                     ..
386                 })
387                 | hir::Node::TraitItem(&hir::TraitItem { ref generics, .. })
388                 | hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => generics,
389                 _ => return false,
390             };
391 
392             let suggestion_param_name = generics
393                 .params
394                 .iter()
395                 .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
396                 .map(|p| p.name.ident().name)
397                 .find(|i| *i != kw::UnderscoreLifetime);
398             let introduce_new = suggestion_param_name.is_none();
399             let suggestion_param_name =
400                 suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| "'a".to_owned());
401 
402             debug!(?lifetime_sup.ident.span);
403             debug!(?lifetime_sub.ident.span);
404             let make_suggestion = |ident: Ident| {
405                 let sugg = if ident.name == kw::Empty {
406                     format!("{}, ", suggestion_param_name)
407                 } else if ident.name == kw::UnderscoreLifetime && ident.span.is_empty() {
408                     format!("{} ", suggestion_param_name)
409                 } else {
410                     suggestion_param_name.clone()
411                 };
412                 (ident.span, sugg)
413             };
414             let mut suggestions =
415                 vec![make_suggestion(lifetime_sub.ident), make_suggestion(lifetime_sup.ident)];
416 
417             if introduce_new {
418                 let new_param_suggestion = if let Some(first) =
419                     generics.params.iter().find(|p| !p.name.ident().span.is_empty())
420                 {
421                     (first.span.shrink_to_lo(), format!("{}, ", suggestion_param_name))
422                 } else {
423                     (generics.span, format!("<{}>", suggestion_param_name))
424                 };
425 
426                 suggestions.push(new_param_suggestion);
427             }
428 
429             diag.multipart_suggestion(
430                 fluent::infer_lifetime_param_suggestion,
431                 suggestions,
432                 Applicability::MaybeIncorrect,
433             );
434             diag.set_arg("is_impl", is_impl);
435             true
436         };
437         if mk_suggestion() && self.add_note {
438             diag.note(fluent::infer_lifetime_param_suggestion_elided);
439         }
440     }
441 }
442 
443 #[derive(Diagnostic)]
444 #[diag(infer_lifetime_mismatch, code = "E0623")]
445 pub struct LifetimeMismatch<'a> {
446     #[primary_span]
447     pub span: Span,
448     #[subdiagnostic]
449     pub labels: LifetimeMismatchLabels,
450     #[subdiagnostic]
451     pub suggestion: AddLifetimeParamsSuggestion<'a>,
452 }
453 
454 pub struct IntroducesStaticBecauseUnmetLifetimeReq {
455     pub unmet_requirements: MultiSpan,
456     pub binding_span: Span,
457 }
458 
459 impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, _: F) where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,460     fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, _: F)
461     where
462         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
463     {
464         self.unmet_requirements
465             .push_span_label(self.binding_span, fluent::infer_msl_introduces_static);
466         diag.span_note(self.unmet_requirements, fluent::infer_msl_unmet_req);
467     }
468 }
469 
470 // FIXME(#100717): replace with a `Option<Span>` when subdiagnostic supports that
471 #[derive(Subdiagnostic)]
472 pub enum DoesNotOutliveStaticFromImpl {
473     #[note(infer_does_not_outlive_static_from_impl)]
474     Spanned {
475         #[primary_span]
476         span: Span,
477     },
478     #[note(infer_does_not_outlive_static_from_impl)]
479     Unspanned,
480 }
481 
482 #[derive(Subdiagnostic)]
483 pub enum ImplicitStaticLifetimeSubdiag {
484     #[note(infer_implicit_static_lifetime_note)]
485     Note {
486         #[primary_span]
487         span: Span,
488     },
489     #[suggestion(
490         infer_implicit_static_lifetime_suggestion,
491         style = "verbose",
492         code = " + '_",
493         applicability = "maybe-incorrect"
494     )]
495     Sugg {
496         #[primary_span]
497         span: Span,
498     },
499 }
500 
501 #[derive(Diagnostic)]
502 #[diag(infer_mismatched_static_lifetime)]
503 pub struct MismatchedStaticLifetime<'a> {
504     #[primary_span]
505     pub cause_span: Span,
506     #[subdiagnostic]
507     pub unmet_lifetime_reqs: IntroducesStaticBecauseUnmetLifetimeReq,
508     #[subdiagnostic]
509     pub expl: Option<note_and_explain::RegionExplanation<'a>>,
510     #[subdiagnostic]
511     pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl,
512     #[subdiagnostic]
513     pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
514 }
515 
516 #[derive(Diagnostic)]
517 pub enum ExplicitLifetimeRequired<'a> {
518     #[diag(infer_explicit_lifetime_required_with_ident, code = "E0621")]
519     WithIdent {
520         #[primary_span]
521         #[label]
522         span: Span,
523         simple_ident: Ident,
524         named: String,
525         #[suggestion(
526             infer_explicit_lifetime_required_sugg_with_ident,
527             code = "{new_ty}",
528             applicability = "unspecified"
529         )]
530         new_ty_span: Span,
531         #[skip_arg]
532         new_ty: Ty<'a>,
533     },
534     #[diag(infer_explicit_lifetime_required_with_param_type, code = "E0621")]
535     WithParamType {
536         #[primary_span]
537         #[label]
538         span: Span,
539         named: String,
540         #[suggestion(
541             infer_explicit_lifetime_required_sugg_with_param_type,
542             code = "{new_ty}",
543             applicability = "unspecified"
544         )]
545         new_ty_span: Span,
546         #[skip_arg]
547         new_ty: Ty<'a>,
548     },
549 }
550 
551 pub enum TyOrSig<'tcx> {
552     Ty(Highlighted<'tcx, Ty<'tcx>>),
553     ClosureSig(Highlighted<'tcx, Binder<'tcx, FnSig<'tcx>>>),
554 }
555 
556 impl IntoDiagnosticArg for TyOrSig<'_> {
into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static>557     fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
558         match self {
559             TyOrSig::Ty(ty) => ty.into_diagnostic_arg(),
560             TyOrSig::ClosureSig(sig) => sig.into_diagnostic_arg(),
561         }
562     }
563 }
564 
565 #[derive(Subdiagnostic)]
566 pub enum ActualImplExplNotes<'tcx> {
567     #[note(infer_actual_impl_expl_expected_signature_two)]
568     ExpectedSignatureTwo {
569         leading_ellipsis: bool,
570         ty_or_sig: TyOrSig<'tcx>,
571         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
572         lifetime_1: usize,
573         lifetime_2: usize,
574     },
575     #[note(infer_actual_impl_expl_expected_signature_any)]
576     ExpectedSignatureAny {
577         leading_ellipsis: bool,
578         ty_or_sig: TyOrSig<'tcx>,
579         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
580         lifetime_1: usize,
581     },
582     #[note(infer_actual_impl_expl_expected_signature_some)]
583     ExpectedSignatureSome {
584         leading_ellipsis: bool,
585         ty_or_sig: TyOrSig<'tcx>,
586         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
587         lifetime_1: usize,
588     },
589     #[note(infer_actual_impl_expl_expected_signature_nothing)]
590     ExpectedSignatureNothing {
591         leading_ellipsis: bool,
592         ty_or_sig: TyOrSig<'tcx>,
593         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
594     },
595     #[note(infer_actual_impl_expl_expected_passive_two)]
596     ExpectedPassiveTwo {
597         leading_ellipsis: bool,
598         ty_or_sig: TyOrSig<'tcx>,
599         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
600         lifetime_1: usize,
601         lifetime_2: usize,
602     },
603     #[note(infer_actual_impl_expl_expected_passive_any)]
604     ExpectedPassiveAny {
605         leading_ellipsis: bool,
606         ty_or_sig: TyOrSig<'tcx>,
607         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
608         lifetime_1: usize,
609     },
610     #[note(infer_actual_impl_expl_expected_passive_some)]
611     ExpectedPassiveSome {
612         leading_ellipsis: bool,
613         ty_or_sig: TyOrSig<'tcx>,
614         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
615         lifetime_1: usize,
616     },
617     #[note(infer_actual_impl_expl_expected_passive_nothing)]
618     ExpectedPassiveNothing {
619         leading_ellipsis: bool,
620         ty_or_sig: TyOrSig<'tcx>,
621         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
622     },
623     #[note(infer_actual_impl_expl_expected_other_two)]
624     ExpectedOtherTwo {
625         leading_ellipsis: bool,
626         ty_or_sig: TyOrSig<'tcx>,
627         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
628         lifetime_1: usize,
629         lifetime_2: usize,
630     },
631     #[note(infer_actual_impl_expl_expected_other_any)]
632     ExpectedOtherAny {
633         leading_ellipsis: bool,
634         ty_or_sig: TyOrSig<'tcx>,
635         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
636         lifetime_1: usize,
637     },
638     #[note(infer_actual_impl_expl_expected_other_some)]
639     ExpectedOtherSome {
640         leading_ellipsis: bool,
641         ty_or_sig: TyOrSig<'tcx>,
642         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
643         lifetime_1: usize,
644     },
645     #[note(infer_actual_impl_expl_expected_other_nothing)]
646     ExpectedOtherNothing {
647         leading_ellipsis: bool,
648         ty_or_sig: TyOrSig<'tcx>,
649         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
650     },
651     #[note(infer_actual_impl_expl_but_actually_implements_trait)]
652     ButActuallyImplementsTrait {
653         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
654         has_lifetime: bool,
655         lifetime: usize,
656     },
657     #[note(infer_actual_impl_expl_but_actually_implemented_for_ty)]
658     ButActuallyImplementedForTy {
659         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
660         has_lifetime: bool,
661         lifetime: usize,
662         ty: String,
663     },
664     #[note(infer_actual_impl_expl_but_actually_ty_implements)]
665     ButActuallyTyImplements {
666         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
667         has_lifetime: bool,
668         lifetime: usize,
669         ty: String,
670     },
671 }
672 
673 pub enum ActualImplExpectedKind {
674     Signature,
675     Passive,
676     Other,
677 }
678 
679 pub enum ActualImplExpectedLifetimeKind {
680     Two,
681     Any,
682     Some,
683     Nothing,
684 }
685 
686 impl<'tcx> ActualImplExplNotes<'tcx> {
new_expected( kind: ActualImplExpectedKind, lt_kind: ActualImplExpectedLifetimeKind, leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, ) -> Self687     pub fn new_expected(
688         kind: ActualImplExpectedKind,
689         lt_kind: ActualImplExpectedLifetimeKind,
690         leading_ellipsis: bool,
691         ty_or_sig: TyOrSig<'tcx>,
692         trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
693         lifetime_1: usize,
694         lifetime_2: usize,
695     ) -> Self {
696         match (kind, lt_kind) {
697             (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => {
698                 Self::ExpectedSignatureTwo {
699                     leading_ellipsis,
700                     ty_or_sig,
701                     trait_path,
702                     lifetime_1,
703                     lifetime_2,
704                 }
705             }
706             (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => {
707                 Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
708             }
709             (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => {
710                 Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
711             }
712             (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => {
713                 Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path }
714             }
715             (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => {
716                 Self::ExpectedPassiveTwo {
717                     leading_ellipsis,
718                     ty_or_sig,
719                     trait_path,
720                     lifetime_1,
721                     lifetime_2,
722                 }
723             }
724             (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => {
725                 Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
726             }
727             (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => {
728                 Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
729             }
730             (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => {
731                 Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path }
732             }
733             (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => {
734                 Self::ExpectedOtherTwo {
735                     leading_ellipsis,
736                     ty_or_sig,
737                     trait_path,
738                     lifetime_1,
739                     lifetime_2,
740                 }
741             }
742             (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => {
743                 Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
744             }
745             (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => {
746                 Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
747             }
748             (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => {
749                 Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path }
750             }
751         }
752     }
753 }
754 
755 #[derive(Diagnostic)]
756 #[diag(infer_trait_placeholder_mismatch)]
757 pub struct TraitPlaceholderMismatch<'tcx> {
758     #[primary_span]
759     pub span: Span,
760     #[label(infer_label_satisfy)]
761     pub satisfy_span: Option<Span>,
762     #[label(infer_label_where)]
763     pub where_span: Option<Span>,
764     #[label(infer_label_dup)]
765     pub dup_span: Option<Span>,
766     pub def_id: String,
767     pub trait_def_id: String,
768 
769     #[subdiagnostic]
770     pub actual_impl_expl_notes: Vec<ActualImplExplNotes<'tcx>>,
771 }
772 
773 pub struct ConsiderBorrowingParamHelp {
774     pub spans: Vec<Span>,
775 }
776 
777 impl AddToDiagnostic for ConsiderBorrowingParamHelp {
add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F) where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,778     fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
779     where
780         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
781     {
782         let mut type_param_span: MultiSpan = self.spans.clone().into();
783         for &span in &self.spans {
784             // Seems like we can't call f() here as Into<DiagnosticMessage> is required
785             type_param_span.push_span_label(span, fluent::infer_tid_consider_borrowing);
786         }
787         let msg = f(diag, fluent::infer_tid_param_help.into());
788         diag.span_help(type_param_span, msg);
789     }
790 }
791 
792 #[derive(Subdiagnostic)]
793 #[help(infer_tid_rel_help)]
794 pub struct RelationshipHelp;
795 
796 #[derive(Diagnostic)]
797 #[diag(infer_trait_impl_diff)]
798 pub struct TraitImplDiff {
799     #[primary_span]
800     #[label(infer_found)]
801     pub sp: Span,
802     #[label(infer_expected)]
803     pub trait_sp: Span,
804     #[note(infer_expected_found)]
805     pub note: (),
806     #[subdiagnostic]
807     pub param_help: ConsiderBorrowingParamHelp,
808     #[subdiagnostic]
809     // Seems like subdiagnostics are always pushed to the end, so this one
810     // also has to be a subdiagnostic to maintain order.
811     pub rel_help: Option<RelationshipHelp>,
812     pub expected: String,
813     pub found: String,
814 }
815 
816 pub struct DynTraitConstraintSuggestion {
817     pub span: Span,
818     pub ident: Ident,
819 }
820 
821 impl AddToDiagnostic for DynTraitConstraintSuggestion {
add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F) where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,822     fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
823     where
824         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
825     {
826         let mut multi_span: MultiSpan = vec![self.span].into();
827         multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label);
828         multi_span.push_span_label(self.ident.span, fluent::infer_dtcs_introduces_requirement);
829         let msg = f(diag, fluent::infer_dtcs_has_req_note.into());
830         diag.span_note(multi_span, msg);
831         let msg = f(diag, fluent::infer_dtcs_suggestion.into());
832         diag.span_suggestion_verbose(
833             self.span.shrink_to_hi(),
834             msg,
835             " + '_",
836             Applicability::MaybeIncorrect,
837         );
838     }
839 }
840 
841 #[derive(Diagnostic)]
842 #[diag(infer_but_calling_introduces, code = "E0772")]
843 pub struct ButCallingIntroduces {
844     #[label(infer_label1)]
845     pub param_ty_span: Span,
846     #[primary_span]
847     #[label(infer_label2)]
848     pub cause_span: Span,
849 
850     pub has_param_name: bool,
851     pub param_name: String,
852     pub has_lifetime: bool,
853     pub lifetime: String,
854     pub assoc_item: Symbol,
855     pub has_impl_path: bool,
856     pub impl_path: String,
857 }
858 
859 pub struct ReqIntroducedLocations {
860     pub span: MultiSpan,
861     pub spans: Vec<Span>,
862     pub fn_decl_span: Span,
863     pub cause_span: Span,
864     pub add_label: bool,
865 }
866 
867 impl AddToDiagnostic for ReqIntroducedLocations {
add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, f: F) where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,868     fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, f: F)
869     where
870         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
871     {
872         for sp in self.spans {
873             self.span.push_span_label(sp, fluent::infer_ril_introduced_here);
874         }
875 
876         if self.add_label {
877             self.span.push_span_label(self.fn_decl_span, fluent::infer_ril_introduced_by);
878         }
879         self.span.push_span_label(self.cause_span, fluent::infer_ril_because_of);
880         let msg = f(diag, fluent::infer_ril_static_introduced_by.into());
881         diag.span_note(self.span, msg);
882     }
883 }
884 
885 pub struct MoreTargeted {
886     pub ident: Symbol,
887 }
888 
889 impl AddToDiagnostic for MoreTargeted {
add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _f: F) where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,890     fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _f: F)
891     where
892         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
893     {
894         diag.code(rustc_errors::error_code!(E0772));
895         diag.set_primary_message(fluent::infer_more_targeted);
896         diag.set_arg("ident", self.ident);
897     }
898 }
899 
900 #[derive(Diagnostic)]
901 #[diag(infer_but_needs_to_satisfy, code = "E0759")]
902 pub struct ButNeedsToSatisfy {
903     #[primary_span]
904     pub sp: Span,
905     #[label(infer_influencer)]
906     pub influencer_point: Span,
907     #[label(infer_used_here)]
908     pub spans: Vec<Span>,
909     #[label(infer_require)]
910     pub require_span_as_label: Option<Span>,
911     #[note(infer_require)]
912     pub require_span_as_note: Option<Span>,
913     #[note(infer_introduced_by_bound)]
914     pub bound: Option<Span>,
915 
916     #[subdiagnostic]
917     pub req_introduces_loc: Option<ReqIntroducedLocations>,
918 
919     pub has_param_name: bool,
920     pub param_name: String,
921     pub spans_empty: bool,
922     pub has_lifetime: bool,
923     pub lifetime: String,
924 }
925 
926 #[derive(Diagnostic)]
927 #[diag(infer_outlives_content, code = "E0312")]
928 pub struct OutlivesContent<'a> {
929     #[primary_span]
930     pub span: Span,
931     #[subdiagnostic]
932     pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
933 }
934 
935 #[derive(Diagnostic)]
936 #[diag(infer_outlives_bound, code = "E0476")]
937 pub struct OutlivesBound<'a> {
938     #[primary_span]
939     pub span: Span,
940     #[subdiagnostic]
941     pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
942 }
943 
944 #[derive(Diagnostic)]
945 #[diag(infer_fulfill_req_lifetime, code = "E0477")]
946 pub struct FulfillReqLifetime<'a> {
947     #[primary_span]
948     pub span: Span,
949     pub ty: Ty<'a>,
950     #[subdiagnostic]
951     pub note: Option<note_and_explain::RegionExplanation<'a>>,
952 }
953 
954 #[derive(Diagnostic)]
955 #[diag(infer_lf_bound_not_satisfied, code = "E0478")]
956 pub struct LfBoundNotSatisfied<'a> {
957     #[primary_span]
958     pub span: Span,
959     #[subdiagnostic]
960     pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
961 }
962 
963 #[derive(Diagnostic)]
964 #[diag(infer_ref_longer_than_data, code = "E0491")]
965 pub struct RefLongerThanData<'a> {
966     #[primary_span]
967     pub span: Span,
968     pub ty: Ty<'a>,
969     #[subdiagnostic]
970     pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
971 }
972 
973 #[derive(Subdiagnostic)]
974 pub enum WhereClauseSuggestions {
975     #[suggestion(
976         infer_where_remove,
977         code = "",
978         applicability = "machine-applicable",
979         style = "verbose"
980     )]
981     Remove {
982         #[primary_span]
983         span: Span,
984     },
985     #[suggestion(
986         infer_where_copy_predicates,
987         code = "{space}where {trait_predicates}",
988         applicability = "machine-applicable",
989         style = "verbose"
990     )]
991     CopyPredicates {
992         #[primary_span]
993         span: Span,
994         space: &'static str,
995         trait_predicates: String,
996     },
997 }
998 
999 #[derive(Subdiagnostic)]
1000 pub enum SuggestRemoveSemiOrReturnBinding {
1001     #[multipart_suggestion(infer_srs_remove_and_box, applicability = "machine-applicable")]
1002     RemoveAndBox {
1003         #[suggestion_part(code = "Box::new(")]
1004         first_lo: Span,
1005         #[suggestion_part(code = ")")]
1006         first_hi: Span,
1007         #[suggestion_part(code = "Box::new(")]
1008         second_lo: Span,
1009         #[suggestion_part(code = ")")]
1010         second_hi: Span,
1011         #[suggestion_part(code = "")]
1012         sp: Span,
1013     },
1014     #[suggestion(
1015         infer_srs_remove,
1016         style = "short",
1017         code = "",
1018         applicability = "machine-applicable"
1019     )]
1020     Remove {
1021         #[primary_span]
1022         sp: Span,
1023     },
1024     #[suggestion(
1025         infer_srs_add,
1026         style = "verbose",
1027         code = "{code}",
1028         applicability = "maybe-incorrect"
1029     )]
1030     Add {
1031         #[primary_span]
1032         sp: Span,
1033         code: String,
1034         ident: Ident,
1035     },
1036     #[note(infer_srs_add_one)]
1037     AddOne {
1038         #[primary_span]
1039         spans: MultiSpan,
1040     },
1041 }
1042 
1043 #[derive(Subdiagnostic)]
1044 pub enum ConsiderAddingAwait {
1045     #[help(infer_await_both_futures)]
1046     BothFuturesHelp,
1047     #[multipart_suggestion(infer_await_both_futures, applicability = "maybe-incorrect")]
1048     BothFuturesSugg {
1049         #[suggestion_part(code = ".await")]
1050         first: Span,
1051         #[suggestion_part(code = ".await")]
1052         second: Span,
1053     },
1054     #[suggestion(
1055         infer_await_future,
1056         code = ".await",
1057         style = "verbose",
1058         applicability = "maybe-incorrect"
1059     )]
1060     FutureSugg {
1061         #[primary_span]
1062         span: Span,
1063     },
1064     #[note(infer_await_note)]
1065     FutureSuggNote {
1066         #[primary_span]
1067         span: Span,
1068     },
1069     #[multipart_suggestion(
1070         infer_await_future,
1071         style = "verbose",
1072         applicability = "maybe-incorrect"
1073     )]
1074     FutureSuggMultiple {
1075         #[suggestion_part(code = ".await")]
1076         spans: Vec<Span>,
1077     },
1078 }
1079 
1080 #[derive(Diagnostic)]
1081 pub enum PlaceholderRelationLfNotSatisfied {
1082     #[diag(infer_lf_bound_not_satisfied)]
1083     HasBoth {
1084         #[primary_span]
1085         span: Span,
1086         #[note(infer_prlf_defined_with_sub)]
1087         sub_span: Span,
1088         #[note(infer_prlf_must_outlive_with_sup)]
1089         sup_span: Span,
1090         sub_symbol: Symbol,
1091         sup_symbol: Symbol,
1092         #[note(infer_prlf_known_limitation)]
1093         note: (),
1094     },
1095     #[diag(infer_lf_bound_not_satisfied)]
1096     HasSub {
1097         #[primary_span]
1098         span: Span,
1099         #[note(infer_prlf_defined_with_sub)]
1100         sub_span: Span,
1101         #[note(infer_prlf_must_outlive_without_sup)]
1102         sup_span: Span,
1103         sub_symbol: Symbol,
1104         #[note(infer_prlf_known_limitation)]
1105         note: (),
1106     },
1107     #[diag(infer_lf_bound_not_satisfied)]
1108     HasSup {
1109         #[primary_span]
1110         span: Span,
1111         #[note(infer_prlf_defined_without_sub)]
1112         sub_span: Span,
1113         #[note(infer_prlf_must_outlive_with_sup)]
1114         sup_span: Span,
1115         sup_symbol: Symbol,
1116         #[note(infer_prlf_known_limitation)]
1117         note: (),
1118     },
1119     #[diag(infer_lf_bound_not_satisfied)]
1120     HasNone {
1121         #[primary_span]
1122         span: Span,
1123         #[note(infer_prlf_defined_without_sub)]
1124         sub_span: Span,
1125         #[note(infer_prlf_must_outlive_without_sup)]
1126         sup_span: Span,
1127         #[note(infer_prlf_known_limitation)]
1128         note: (),
1129     },
1130     #[diag(infer_lf_bound_not_satisfied)]
1131     OnlyPrimarySpan {
1132         #[primary_span]
1133         span: Span,
1134         #[note(infer_prlf_known_limitation)]
1135         note: (),
1136     },
1137 }
1138 
1139 #[derive(Diagnostic)]
1140 #[diag(infer_opaque_captures_lifetime, code = "E0700")]
1141 pub struct OpaqueCapturesLifetime<'tcx> {
1142     #[primary_span]
1143     pub span: Span,
1144     #[label]
1145     pub opaque_ty_span: Span,
1146     pub opaque_ty: Ty<'tcx>,
1147 }
1148 
1149 #[derive(Subdiagnostic)]
1150 pub enum FunctionPointerSuggestion<'a> {
1151     #[suggestion(
1152         infer_fps_use_ref,
1153         code = "&{fn_name}",
1154         style = "verbose",
1155         applicability = "maybe-incorrect"
1156     )]
1157     UseRef {
1158         #[primary_span]
1159         span: Span,
1160         #[skip_arg]
1161         fn_name: String,
1162     },
1163     #[suggestion(
1164         infer_fps_remove_ref,
1165         code = "{fn_name}",
1166         style = "verbose",
1167         applicability = "maybe-incorrect"
1168     )]
1169     RemoveRef {
1170         #[primary_span]
1171         span: Span,
1172         #[skip_arg]
1173         fn_name: String,
1174     },
1175     #[suggestion(
1176         infer_fps_cast,
1177         code = "&({fn_name} as {sig})",
1178         style = "verbose",
1179         applicability = "maybe-incorrect"
1180     )]
1181     CastRef {
1182         #[primary_span]
1183         span: Span,
1184         #[skip_arg]
1185         fn_name: String,
1186         #[skip_arg]
1187         sig: Binder<'a, FnSig<'a>>,
1188     },
1189     #[suggestion(
1190         infer_fps_cast,
1191         code = "{fn_name} as {sig}",
1192         style = "verbose",
1193         applicability = "maybe-incorrect"
1194     )]
1195     Cast {
1196         #[primary_span]
1197         span: Span,
1198         #[skip_arg]
1199         fn_name: String,
1200         #[skip_arg]
1201         sig: Binder<'a, FnSig<'a>>,
1202     },
1203     #[suggestion(
1204         infer_fps_cast_both,
1205         code = "{fn_name} as {found_sig}",
1206         style = "hidden",
1207         applicability = "maybe-incorrect"
1208     )]
1209     CastBoth {
1210         #[primary_span]
1211         span: Span,
1212         #[skip_arg]
1213         fn_name: String,
1214         #[skip_arg]
1215         found_sig: Binder<'a, FnSig<'a>>,
1216         expected_sig: Binder<'a, FnSig<'a>>,
1217     },
1218     #[suggestion(
1219         infer_fps_cast_both,
1220         code = "&({fn_name} as {found_sig})",
1221         style = "hidden",
1222         applicability = "maybe-incorrect"
1223     )]
1224     CastBothRef {
1225         #[primary_span]
1226         span: Span,
1227         #[skip_arg]
1228         fn_name: String,
1229         #[skip_arg]
1230         found_sig: Binder<'a, FnSig<'a>>,
1231         expected_sig: Binder<'a, FnSig<'a>>,
1232     },
1233 }
1234 
1235 #[derive(Subdiagnostic)]
1236 #[note(infer_fps_items_are_distinct)]
1237 pub struct FnItemsAreDistinct;
1238 
1239 #[derive(Subdiagnostic)]
1240 #[note(infer_fn_uniq_types)]
1241 pub struct FnUniqTypes;
1242 
1243 #[derive(Subdiagnostic)]
1244 #[help(infer_fn_consider_casting)]
1245 pub struct FnConsiderCasting {
1246     pub casting: String,
1247 }
1248 
1249 #[derive(Subdiagnostic)]
1250 pub enum SuggestAccessingField<'a> {
1251     #[suggestion(
1252         infer_suggest_accessing_field,
1253         code = "{snippet}.{name}",
1254         applicability = "maybe-incorrect"
1255     )]
1256     Safe {
1257         #[primary_span]
1258         span: Span,
1259         snippet: String,
1260         name: Symbol,
1261         ty: Ty<'a>,
1262     },
1263     #[suggestion(
1264         infer_suggest_accessing_field,
1265         code = "unsafe {{ {snippet}.{name} }}",
1266         applicability = "maybe-incorrect"
1267     )]
1268     Unsafe {
1269         #[primary_span]
1270         span: Span,
1271         snippet: String,
1272         name: Symbol,
1273         ty: Ty<'a>,
1274     },
1275 }
1276 
1277 #[derive(Subdiagnostic)]
1278 pub enum SuggestBoxingForReturnImplTrait {
1279     #[multipart_suggestion(infer_sbfrit_change_return_type, applicability = "maybe-incorrect")]
1280     ChangeReturnType {
1281         #[suggestion_part(code = "Box<dyn")]
1282         start_sp: Span,
1283         #[suggestion_part(code = ">")]
1284         end_sp: Span,
1285     },
1286     #[multipart_suggestion(infer_sbfrit_box_return_expr, applicability = "maybe-incorrect")]
1287     BoxReturnExpr {
1288         #[suggestion_part(code = "Box::new(")]
1289         starts: Vec<Span>,
1290         #[suggestion_part(code = ")")]
1291         ends: Vec<Span>,
1292     },
1293 }
1294 
1295 #[derive(Subdiagnostic)]
1296 #[multipart_suggestion(infer_stp_wrap_one, applicability = "maybe-incorrect")]
1297 pub struct SuggestTuplePatternOne {
1298     pub variant: String,
1299     #[suggestion_part(code = "{variant}(")]
1300     pub span_low: Span,
1301     #[suggestion_part(code = ")")]
1302     pub span_high: Span,
1303 }
1304 
1305 pub struct SuggestTuplePatternMany {
1306     pub path: String,
1307     pub cause_span: Span,
1308     pub compatible_variants: Vec<String>,
1309 }
1310 
1311 impl AddToDiagnostic for SuggestTuplePatternMany {
add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, f: F) where F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,1312     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, f: F)
1313     where
1314         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
1315     {
1316         diag.set_arg("path", self.path);
1317         let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into());
1318         diag.multipart_suggestions(
1319             message,
1320             self.compatible_variants.into_iter().map(|variant| {
1321                 vec![
1322                     (self.cause_span.shrink_to_lo(), format!("{}(", variant)),
1323                     (self.cause_span.shrink_to_hi(), ")".to_string()),
1324                 ]
1325             }),
1326             rustc_errors::Applicability::MaybeIncorrect,
1327         );
1328     }
1329 }
1330 
1331 #[derive(Subdiagnostic)]
1332 pub enum TypeErrorAdditionalDiags {
1333     #[suggestion(
1334         infer_meant_byte_literal,
1335         code = "b'{code}'",
1336         applicability = "machine-applicable"
1337     )]
1338     MeantByteLiteral {
1339         #[primary_span]
1340         span: Span,
1341         code: String,
1342     },
1343     #[suggestion(
1344         infer_meant_char_literal,
1345         code = "'{code}'",
1346         applicability = "machine-applicable"
1347     )]
1348     MeantCharLiteral {
1349         #[primary_span]
1350         span: Span,
1351         code: String,
1352     },
1353     #[suggestion(
1354         infer_meant_str_literal,
1355         code = "\"{code}\"",
1356         applicability = "machine-applicable"
1357     )]
1358     MeantStrLiteral {
1359         #[primary_span]
1360         span: Span,
1361         code: String,
1362     },
1363     #[suggestion(
1364         infer_consider_specifying_length,
1365         code = "{length}",
1366         applicability = "maybe-incorrect"
1367     )]
1368     ConsiderSpecifyingLength {
1369         #[primary_span]
1370         span: Span,
1371         length: u64,
1372     },
1373     #[note(infer_try_cannot_convert)]
1374     TryCannotConvert { found: String, expected: String },
1375     #[suggestion(infer_tuple_trailing_comma, code = ",", applicability = "machine-applicable")]
1376     TupleOnlyComma {
1377         #[primary_span]
1378         span: Span,
1379     },
1380     #[multipart_suggestion(infer_tuple_trailing_comma, applicability = "machine-applicable")]
1381     TupleAlsoParentheses {
1382         #[suggestion_part(code = "(")]
1383         span_low: Span,
1384         #[suggestion_part(code = ",)")]
1385         span_high: Span,
1386     },
1387     #[suggestion(
1388         infer_suggest_add_let_for_letchains,
1389         style = "verbose",
1390         applicability = "machine-applicable",
1391         code = "let "
1392     )]
1393     AddLetForLetChains {
1394         #[primary_span]
1395         span: Span,
1396     },
1397 }
1398 
1399 #[derive(Diagnostic)]
1400 pub enum ObligationCauseFailureCode {
1401     #[diag(infer_oc_method_compat, code = "E0308")]
1402     MethodCompat {
1403         #[primary_span]
1404         span: Span,
1405         #[subdiagnostic]
1406         subdiags: Vec<TypeErrorAdditionalDiags>,
1407     },
1408     #[diag(infer_oc_type_compat, code = "E0308")]
1409     TypeCompat {
1410         #[primary_span]
1411         span: Span,
1412         #[subdiagnostic]
1413         subdiags: Vec<TypeErrorAdditionalDiags>,
1414     },
1415     #[diag(infer_oc_const_compat, code = "E0308")]
1416     ConstCompat {
1417         #[primary_span]
1418         span: Span,
1419         #[subdiagnostic]
1420         subdiags: Vec<TypeErrorAdditionalDiags>,
1421     },
1422     #[diag(infer_oc_try_compat, code = "E0308")]
1423     TryCompat {
1424         #[primary_span]
1425         span: Span,
1426         #[subdiagnostic]
1427         subdiags: Vec<TypeErrorAdditionalDiags>,
1428     },
1429     #[diag(infer_oc_match_compat, code = "E0308")]
1430     MatchCompat {
1431         #[primary_span]
1432         span: Span,
1433         #[subdiagnostic]
1434         subdiags: Vec<TypeErrorAdditionalDiags>,
1435     },
1436     #[diag(infer_oc_if_else_different, code = "E0308")]
1437     IfElseDifferent {
1438         #[primary_span]
1439         span: Span,
1440         #[subdiagnostic]
1441         subdiags: Vec<TypeErrorAdditionalDiags>,
1442     },
1443     #[diag(infer_oc_no_else, code = "E0317")]
1444     NoElse {
1445         #[primary_span]
1446         span: Span,
1447     },
1448     #[diag(infer_oc_no_diverge, code = "E0308")]
1449     NoDiverge {
1450         #[primary_span]
1451         span: Span,
1452         #[subdiagnostic]
1453         subdiags: Vec<TypeErrorAdditionalDiags>,
1454     },
1455     #[diag(infer_oc_fn_main_correct_type, code = "E0580")]
1456     FnMainCorrectType {
1457         #[primary_span]
1458         span: Span,
1459     },
1460     #[diag(infer_oc_fn_start_correct_type, code = "E0308")]
1461     FnStartCorrectType {
1462         #[primary_span]
1463         span: Span,
1464         #[subdiagnostic]
1465         subdiags: Vec<TypeErrorAdditionalDiags>,
1466     },
1467     #[diag(infer_oc_intrinsic_correct_type, code = "E0308")]
1468     IntrinsicCorrectType {
1469         #[primary_span]
1470         span: Span,
1471         #[subdiagnostic]
1472         subdiags: Vec<TypeErrorAdditionalDiags>,
1473     },
1474     #[diag(infer_oc_method_correct_type, code = "E0308")]
1475     MethodCorrectType {
1476         #[primary_span]
1477         span: Span,
1478         #[subdiagnostic]
1479         subdiags: Vec<TypeErrorAdditionalDiags>,
1480     },
1481     #[diag(infer_oc_closure_selfref, code = "E0644")]
1482     ClosureSelfref {
1483         #[primary_span]
1484         span: Span,
1485     },
1486     #[diag(infer_oc_cant_coerce, code = "E0308")]
1487     CantCoerce {
1488         #[primary_span]
1489         span: Span,
1490         #[subdiagnostic]
1491         subdiags: Vec<TypeErrorAdditionalDiags>,
1492     },
1493     #[diag(infer_oc_generic, code = "E0308")]
1494     Generic {
1495         #[primary_span]
1496         span: Span,
1497         #[subdiagnostic]
1498         subdiags: Vec<TypeErrorAdditionalDiags>,
1499     },
1500 }
1501