1use std::path::PathBuf;
2
3use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
4use rustc_errors::codes::*;
5use rustc_errors::{
6 Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic,
7 EmissionGuarantee, IntoDiagArg, Level, MultiSpan, SubdiagMessageOp, Subdiagnostic,
8};
9use rustc_hir::def::DefKind;
10use rustc_hir::def_id::{DefId, LocalDefId};
11use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty};
12use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, Node};
13use rustc_macros::{Diagnostic, Subdiagnostic};
14use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
15use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, Region, Ty, TyCtxt};
16use rustc_span::{BytePos, Ident, Span, Symbol, kw};
17
18use crate::error_reporting::infer::ObligationCauseAsDiagArg;
19use crate::error_reporting::infer::need_type_info::UnderspecifiedArgKind;
20use crate::error_reporting::infer::nice_region_error::placeholder_error::Highlighted;
21use crate::fluent_generated as fluent;
22
23pub mod note_and_explain;
24
25#[derive(Diagnostic)]
26#[diag(trait_selection_unable_to_construct_constant_value)]
27pub struct UnableToConstructConstantValue<'a> {
28 #[primary_span]
29 pub span: Span,
30 pub unevaluated: ty::UnevaluatedConst<'a>,
31}
32
33#[derive(Diagnostic)]
34#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = E0232)]
35pub struct EmptyOnClauseInOnUnimplemented {
36 #[primary_span]
37 #[label]
38 pub span: Span,
39}
40
41#[derive(Diagnostic)]
42#[diag(trait_selection_invalid_on_clause_in_rustc_on_unimplemented, code = E0232)]
43pub struct InvalidOnClauseInOnUnimplemented {
44 #[primary_span]
45 #[label]
46 pub span: Span,
47}
48
49#[derive(Diagnostic)]
50#[diag(trait_selection_no_value_in_rustc_on_unimplemented, code = E0232)]
51#[note]
52pub struct NoValueInOnUnimplemented {
53 #[primary_span]
54 #[label]
55 pub span: Span,
56}
57
58pub struct NegativePositiveConflict<'tcx> {
59 pub impl_span: Span,
60 pub trait_desc: ty::TraitRef<'tcx>,
61 pub self_ty: Option<Ty<'tcx>>,
62 pub negative_impl_span: Result<Span, Symbol>,
63 pub positive_impl_span: Result<Span, Symbol>,
64}
65
66impl<G: EmissionGuarantee> Diagnostic<'_, G> for NegativePositiveConflict<'_> {
67 #[track_caller]
68 fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
69 let mut diag = Diag::new(dcx, level, fluent::trait_selection_negative_positive_conflict);
70 diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string());
71 diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string()));
72 diag.span(self.impl_span);
73 diag.code(E0751);
74 match self.negative_impl_span {
75 Ok(span) => {
76 diag.span_label(span, fluent::trait_selection_negative_implementation_here);
77 }
78 Err(cname) => {
79 diag.note(fluent::trait_selection_negative_implementation_in_crate);
80 diag.arg("negative_impl_cname", cname.to_string());
81 }
82 }
83 match self.positive_impl_span {
84 Ok(span) => {
85 diag.span_label(span, fluent::trait_selection_positive_implementation_here);
86 }
87 Err(cname) => {
88 diag.note(fluent::trait_selection_positive_implementation_in_crate);
89 diag.arg("positive_impl_cname", cname.to_string());
90 }
91 }
92 diag
93 }
94}
95
96#[derive(Diagnostic)]
97#[diag(trait_selection_inherent_projection_normalization_overflow)]
98pub struct InherentProjectionNormalizationOverflow {
99 #[primary_span]
100 pub span: Span,
101 pub ty: String,
102}
103
104pub enum AdjustSignatureBorrow {
105 Borrow { to_borrow: Vec<(Span, String)> },
106 RemoveBorrow { remove_borrow: Vec<(Span, String)> },
107}
108
109impl Subdiagnostic for AdjustSignatureBorrow {
110 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
111 self,
112 diag: &mut Diag<'_, G>,
113 _f: &F,
114 ) {
115 match self {
116 AdjustSignatureBorrow::Borrow { to_borrow } => {
117 diag.arg("len", to_borrow.len());
118 diag.multipart_suggestion_verbose(
119 fluent::trait_selection_adjust_signature_borrow,
120 to_borrow,
121 Applicability::MaybeIncorrect,
122 );
123 }
124 AdjustSignatureBorrow::RemoveBorrow { remove_borrow } => {
125 diag.arg("len", remove_borrow.len());
126 diag.multipart_suggestion_verbose(
127 fluent::trait_selection_adjust_signature_remove_borrow,
128 remove_borrow,
129 Applicability::MaybeIncorrect,
130 );
131 }
132 }
133 }
134}
135
136#[derive(Diagnostic)]
137#[diag(trait_selection_closure_kind_mismatch, code = E0525)]
138pub struct ClosureKindMismatch {
139 #[primary_span]
140 #[label]
141 pub closure_span: Span,
142 pub expected: ClosureKind,
143 pub found: ClosureKind,
144 #[label(trait_selection_closure_kind_requirement)]
145 pub cause_span: Span,
146
147 pub trait_prefix: &'static str,
148
149 #[subdiagnostic]
150 pub fn_once_label: Option<ClosureFnOnceLabel>,
151
152 #[subdiagnostic]
153 pub fn_mut_label: Option<ClosureFnMutLabel>,
154}
155
156#[derive(Subdiagnostic)]
157#[label(trait_selection_closure_fn_once_label)]
158pub struct ClosureFnOnceLabel {
159 #[primary_span]
160 pub span: Span,
161 pub place: String,
162}
163
164#[derive(Subdiagnostic)]
165#[label(trait_selection_closure_fn_mut_label)]
166pub struct ClosureFnMutLabel {
167 #[primary_span]
168 pub span: Span,
169 pub place: String,
170}
171
172#[derive(Diagnostic)]
173#[diag(trait_selection_async_closure_not_fn)]
174pub(crate) struct AsyncClosureNotFn {
175 #[primary_span]
176 pub span: Span,
177 pub kind: &'static str,
178}
179
180#[derive(Diagnostic)]
181#[diag(trait_selection_type_annotations_needed, code = E0282)]
182pub struct AnnotationRequired<'a> {
183 #[primary_span]
184 pub span: Span,
185 pub source_kind: &'static str,
186 pub source_name: &'a str,
187 #[label]
188 pub failure_span: Option<Span>,
189 #[subdiagnostic]
190 pub bad_label: Option<InferenceBadError<'a>>,
191 #[subdiagnostic]
192 pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
193 #[subdiagnostic]
194 pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
195 #[note(trait_selection_full_type_written)]
196 pub was_written: bool,
197 pub path: PathBuf,
198 #[note(trait_selection_type_annotations_needed_error_time)]
199 pub time_version: bool,
200}
201
202#[derive(Diagnostic)]
204#[diag(trait_selection_type_annotations_needed, code = E0283)]
205pub struct AmbiguousImpl<'a> {
206 #[primary_span]
207 pub span: Span,
208 pub source_kind: &'static str,
209 pub source_name: &'a str,
210 #[label]
211 pub failure_span: Option<Span>,
212 #[subdiagnostic]
213 pub bad_label: Option<InferenceBadError<'a>>,
214 #[subdiagnostic]
215 pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
216 #[subdiagnostic]
217 pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
218 #[note(trait_selection_full_type_written)]
219 pub was_written: bool,
220 pub path: PathBuf,
221}
222
223#[derive(Diagnostic)]
225#[diag(trait_selection_type_annotations_needed, code = E0284)]
226pub struct AmbiguousReturn<'a> {
227 #[primary_span]
228 pub span: Span,
229 pub source_kind: &'static str,
230 pub source_name: &'a str,
231 #[label]
232 pub failure_span: Option<Span>,
233 #[subdiagnostic]
234 pub bad_label: Option<InferenceBadError<'a>>,
235 #[subdiagnostic]
236 pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
237 #[subdiagnostic]
238 pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
239 #[note(trait_selection_full_type_written)]
240 pub was_written: bool,
241 pub path: PathBuf,
242}
243
244#[derive(Subdiagnostic)]
246#[label(trait_selection_label_bad)]
247pub struct InferenceBadError<'a> {
248 #[primary_span]
249 pub span: Span,
250 pub bad_kind: &'static str,
251 pub prefix_kind: UnderspecifiedArgKind,
252 pub has_parent: bool,
253 pub prefix: &'a str,
254 pub parent_prefix: &'a str,
255 pub parent_name: String,
256 pub name: String,
257}
258
259#[derive(Subdiagnostic)]
260pub enum SourceKindSubdiag<'a> {
261 #[suggestion(
262 trait_selection_source_kind_subdiag_let,
263 style = "verbose",
264 code = ": {type_name}",
265 applicability = "has-placeholders"
266 )]
267 LetLike {
268 #[primary_span]
269 span: Span,
270 name: String,
271 type_name: String,
272 kind: &'static str,
273 x_kind: &'static str,
274 prefix_kind: UnderspecifiedArgKind,
275 prefix: &'a str,
276 arg_name: String,
277 },
278 #[label(trait_selection_source_kind_subdiag_generic_label)]
279 GenericLabel {
280 #[primary_span]
281 span: Span,
282 is_type: bool,
283 param_name: String,
284 parent_exists: bool,
285 parent_prefix: String,
286 parent_name: String,
287 },
288 #[suggestion(
289 trait_selection_source_kind_subdiag_generic_suggestion,
290 style = "verbose",
291 code = "::<{args}>",
292 applicability = "has-placeholders"
293 )]
294 GenericSuggestion {
295 #[primary_span]
296 span: Span,
297 arg_count: usize,
298 args: String,
299 },
300}
301
302#[derive(Subdiagnostic)]
303pub enum SourceKindMultiSuggestion<'a> {
304 #[multipart_suggestion(
305 trait_selection_source_kind_fully_qualified,
306 style = "verbose",
307 applicability = "has-placeholders"
308 )]
309 FullyQualified {
310 #[suggestion_part(code = "{def_path}({adjustment}")]
311 span_lo: Span,
312 #[suggestion_part(code = "{successor_pos}")]
313 span_hi: Span,
314 def_path: String,
315 adjustment: &'a str,
316 successor_pos: &'a str,
317 },
318 #[multipart_suggestion(
319 trait_selection_source_kind_closure_return,
320 style = "verbose",
321 applicability = "has-placeholders"
322 )]
323 ClosureReturn {
324 #[suggestion_part(code = "{start_span_code}")]
325 start_span: Span,
326 start_span_code: String,
327 #[suggestion_part(code = " }}")]
328 end_span: Option<Span>,
329 },
330}
331
332impl<'a> SourceKindMultiSuggestion<'a> {
333 pub fn new_fully_qualified(
334 span: Span,
335 def_path: String,
336 adjustment: &'a str,
337 successor: (&'a str, BytePos),
338 ) -> Self {
339 Self::FullyQualified {
340 span_lo: span.shrink_to_lo(),
341 span_hi: span.shrink_to_hi().with_hi(successor.1),
342 def_path,
343 adjustment,
344 successor_pos: successor.0,
345 }
346 }
347
348 pub fn new_closure_return(
349 ty_info: String,
350 data: &'a FnRetTy<'a>,
351 should_wrap_expr: Option<Span>,
352 ) -> Self {
353 let arrow = match data {
354 FnRetTy::DefaultReturn(_) => " -> ",
355 _ => "",
356 };
357 let (start_span, start_span_code, end_span) = match should_wrap_expr {
358 Some(end_span) => (data.span(), format!("{arrow}{ty_info} {{"), Some(end_span)),
359 None => (data.span(), format!("{arrow}{ty_info}"), None),
360 };
361 Self::ClosureReturn { start_span, start_span_code, end_span }
362 }
363}
364
365pub enum RegionOriginNote<'a> {
366 Plain {
367 span: Span,
368 msg: DiagMessage,
369 },
370 WithName {
371 span: Span,
372 msg: DiagMessage,
373 name: &'a str,
374 continues: bool,
375 },
376 WithRequirement {
377 span: Span,
378 requirement: ObligationCauseAsDiagArg<'a>,
379 expected_found: Option<(DiagStyledString, DiagStyledString)>,
380 },
381}
382
383impl Subdiagnostic for RegionOriginNote<'_> {
384 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
385 self,
386 diag: &mut Diag<'_, G>,
387 _f: &F,
388 ) {
389 let mut label_or_note = |span, msg: DiagMessage| {
390 let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
391 let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
392 let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span);
393 if span_is_primary && sub_count == 0 && expanded_sub_count == 0 {
394 diag.span_label(span, msg);
395 } else if span_is_primary && expanded_sub_count == 0 {
396 diag.note(msg);
397 } else {
398 diag.span_note(span, msg);
399 }
400 };
401 match self {
402 RegionOriginNote::Plain { span, msg } => {
403 label_or_note(span, msg);
404 }
405 RegionOriginNote::WithName { span, msg, name, continues } => {
406 label_or_note(span, msg);
407 diag.arg("name", name);
408 diag.arg("continues", continues);
409 }
410 RegionOriginNote::WithRequirement {
411 span,
412 requirement,
413 expected_found: Some((expected, found)),
414 } => {
415 label_or_note(span, fluent::trait_selection_subtype);
416 diag.arg("requirement", requirement);
417
418 diag.note_expected_found(&"", expected, &"", found);
419 }
420 RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => {
421 label_or_note(span, fluent::trait_selection_subtype_2);
425 diag.arg("requirement", requirement);
426 }
427 };
428 }
429}
430
431pub enum LifetimeMismatchLabels {
432 InRet {
433 param_span: Span,
434 ret_span: Span,
435 span: Span,
436 label_var1: Option<Ident>,
437 },
438 Normal {
439 hir_equal: bool,
440 ty_sup: Span,
441 ty_sub: Span,
442 span: Span,
443 sup: Option<Ident>,
444 sub: Option<Ident>,
445 },
446}
447
448impl Subdiagnostic for LifetimeMismatchLabels {
449 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
450 self,
451 diag: &mut Diag<'_, G>,
452 _f: &F,
453 ) {
454 match self {
455 LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
456 diag.span_label(param_span, fluent::trait_selection_declared_different);
457 diag.span_label(ret_span, fluent::trait_selection_nothing);
458 diag.span_label(span, fluent::trait_selection_data_returned);
459 diag.arg("label_var1_exists", label_var1.is_some());
460 diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
461 }
462 LifetimeMismatchLabels::Normal {
463 hir_equal,
464 ty_sup,
465 ty_sub,
466 span,
467 sup: label_var1,
468 sub: label_var2,
469 } => {
470 if hir_equal {
471 diag.span_label(ty_sup, fluent::trait_selection_declared_multiple);
472 diag.span_label(ty_sub, fluent::trait_selection_nothing);
473 diag.span_label(span, fluent::trait_selection_data_lifetime_flow);
474 } else {
475 diag.span_label(ty_sup, fluent::trait_selection_types_declared_different);
476 diag.span_label(ty_sub, fluent::trait_selection_nothing);
477 diag.span_label(span, fluent::trait_selection_data_flows);
478 diag.arg("label_var1_exists", label_var1.is_some());
479 diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
480 diag.arg("label_var2_exists", label_var2.is_some());
481 diag.arg("label_var2", label_var2.map(|x| x.to_string()).unwrap_or_default());
482 }
483 }
484 }
485 }
486}
487
488pub struct AddLifetimeParamsSuggestion<'a> {
489 pub tcx: TyCtxt<'a>,
490 pub generic_param_scope: LocalDefId,
491 pub sub: Region<'a>,
492 pub ty_sup: &'a hir::Ty<'a>,
493 pub ty_sub: &'a hir::Ty<'a>,
494 pub add_note: bool,
495}
496
497impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
498 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
499 self,
500 diag: &mut Diag<'_, G>,
501 _f: &F,
502 ) {
503 let mut mk_suggestion = || {
504 let Some(anon_reg) = self.tcx.is_suitable_region(self.generic_param_scope, self.sub)
505 else {
506 return false;
507 };
508
509 let node = self.tcx.hir_node_by_def_id(anon_reg.scope);
510 let is_impl = matches!(&node, hir::Node::ImplItem(_));
511 let (generics, parent_generics) = match node {
512 hir::Node::Item(&hir::Item {
513 kind: hir::ItemKind::Fn { ref generics, .. },
514 ..
515 })
516 | hir::Node::TraitItem(&hir::TraitItem { ref generics, .. })
517 | hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => (
518 generics,
519 match self.tcx.parent_hir_node(self.tcx.local_def_id_to_hir_id(anon_reg.scope))
520 {
521 hir::Node::Item(hir::Item {
522 kind: hir::ItemKind::Trait(_, _, ref generics, ..),
523 ..
524 })
525 | hir::Node::Item(hir::Item {
526 kind: hir::ItemKind::Impl(hir::Impl { ref generics, .. }),
527 ..
528 }) => Some(generics),
529 _ => None,
530 },
531 ),
532 _ => return false,
533 };
534
535 let suggestion_param_name = generics
536 .params
537 .iter()
538 .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
539 .map(|p| p.name.ident().name)
540 .find(|i| *i != kw::UnderscoreLifetime);
541 let introduce_new = suggestion_param_name.is_none();
542
543 let mut default = "'a".to_string();
544 if let Some(parent_generics) = parent_generics {
545 let used: FxHashSet<_> = parent_generics
546 .params
547 .iter()
548 .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
549 .map(|p| p.name.ident().name)
550 .filter(|i| *i != kw::UnderscoreLifetime)
551 .map(|l| l.to_string())
552 .collect();
553 if let Some(lt) =
554 ('a'..='z').map(|it| format!("'{it}")).find(|it| !used.contains(it))
555 {
556 default = lt;
561 }
562 }
563 let suggestion_param_name =
564 suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| default);
565
566 struct ImplicitLifetimeFinder {
567 suggestions: Vec<(Span, String)>,
568 suggestion_param_name: String,
569 }
570
571 impl<'v> Visitor<'v> for ImplicitLifetimeFinder {
572 fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
573 let make_suggestion = |ident: Ident| {
574 if ident.name == kw::Empty && ident.span.is_empty() {
575 format!("{}, ", self.suggestion_param_name)
576 } else if ident.name == kw::UnderscoreLifetime && ident.span.is_empty() {
577 format!("{} ", self.suggestion_param_name)
578 } else {
579 self.suggestion_param_name.clone()
580 }
581 };
582 match ty.kind {
583 hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
584 for segment in path.segments {
585 if let Some(args) = segment.args {
586 if args.args.iter().all(|arg| {
587 matches!(
588 arg,
589 hir::GenericArg::Lifetime(lifetime)
590 if lifetime.ident.name == kw::Empty
591 )
592 }) {
593 self.suggestions.push((
594 segment.ident.span.shrink_to_hi(),
595 format!(
596 "<{}>",
597 args.args
598 .iter()
599 .map(|_| self.suggestion_param_name.clone())
600 .collect::<Vec<_>>()
601 .join(", ")
602 ),
603 ));
604 } else {
605 for arg in args.args {
606 if let hir::GenericArg::Lifetime(lifetime) = arg
607 && lifetime.is_anonymous()
608 {
609 self.suggestions.push((
610 lifetime.ident.span,
611 make_suggestion(lifetime.ident),
612 ));
613 }
614 }
615 }
616 }
617 }
618 }
619 hir::TyKind::Ref(lifetime, ..) if lifetime.is_anonymous() => {
620 self.suggestions
621 .push((lifetime.ident.span, make_suggestion(lifetime.ident)));
622 }
623 _ => {}
624 }
625 walk_ty(self, ty);
626 }
627 }
628 let mut visitor = ImplicitLifetimeFinder {
629 suggestions: vec![],
630 suggestion_param_name: suggestion_param_name.clone(),
631 };
632 if let Some(fn_decl) = node.fn_decl()
633 && let hir::FnRetTy::Return(ty) = fn_decl.output
634 {
635 visitor.visit_ty_unambig(ty);
636 }
637 if visitor.suggestions.is_empty() {
638 visitor.visit_ty_unambig(self.ty_sup);
643 }
644 visitor.visit_ty_unambig(self.ty_sub);
645 if visitor.suggestions.is_empty() {
646 return false;
647 }
648 if introduce_new {
649 let new_param_suggestion = if let Some(first) =
650 generics.params.iter().find(|p| !p.name.ident().span.is_empty())
651 {
652 (first.span.shrink_to_lo(), format!("{suggestion_param_name}, "))
653 } else {
654 (generics.span, format!("<{suggestion_param_name}>"))
655 };
656
657 visitor.suggestions.push(new_param_suggestion);
658 }
659 diag.multipart_suggestion_verbose(
660 fluent::trait_selection_lifetime_param_suggestion,
661 visitor.suggestions,
662 Applicability::MaybeIncorrect,
663 );
664 diag.arg("is_impl", is_impl);
665 diag.arg("is_reuse", !introduce_new);
666
667 true
668 };
669 if mk_suggestion() && self.add_note {
670 diag.note(fluent::trait_selection_lifetime_param_suggestion_elided);
671 }
672 }
673}
674
675#[derive(Diagnostic)]
676#[diag(trait_selection_lifetime_mismatch, code = E0623)]
677pub struct LifetimeMismatch<'a> {
678 #[primary_span]
679 pub span: Span,
680 #[subdiagnostic]
681 pub labels: LifetimeMismatchLabels,
682 #[subdiagnostic]
683 pub suggestion: AddLifetimeParamsSuggestion<'a>,
684}
685
686pub struct IntroducesStaticBecauseUnmetLifetimeReq {
687 pub unmet_requirements: MultiSpan,
688 pub binding_span: Span,
689}
690
691impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
692 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
693 mut self,
694 diag: &mut Diag<'_, G>,
695 _f: &F,
696 ) {
697 self.unmet_requirements
698 .push_span_label(self.binding_span, fluent::trait_selection_msl_introduces_static);
699 diag.span_note(self.unmet_requirements, fluent::trait_selection_msl_unmet_req);
700 }
701}
702
703#[derive(Subdiagnostic)]
705pub enum DoesNotOutliveStaticFromImpl {
706 #[note(trait_selection_does_not_outlive_static_from_impl)]
707 Spanned {
708 #[primary_span]
709 span: Span,
710 },
711 #[note(trait_selection_does_not_outlive_static_from_impl)]
712 Unspanned,
713}
714
715#[derive(Subdiagnostic)]
716pub enum ImplicitStaticLifetimeSubdiag {
717 #[note(trait_selection_implicit_static_lifetime_note)]
718 Note {
719 #[primary_span]
720 span: Span,
721 },
722 #[suggestion(
723 trait_selection_implicit_static_lifetime_suggestion,
724 style = "verbose",
725 code = " + '_",
726 applicability = "maybe-incorrect"
727 )]
728 Sugg {
729 #[primary_span]
730 span: Span,
731 },
732}
733
734#[derive(Diagnostic)]
735#[diag(trait_selection_mismatched_static_lifetime)]
736pub struct MismatchedStaticLifetime<'a> {
737 #[primary_span]
738 pub cause_span: Span,
739 #[subdiagnostic]
740 pub unmet_lifetime_reqs: IntroducesStaticBecauseUnmetLifetimeReq,
741 #[subdiagnostic]
742 pub expl: Option<note_and_explain::RegionExplanation<'a>>,
743 #[subdiagnostic]
744 pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl,
745 #[subdiagnostic]
746 pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
747}
748
749#[derive(Diagnostic)]
750pub enum ExplicitLifetimeRequired<'a> {
751 #[diag(trait_selection_explicit_lifetime_required_with_ident, code = E0621)]
752 WithIdent {
753 #[primary_span]
754 #[label]
755 span: Span,
756 simple_ident: Ident,
757 named: String,
758 #[suggestion(
759 trait_selection_explicit_lifetime_required_sugg_with_ident,
760 code = "{new_ty}",
761 applicability = "unspecified"
762 )]
763 new_ty_span: Span,
764 #[skip_arg]
765 new_ty: Ty<'a>,
766 },
767 #[diag(trait_selection_explicit_lifetime_required_with_param_type, code = E0621)]
768 WithParamType {
769 #[primary_span]
770 #[label]
771 span: Span,
772 named: String,
773 #[suggestion(
774 trait_selection_explicit_lifetime_required_sugg_with_param_type,
775 code = "{new_ty}",
776 applicability = "unspecified"
777 )]
778 new_ty_span: Span,
779 #[skip_arg]
780 new_ty: Ty<'a>,
781 },
782}
783
784pub enum TyOrSig<'tcx> {
785 Ty(Highlighted<'tcx, Ty<'tcx>>),
786 ClosureSig(Highlighted<'tcx, Binder<'tcx, FnSig<'tcx>>>),
787}
788
789impl IntoDiagArg for TyOrSig<'_> {
790 fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
791 match self {
792 TyOrSig::Ty(ty) => ty.into_diag_arg(),
793 TyOrSig::ClosureSig(sig) => sig.into_diag_arg(),
794 }
795 }
796}
797
798#[derive(Subdiagnostic)]
799pub enum ActualImplExplNotes<'tcx> {
800 #[note(trait_selection_actual_impl_expl_expected_signature_two)]
801 ExpectedSignatureTwo {
802 leading_ellipsis: bool,
803 ty_or_sig: TyOrSig<'tcx>,
804 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
805 lifetime_1: usize,
806 lifetime_2: usize,
807 },
808 #[note(trait_selection_actual_impl_expl_expected_signature_any)]
809 ExpectedSignatureAny {
810 leading_ellipsis: bool,
811 ty_or_sig: TyOrSig<'tcx>,
812 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
813 lifetime_1: usize,
814 },
815 #[note(trait_selection_actual_impl_expl_expected_signature_some)]
816 ExpectedSignatureSome {
817 leading_ellipsis: bool,
818 ty_or_sig: TyOrSig<'tcx>,
819 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
820 lifetime_1: usize,
821 },
822 #[note(trait_selection_actual_impl_expl_expected_signature_nothing)]
823 ExpectedSignatureNothing {
824 leading_ellipsis: bool,
825 ty_or_sig: TyOrSig<'tcx>,
826 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
827 },
828 #[note(trait_selection_actual_impl_expl_expected_passive_two)]
829 ExpectedPassiveTwo {
830 leading_ellipsis: bool,
831 ty_or_sig: TyOrSig<'tcx>,
832 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
833 lifetime_1: usize,
834 lifetime_2: usize,
835 },
836 #[note(trait_selection_actual_impl_expl_expected_passive_any)]
837 ExpectedPassiveAny {
838 leading_ellipsis: bool,
839 ty_or_sig: TyOrSig<'tcx>,
840 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
841 lifetime_1: usize,
842 },
843 #[note(trait_selection_actual_impl_expl_expected_passive_some)]
844 ExpectedPassiveSome {
845 leading_ellipsis: bool,
846 ty_or_sig: TyOrSig<'tcx>,
847 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
848 lifetime_1: usize,
849 },
850 #[note(trait_selection_actual_impl_expl_expected_passive_nothing)]
851 ExpectedPassiveNothing {
852 leading_ellipsis: bool,
853 ty_or_sig: TyOrSig<'tcx>,
854 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
855 },
856 #[note(trait_selection_actual_impl_expl_expected_other_two)]
857 ExpectedOtherTwo {
858 leading_ellipsis: bool,
859 ty_or_sig: TyOrSig<'tcx>,
860 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
861 lifetime_1: usize,
862 lifetime_2: usize,
863 },
864 #[note(trait_selection_actual_impl_expl_expected_other_any)]
865 ExpectedOtherAny {
866 leading_ellipsis: bool,
867 ty_or_sig: TyOrSig<'tcx>,
868 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
869 lifetime_1: usize,
870 },
871 #[note(trait_selection_actual_impl_expl_expected_other_some)]
872 ExpectedOtherSome {
873 leading_ellipsis: bool,
874 ty_or_sig: TyOrSig<'tcx>,
875 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
876 lifetime_1: usize,
877 },
878 #[note(trait_selection_actual_impl_expl_expected_other_nothing)]
879 ExpectedOtherNothing {
880 leading_ellipsis: bool,
881 ty_or_sig: TyOrSig<'tcx>,
882 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
883 },
884 #[note(trait_selection_actual_impl_expl_but_actually_implements_trait)]
885 ButActuallyImplementsTrait {
886 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
887 has_lifetime: bool,
888 lifetime: usize,
889 },
890 #[note(trait_selection_actual_impl_expl_but_actually_implemented_for_ty)]
891 ButActuallyImplementedForTy {
892 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
893 has_lifetime: bool,
894 lifetime: usize,
895 ty: String,
896 },
897 #[note(trait_selection_actual_impl_expl_but_actually_ty_implements)]
898 ButActuallyTyImplements {
899 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
900 has_lifetime: bool,
901 lifetime: usize,
902 ty: String,
903 },
904}
905
906pub enum ActualImplExpectedKind {
907 Signature,
908 Passive,
909 Other,
910}
911
912pub enum ActualImplExpectedLifetimeKind {
913 Two,
914 Any,
915 Some,
916 Nothing,
917}
918
919impl<'tcx> ActualImplExplNotes<'tcx> {
920 pub fn new_expected(
921 kind: ActualImplExpectedKind,
922 lt_kind: ActualImplExpectedLifetimeKind,
923 leading_ellipsis: bool,
924 ty_or_sig: TyOrSig<'tcx>,
925 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
926 lifetime_1: usize,
927 lifetime_2: usize,
928 ) -> Self {
929 match (kind, lt_kind) {
930 (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => {
931 Self::ExpectedSignatureTwo {
932 leading_ellipsis,
933 ty_or_sig,
934 trait_path,
935 lifetime_1,
936 lifetime_2,
937 }
938 }
939 (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => {
940 Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
941 }
942 (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => {
943 Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
944 }
945 (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => {
946 Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path }
947 }
948 (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => {
949 Self::ExpectedPassiveTwo {
950 leading_ellipsis,
951 ty_or_sig,
952 trait_path,
953 lifetime_1,
954 lifetime_2,
955 }
956 }
957 (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => {
958 Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
959 }
960 (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => {
961 Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
962 }
963 (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => {
964 Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path }
965 }
966 (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => {
967 Self::ExpectedOtherTwo {
968 leading_ellipsis,
969 ty_or_sig,
970 trait_path,
971 lifetime_1,
972 lifetime_2,
973 }
974 }
975 (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => {
976 Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
977 }
978 (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => {
979 Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
980 }
981 (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => {
982 Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path }
983 }
984 }
985 }
986}
987
988#[derive(Diagnostic)]
989#[diag(trait_selection_trait_placeholder_mismatch)]
990pub struct TraitPlaceholderMismatch<'tcx> {
991 #[primary_span]
992 pub span: Span,
993 #[label(trait_selection_label_satisfy)]
994 pub satisfy_span: Option<Span>,
995 #[label(trait_selection_label_where)]
996 pub where_span: Option<Span>,
997 #[label(trait_selection_label_dup)]
998 pub dup_span: Option<Span>,
999 pub def_id: String,
1000 pub trait_def_id: String,
1001
1002 #[subdiagnostic]
1003 pub actual_impl_expl_notes: Vec<ActualImplExplNotes<'tcx>>,
1004}
1005
1006pub struct ConsiderBorrowingParamHelp {
1007 pub spans: Vec<Span>,
1008}
1009
1010impl Subdiagnostic for ConsiderBorrowingParamHelp {
1011 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
1012 self,
1013 diag: &mut Diag<'_, G>,
1014 f: &F,
1015 ) {
1016 let mut type_param_span: MultiSpan = self.spans.clone().into();
1017 for &span in &self.spans {
1018 type_param_span.push_span_label(span, fluent::trait_selection_tid_consider_borrowing);
1020 }
1021 let msg = f(diag, fluent::trait_selection_tid_param_help.into());
1022 diag.span_help(type_param_span, msg);
1023 }
1024}
1025
1026#[derive(Subdiagnostic)]
1027#[help(trait_selection_tid_rel_help)]
1028pub struct RelationshipHelp;
1029
1030#[derive(Diagnostic)]
1031#[diag(trait_selection_trait_impl_diff)]
1032pub struct TraitImplDiff {
1033 #[primary_span]
1034 #[label(trait_selection_found)]
1035 pub sp: Span,
1036 #[label(trait_selection_expected)]
1037 pub trait_sp: Span,
1038 #[note(trait_selection_expected_found)]
1039 pub note: (),
1040 #[subdiagnostic]
1041 pub param_help: ConsiderBorrowingParamHelp,
1042 #[subdiagnostic]
1043 pub rel_help: Option<RelationshipHelp>,
1046 pub expected: String,
1047 pub found: String,
1048}
1049
1050pub struct DynTraitConstraintSuggestion {
1051 pub span: Span,
1052 pub ident: Ident,
1053}
1054
1055impl Subdiagnostic for DynTraitConstraintSuggestion {
1056 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
1057 self,
1058 diag: &mut Diag<'_, G>,
1059 f: &F,
1060 ) {
1061 let mut multi_span: MultiSpan = vec![self.span].into();
1062 multi_span.push_span_label(self.span, fluent::trait_selection_dtcs_has_lifetime_req_label);
1063 multi_span
1064 .push_span_label(self.ident.span, fluent::trait_selection_dtcs_introduces_requirement);
1065 let msg = f(diag, fluent::trait_selection_dtcs_has_req_note.into());
1066 diag.span_note(multi_span, msg);
1067 let msg = f(diag, fluent::trait_selection_dtcs_suggestion.into());
1068 diag.span_suggestion_verbose(
1069 self.span.shrink_to_hi(),
1070 msg,
1071 " + '_",
1072 Applicability::MaybeIncorrect,
1073 );
1074 }
1075}
1076
1077#[derive(Diagnostic)]
1078#[diag(trait_selection_but_calling_introduces, code = E0772)]
1079pub struct ButCallingIntroduces {
1080 #[label(trait_selection_label1)]
1081 pub param_ty_span: Span,
1082 #[primary_span]
1083 #[label(trait_selection_label2)]
1084 pub cause_span: Span,
1085
1086 pub has_param_name: bool,
1087 pub param_name: String,
1088 pub has_lifetime: bool,
1089 pub lifetime: String,
1090 pub assoc_item: Symbol,
1091 pub has_impl_path: bool,
1092 pub impl_path: String,
1093}
1094
1095pub struct ReqIntroducedLocations {
1096 pub span: MultiSpan,
1097 pub spans: Vec<Span>,
1098 pub fn_decl_span: Span,
1099 pub cause_span: Span,
1100 pub add_label: bool,
1101}
1102
1103impl Subdiagnostic for ReqIntroducedLocations {
1104 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
1105 mut self,
1106 diag: &mut Diag<'_, G>,
1107 f: &F,
1108 ) {
1109 for sp in self.spans {
1110 self.span.push_span_label(sp, fluent::trait_selection_ril_introduced_here);
1111 }
1112
1113 if self.add_label {
1114 self.span.push_span_label(self.fn_decl_span, fluent::trait_selection_ril_introduced_by);
1115 }
1116 self.span.push_span_label(self.cause_span, fluent::trait_selection_ril_because_of);
1117 let msg = f(diag, fluent::trait_selection_ril_static_introduced_by.into());
1118 diag.span_note(self.span, msg);
1119 }
1120}
1121
1122pub struct MoreTargeted {
1123 pub ident: Symbol,
1124}
1125
1126impl Subdiagnostic for MoreTargeted {
1127 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
1128 self,
1129 diag: &mut Diag<'_, G>,
1130 _f: &F,
1131 ) {
1132 diag.code(E0772);
1133 diag.primary_message(fluent::trait_selection_more_targeted);
1134 diag.arg("ident", self.ident);
1135 }
1136}
1137
1138#[derive(Diagnostic)]
1139#[diag(trait_selection_but_needs_to_satisfy, code = E0759)]
1140pub struct ButNeedsToSatisfy {
1141 #[primary_span]
1142 pub sp: Span,
1143 #[label(trait_selection_influencer)]
1144 pub influencer_point: Span,
1145 #[label(trait_selection_used_here)]
1146 pub spans: Vec<Span>,
1147 #[label(trait_selection_require)]
1148 pub require_span_as_label: Option<Span>,
1149 #[note(trait_selection_require)]
1150 pub require_span_as_note: Option<Span>,
1151 #[note(trait_selection_introduced_by_bound)]
1152 pub bound: Option<Span>,
1153
1154 #[subdiagnostic]
1155 pub req_introduces_loc: Option<ReqIntroducedLocations>,
1156
1157 pub has_param_name: bool,
1158 pub param_name: String,
1159 pub spans_empty: bool,
1160 pub has_lifetime: bool,
1161 pub lifetime: String,
1162}
1163
1164#[derive(Diagnostic)]
1165#[diag(trait_selection_outlives_content, code = E0312)]
1166pub struct OutlivesContent<'a> {
1167 #[primary_span]
1168 pub span: Span,
1169 #[subdiagnostic]
1170 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1171}
1172
1173#[derive(Diagnostic)]
1174#[diag(trait_selection_outlives_bound, code = E0476)]
1175pub struct OutlivesBound<'a> {
1176 #[primary_span]
1177 pub span: Span,
1178 #[subdiagnostic]
1179 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1180}
1181
1182#[derive(Diagnostic)]
1183#[diag(trait_selection_fulfill_req_lifetime, code = E0477)]
1184pub struct FulfillReqLifetime<'a> {
1185 #[primary_span]
1186 pub span: Span,
1187 pub ty: Ty<'a>,
1188 #[subdiagnostic]
1189 pub note: Option<note_and_explain::RegionExplanation<'a>>,
1190}
1191
1192#[derive(Diagnostic)]
1193#[diag(trait_selection_lf_bound_not_satisfied, code = E0478)]
1194pub struct LfBoundNotSatisfied<'a> {
1195 #[primary_span]
1196 pub span: Span,
1197 #[subdiagnostic]
1198 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1199}
1200
1201#[derive(Diagnostic)]
1202#[diag(trait_selection_ref_longer_than_data, code = E0491)]
1203pub struct RefLongerThanData<'a> {
1204 #[primary_span]
1205 pub span: Span,
1206 pub ty: Ty<'a>,
1207 #[subdiagnostic]
1208 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1209}
1210
1211#[derive(Subdiagnostic)]
1212pub enum WhereClauseSuggestions {
1213 #[suggestion(
1214 trait_selection_where_remove,
1215 code = "",
1216 applicability = "machine-applicable",
1217 style = "verbose"
1218 )]
1219 Remove {
1220 #[primary_span]
1221 span: Span,
1222 },
1223 #[suggestion(
1224 trait_selection_where_copy_predicates,
1225 code = "{space}where {trait_predicates}",
1226 applicability = "machine-applicable",
1227 style = "verbose"
1228 )]
1229 CopyPredicates {
1230 #[primary_span]
1231 span: Span,
1232 space: &'static str,
1233 trait_predicates: String,
1234 },
1235}
1236
1237#[derive(Subdiagnostic)]
1238pub enum SuggestRemoveSemiOrReturnBinding {
1239 #[multipart_suggestion(
1240 trait_selection_srs_remove_and_box,
1241 applicability = "machine-applicable"
1242 )]
1243 RemoveAndBox {
1244 #[suggestion_part(code = "Box::new(")]
1245 first_lo: Span,
1246 #[suggestion_part(code = ")")]
1247 first_hi: Span,
1248 #[suggestion_part(code = "Box::new(")]
1249 second_lo: Span,
1250 #[suggestion_part(code = ")")]
1251 second_hi: Span,
1252 #[suggestion_part(code = "")]
1253 sp: Span,
1254 },
1255 #[suggestion(
1256 trait_selection_srs_remove,
1257 style = "short",
1258 code = "",
1259 applicability = "machine-applicable"
1260 )]
1261 Remove {
1262 #[primary_span]
1263 sp: Span,
1264 },
1265 #[suggestion(
1266 trait_selection_srs_add,
1267 style = "verbose",
1268 code = "{code}",
1269 applicability = "maybe-incorrect"
1270 )]
1271 Add {
1272 #[primary_span]
1273 sp: Span,
1274 code: String,
1275 ident: Ident,
1276 },
1277 #[note(trait_selection_srs_add_one)]
1278 AddOne {
1279 #[primary_span]
1280 spans: MultiSpan,
1281 },
1282}
1283
1284#[derive(Subdiagnostic)]
1285pub enum ConsiderAddingAwait {
1286 #[help(trait_selection_await_both_futures)]
1287 BothFuturesHelp,
1288 #[multipart_suggestion(trait_selection_await_both_futures, applicability = "maybe-incorrect")]
1289 BothFuturesSugg {
1290 #[suggestion_part(code = ".await")]
1291 first: Span,
1292 #[suggestion_part(code = ".await")]
1293 second: Span,
1294 },
1295 #[suggestion(
1296 trait_selection_await_future,
1297 code = ".await",
1298 style = "verbose",
1299 applicability = "maybe-incorrect"
1300 )]
1301 FutureSugg {
1302 #[primary_span]
1303 span: Span,
1304 },
1305 #[note(trait_selection_await_note)]
1306 FutureSuggNote {
1307 #[primary_span]
1308 span: Span,
1309 },
1310 #[multipart_suggestion(
1311 trait_selection_await_future,
1312 style = "verbose",
1313 applicability = "maybe-incorrect"
1314 )]
1315 FutureSuggMultiple {
1316 #[suggestion_part(code = ".await")]
1317 spans: Vec<Span>,
1318 },
1319}
1320
1321#[derive(Diagnostic)]
1322pub enum PlaceholderRelationLfNotSatisfied {
1323 #[diag(trait_selection_lf_bound_not_satisfied)]
1324 HasBoth {
1325 #[primary_span]
1326 span: Span,
1327 #[note(trait_selection_prlf_defined_with_sub)]
1328 sub_span: Span,
1329 #[note(trait_selection_prlf_must_outlive_with_sup)]
1330 sup_span: Span,
1331 sub_symbol: Symbol,
1332 sup_symbol: Symbol,
1333 #[note(trait_selection_prlf_known_limitation)]
1334 note: (),
1335 },
1336 #[diag(trait_selection_lf_bound_not_satisfied)]
1337 HasSub {
1338 #[primary_span]
1339 span: Span,
1340 #[note(trait_selection_prlf_defined_with_sub)]
1341 sub_span: Span,
1342 #[note(trait_selection_prlf_must_outlive_without_sup)]
1343 sup_span: Span,
1344 sub_symbol: Symbol,
1345 #[note(trait_selection_prlf_known_limitation)]
1346 note: (),
1347 },
1348 #[diag(trait_selection_lf_bound_not_satisfied)]
1349 HasSup {
1350 #[primary_span]
1351 span: Span,
1352 #[note(trait_selection_prlf_defined_without_sub)]
1353 sub_span: Span,
1354 #[note(trait_selection_prlf_must_outlive_with_sup)]
1355 sup_span: Span,
1356 sup_symbol: Symbol,
1357 #[note(trait_selection_prlf_known_limitation)]
1358 note: (),
1359 },
1360 #[diag(trait_selection_lf_bound_not_satisfied)]
1361 HasNone {
1362 #[primary_span]
1363 span: Span,
1364 #[note(trait_selection_prlf_defined_without_sub)]
1365 sub_span: Span,
1366 #[note(trait_selection_prlf_must_outlive_without_sup)]
1367 sup_span: Span,
1368 #[note(trait_selection_prlf_known_limitation)]
1369 note: (),
1370 },
1371 #[diag(trait_selection_lf_bound_not_satisfied)]
1372 OnlyPrimarySpan {
1373 #[primary_span]
1374 span: Span,
1375 #[note(trait_selection_prlf_known_limitation)]
1376 note: (),
1377 },
1378}
1379
1380#[derive(Diagnostic)]
1381#[diag(trait_selection_opaque_captures_lifetime, code = E0700)]
1382pub struct OpaqueCapturesLifetime<'tcx> {
1383 #[primary_span]
1384 pub span: Span,
1385 #[label]
1386 pub opaque_ty_span: Span,
1387 pub opaque_ty: Ty<'tcx>,
1388}
1389
1390#[derive(Subdiagnostic)]
1391pub enum FunctionPointerSuggestion<'a> {
1392 #[suggestion(
1393 trait_selection_fps_use_ref,
1394 code = "&",
1395 style = "verbose",
1396 applicability = "maybe-incorrect"
1397 )]
1398 UseRef {
1399 #[primary_span]
1400 span: Span,
1401 },
1402 #[suggestion(
1403 trait_selection_fps_remove_ref,
1404 code = "{fn_name}",
1405 style = "verbose",
1406 applicability = "maybe-incorrect"
1407 )]
1408 RemoveRef {
1409 #[primary_span]
1410 span: Span,
1411 #[skip_arg]
1412 fn_name: String,
1413 },
1414 #[suggestion(
1415 trait_selection_fps_cast,
1416 code = "&({fn_name} as {sig})",
1417 style = "verbose",
1418 applicability = "maybe-incorrect"
1419 )]
1420 CastRef {
1421 #[primary_span]
1422 span: Span,
1423 #[skip_arg]
1424 fn_name: String,
1425 #[skip_arg]
1426 sig: Binder<'a, FnSig<'a>>,
1427 },
1428 #[suggestion(
1429 trait_selection_fps_cast,
1430 code = " as {sig}",
1431 style = "verbose",
1432 applicability = "maybe-incorrect"
1433 )]
1434 Cast {
1435 #[primary_span]
1436 span: Span,
1437 #[skip_arg]
1438 sig: Binder<'a, FnSig<'a>>,
1439 },
1440 #[suggestion(
1441 trait_selection_fps_cast_both,
1442 code = " as {found_sig}",
1443 style = "hidden",
1444 applicability = "maybe-incorrect"
1445 )]
1446 CastBoth {
1447 #[primary_span]
1448 span: Span,
1449 #[skip_arg]
1450 found_sig: Binder<'a, FnSig<'a>>,
1451 expected_sig: Binder<'a, FnSig<'a>>,
1452 },
1453 #[suggestion(
1454 trait_selection_fps_cast_both,
1455 code = "&({fn_name} as {found_sig})",
1456 style = "hidden",
1457 applicability = "maybe-incorrect"
1458 )]
1459 CastBothRef {
1460 #[primary_span]
1461 span: Span,
1462 #[skip_arg]
1463 fn_name: String,
1464 #[skip_arg]
1465 found_sig: Binder<'a, FnSig<'a>>,
1466 expected_sig: Binder<'a, FnSig<'a>>,
1467 },
1468}
1469
1470#[derive(Subdiagnostic)]
1471#[note(trait_selection_fps_items_are_distinct)]
1472pub struct FnItemsAreDistinct;
1473
1474#[derive(Subdiagnostic)]
1475#[note(trait_selection_fn_uniq_types)]
1476pub struct FnUniqTypes;
1477
1478#[derive(Subdiagnostic)]
1479#[help(trait_selection_fn_consider_casting)]
1480pub struct FnConsiderCasting {
1481 pub casting: String,
1482}
1483
1484#[derive(Subdiagnostic)]
1485#[help(trait_selection_fn_consider_casting_both)]
1486pub struct FnConsiderCastingBoth<'a> {
1487 pub sig: Binder<'a, FnSig<'a>>,
1488}
1489
1490#[derive(Subdiagnostic)]
1491pub enum SuggestAccessingField<'a> {
1492 #[suggestion(
1493 trait_selection_suggest_accessing_field,
1494 code = "{snippet}.{name}",
1495 applicability = "maybe-incorrect"
1496 )]
1497 Safe {
1498 #[primary_span]
1499 span: Span,
1500 snippet: String,
1501 name: Symbol,
1502 ty: Ty<'a>,
1503 },
1504 #[suggestion(
1505 trait_selection_suggest_accessing_field,
1506 code = "unsafe {{ {snippet}.{name} }}",
1507 applicability = "maybe-incorrect"
1508 )]
1509 Unsafe {
1510 #[primary_span]
1511 span: Span,
1512 snippet: String,
1513 name: Symbol,
1514 ty: Ty<'a>,
1515 },
1516}
1517
1518#[derive(Subdiagnostic)]
1519#[multipart_suggestion(trait_selection_stp_wrap_one, applicability = "maybe-incorrect")]
1520pub struct SuggestTuplePatternOne {
1521 pub variant: String,
1522 #[suggestion_part(code = "{variant}(")]
1523 pub span_low: Span,
1524 #[suggestion_part(code = ")")]
1525 pub span_high: Span,
1526}
1527
1528pub struct SuggestTuplePatternMany {
1529 pub path: String,
1530 pub cause_span: Span,
1531 pub compatible_variants: Vec<String>,
1532}
1533
1534impl Subdiagnostic for SuggestTuplePatternMany {
1535 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
1536 self,
1537 diag: &mut Diag<'_, G>,
1538 f: &F,
1539 ) {
1540 diag.arg("path", self.path);
1541 let message = f(diag, crate::fluent_generated::trait_selection_stp_wrap_many.into());
1542 diag.multipart_suggestions(
1543 message,
1544 self.compatible_variants.into_iter().map(|variant| {
1545 vec![
1546 (self.cause_span.shrink_to_lo(), format!("{variant}(")),
1547 (self.cause_span.shrink_to_hi(), ")".to_string()),
1548 ]
1549 }),
1550 rustc_errors::Applicability::MaybeIncorrect,
1551 );
1552 }
1553}
1554
1555#[derive(Subdiagnostic)]
1556pub enum TypeErrorAdditionalDiags {
1557 #[suggestion(
1558 trait_selection_meant_byte_literal,
1559 code = "b'{code}'",
1560 applicability = "machine-applicable"
1561 )]
1562 MeantByteLiteral {
1563 #[primary_span]
1564 span: Span,
1565 code: String,
1566 },
1567 #[suggestion(
1568 trait_selection_meant_char_literal,
1569 code = "'{code}'",
1570 applicability = "machine-applicable"
1571 )]
1572 MeantCharLiteral {
1573 #[primary_span]
1574 span: Span,
1575 code: String,
1576 },
1577 #[multipart_suggestion(trait_selection_meant_str_literal, applicability = "machine-applicable")]
1578 MeantStrLiteral {
1579 #[suggestion_part(code = "\"")]
1580 start: Span,
1581 #[suggestion_part(code = "\"")]
1582 end: Span,
1583 },
1584 #[suggestion(
1585 trait_selection_consider_specifying_length,
1586 code = "{length}",
1587 applicability = "maybe-incorrect"
1588 )]
1589 ConsiderSpecifyingLength {
1590 #[primary_span]
1591 span: Span,
1592 length: u64,
1593 },
1594 #[note(trait_selection_try_cannot_convert)]
1595 TryCannotConvert { found: String, expected: String },
1596 #[suggestion(
1597 trait_selection_tuple_trailing_comma,
1598 code = ",",
1599 applicability = "machine-applicable"
1600 )]
1601 TupleOnlyComma {
1602 #[primary_span]
1603 span: Span,
1604 },
1605 #[multipart_suggestion(
1606 trait_selection_tuple_trailing_comma,
1607 applicability = "machine-applicable"
1608 )]
1609 TupleAlsoParentheses {
1610 #[suggestion_part(code = "(")]
1611 span_low: Span,
1612 #[suggestion_part(code = ",)")]
1613 span_high: Span,
1614 },
1615 #[suggestion(
1616 trait_selection_suggest_add_let_for_letchains,
1617 style = "verbose",
1618 applicability = "machine-applicable",
1619 code = "let "
1620 )]
1621 AddLetForLetChains {
1622 #[primary_span]
1623 span: Span,
1624 },
1625}
1626
1627#[derive(Diagnostic)]
1628pub enum ObligationCauseFailureCode {
1629 #[diag(trait_selection_oc_method_compat, code = E0308)]
1630 MethodCompat {
1631 #[primary_span]
1632 span: Span,
1633 #[subdiagnostic]
1634 subdiags: Vec<TypeErrorAdditionalDiags>,
1635 },
1636 #[diag(trait_selection_oc_type_compat, code = E0308)]
1637 TypeCompat {
1638 #[primary_span]
1639 span: Span,
1640 #[subdiagnostic]
1641 subdiags: Vec<TypeErrorAdditionalDiags>,
1642 },
1643 #[diag(trait_selection_oc_const_compat, code = E0308)]
1644 ConstCompat {
1645 #[primary_span]
1646 span: Span,
1647 #[subdiagnostic]
1648 subdiags: Vec<TypeErrorAdditionalDiags>,
1649 },
1650 #[diag(trait_selection_oc_try_compat, code = E0308)]
1651 TryCompat {
1652 #[primary_span]
1653 span: Span,
1654 #[subdiagnostic]
1655 subdiags: Vec<TypeErrorAdditionalDiags>,
1656 },
1657 #[diag(trait_selection_oc_match_compat, code = E0308)]
1658 MatchCompat {
1659 #[primary_span]
1660 span: Span,
1661 #[subdiagnostic]
1662 subdiags: Vec<TypeErrorAdditionalDiags>,
1663 },
1664 #[diag(trait_selection_oc_if_else_different, code = E0308)]
1665 IfElseDifferent {
1666 #[primary_span]
1667 span: Span,
1668 #[subdiagnostic]
1669 subdiags: Vec<TypeErrorAdditionalDiags>,
1670 },
1671 #[diag(trait_selection_oc_no_else, code = E0317)]
1672 NoElse {
1673 #[primary_span]
1674 span: Span,
1675 },
1676 #[diag(trait_selection_oc_no_diverge, code = E0308)]
1677 NoDiverge {
1678 #[primary_span]
1679 span: Span,
1680 #[subdiagnostic]
1681 subdiags: Vec<TypeErrorAdditionalDiags>,
1682 },
1683 #[diag(trait_selection_oc_fn_main_correct_type, code = E0580)]
1684 FnMainCorrectType {
1685 #[primary_span]
1686 span: Span,
1687 },
1688 #[diag(trait_selection_oc_fn_lang_correct_type, code = E0308)]
1689 FnLangCorrectType {
1690 #[primary_span]
1691 span: Span,
1692 #[subdiagnostic]
1693 subdiags: Vec<TypeErrorAdditionalDiags>,
1694 lang_item_name: Symbol,
1695 },
1696 #[diag(trait_selection_oc_intrinsic_correct_type, code = E0308)]
1697 IntrinsicCorrectType {
1698 #[primary_span]
1699 span: Span,
1700 #[subdiagnostic]
1701 subdiags: Vec<TypeErrorAdditionalDiags>,
1702 },
1703 #[diag(trait_selection_oc_method_correct_type, code = E0308)]
1704 MethodCorrectType {
1705 #[primary_span]
1706 span: Span,
1707 #[subdiagnostic]
1708 subdiags: Vec<TypeErrorAdditionalDiags>,
1709 },
1710 #[diag(trait_selection_oc_closure_selfref, code = E0644)]
1711 ClosureSelfref {
1712 #[primary_span]
1713 span: Span,
1714 },
1715 #[diag(trait_selection_oc_cant_coerce_force_inline, code = E0308)]
1716 CantCoerceForceInline {
1717 #[primary_span]
1718 span: Span,
1719 #[subdiagnostic]
1720 subdiags: Vec<TypeErrorAdditionalDiags>,
1721 },
1722 #[diag(trait_selection_oc_cant_coerce_intrinsic, code = E0308)]
1723 CantCoerceIntrinsic {
1724 #[primary_span]
1725 span: Span,
1726 #[subdiagnostic]
1727 subdiags: Vec<TypeErrorAdditionalDiags>,
1728 },
1729 #[diag(trait_selection_oc_generic, code = E0308)]
1730 Generic {
1731 #[primary_span]
1732 span: Span,
1733 #[subdiagnostic]
1734 subdiags: Vec<TypeErrorAdditionalDiags>,
1735 },
1736}
1737
1738#[derive(Subdiagnostic)]
1739pub enum AddPreciseCapturing {
1740 #[suggestion(
1741 trait_selection_precise_capturing_new,
1742 style = "verbose",
1743 code = " + use<{concatenated_bounds}>",
1744 applicability = "machine-applicable"
1745 )]
1746 New {
1747 #[primary_span]
1748 span: Span,
1749 new_lifetime: Symbol,
1750 concatenated_bounds: String,
1751 },
1752 #[suggestion(
1753 trait_selection_precise_capturing_existing,
1754 style = "verbose",
1755 code = "{pre}{new_lifetime}{post}",
1756 applicability = "machine-applicable"
1757 )]
1758 Existing {
1759 #[primary_span]
1760 span: Span,
1761 new_lifetime: Symbol,
1762 pre: &'static str,
1763 post: &'static str,
1764 },
1765}
1766
1767pub struct AddPreciseCapturingAndParams {
1768 pub suggs: Vec<(Span, String)>,
1769 pub new_lifetime: Symbol,
1770 pub apit_spans: Vec<Span>,
1771}
1772
1773impl Subdiagnostic for AddPreciseCapturingAndParams {
1774 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
1775 self,
1776 diag: &mut Diag<'_, G>,
1777 _f: &F,
1778 ) {
1779 diag.arg("new_lifetime", self.new_lifetime);
1780 diag.multipart_suggestion_verbose(
1781 fluent::trait_selection_precise_capturing_new_but_apit,
1782 self.suggs,
1783 Applicability::MaybeIncorrect,
1784 );
1785 diag.span_note(
1786 self.apit_spans,
1787 fluent::trait_selection_warn_removing_apit_params_for_undercapture,
1788 );
1789 }
1790}
1791
1792pub fn impl_trait_overcapture_suggestion<'tcx>(
1797 tcx: TyCtxt<'tcx>,
1798 opaque_def_id: LocalDefId,
1799 fn_def_id: LocalDefId,
1800 captured_args: FxIndexSet<DefId>,
1801) -> Option<AddPreciseCapturingForOvercapture> {
1802 let generics = tcx.generics_of(fn_def_id);
1803
1804 let mut captured_lifetimes = FxIndexSet::default();
1805 let mut captured_non_lifetimes = FxIndexSet::default();
1806 let mut synthetics = vec![];
1807
1808 for arg in captured_args {
1809 if tcx.def_kind(arg) == DefKind::LifetimeParam {
1810 captured_lifetimes.insert(tcx.item_name(arg));
1811 } else {
1812 let idx = generics.param_def_id_to_index(tcx, arg).expect("expected arg in scope");
1813 let param = generics.param_at(idx as usize, tcx);
1814 if param.kind.is_synthetic() {
1815 synthetics.push((tcx.def_span(arg), param.name));
1816 } else {
1817 captured_non_lifetimes.insert(tcx.item_name(arg));
1818 }
1819 }
1820 }
1821
1822 let mut next_fresh_param = || {
1823 ["T", "U", "V", "W", "X", "Y", "A", "B", "C"]
1824 .into_iter()
1825 .map(Symbol::intern)
1826 .chain((0..).map(|i| Symbol::intern(&format!("T{i}"))))
1827 .find(|s| captured_non_lifetimes.insert(*s))
1828 .unwrap()
1829 };
1830
1831 let mut suggs = vec![];
1832 let mut apit_spans = vec![];
1833
1834 if !synthetics.is_empty() {
1835 let mut new_params = String::new();
1836 for (i, (span, name)) in synthetics.into_iter().enumerate() {
1837 apit_spans.push(span);
1838
1839 let fresh_param = next_fresh_param();
1840
1841 suggs.push((span, fresh_param.to_string()));
1843
1844 if i > 0 {
1852 new_params += ", ";
1853 }
1854 let name_as_bounds = name.as_str().trim_start_matches("impl").trim_start();
1855 new_params += fresh_param.as_str();
1856 new_params += ": ";
1857 new_params += name_as_bounds;
1858 }
1859
1860 let Some(generics) = tcx.hir_get_generics(fn_def_id) else {
1861 return None;
1863 };
1864
1865 suggs.push(if let Some(params_span) = generics.span_for_param_suggestion() {
1867 (params_span, format!(", {new_params}"))
1868 } else {
1869 (generics.span, format!("<{new_params}>"))
1870 });
1871 }
1872
1873 let concatenated_bounds = captured_lifetimes
1874 .into_iter()
1875 .chain(captured_non_lifetimes)
1876 .map(|sym| sym.to_string())
1877 .collect::<Vec<_>>()
1878 .join(", ");
1879
1880 let opaque_hir_id = tcx.local_def_id_to_hir_id(opaque_def_id);
1881 let (lparen, rparen) = match tcx
1883 .hir()
1884 .parent_iter(opaque_hir_id)
1885 .nth(1)
1886 .expect("expected ty to have a parent always")
1887 .1
1888 {
1889 Node::PathSegment(segment)
1890 if segment.args().paren_sugar_output().is_some_and(|ty| ty.hir_id == opaque_hir_id) =>
1891 {
1892 ("(", ")")
1893 }
1894 Node::Ty(ty) => match ty.kind {
1895 rustc_hir::TyKind::Ptr(_) | rustc_hir::TyKind::Ref(..) => ("(", ")"),
1896 _ => ("", ""),
1900 },
1901 _ => ("", ""),
1902 };
1903
1904 let rpit_span = tcx.def_span(opaque_def_id);
1905 if !lparen.is_empty() {
1906 suggs.push((rpit_span.shrink_to_lo(), lparen.to_string()));
1907 }
1908 suggs.push((rpit_span.shrink_to_hi(), format!(" + use<{concatenated_bounds}>{rparen}")));
1909
1910 Some(AddPreciseCapturingForOvercapture { suggs, apit_spans })
1911}
1912
1913pub struct AddPreciseCapturingForOvercapture {
1914 pub suggs: Vec<(Span, String)>,
1915 pub apit_spans: Vec<Span>,
1916}
1917
1918impl Subdiagnostic for AddPreciseCapturingForOvercapture {
1919 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
1920 self,
1921 diag: &mut Diag<'_, G>,
1922 _f: &F,
1923 ) {
1924 let applicability = if self.apit_spans.is_empty() {
1925 Applicability::MachineApplicable
1926 } else {
1927 Applicability::MaybeIncorrect
1931 };
1932 diag.multipart_suggestion_verbose(
1933 fluent::trait_selection_precise_capturing_overcaptures,
1934 self.suggs,
1935 applicability,
1936 );
1937 if !self.apit_spans.is_empty() {
1938 diag.span_note(
1939 self.apit_spans,
1940 fluent::trait_selection_warn_removing_apit_params_for_overcapture,
1941 );
1942 }
1943 }
1944}