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, IsAnonInPath, 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 { kind: hir::ItemKind::Fn { generics, .. }, .. })
513 | hir::Node::TraitItem(hir::TraitItem { generics, .. })
514 | hir::Node::ImplItem(hir::ImplItem { generics, .. }) => (
515 generics,
516 match self.tcx.parent_hir_node(self.tcx.local_def_id_to_hir_id(anon_reg.scope))
517 {
518 hir::Node::Item(hir::Item {
519 kind: hir::ItemKind::Trait(_, _, _, generics, ..),
520 ..
521 })
522 | hir::Node::Item(hir::Item {
523 kind: hir::ItemKind::Impl(hir::Impl { generics, .. }),
524 ..
525 }) => Some(generics),
526 _ => None,
527 },
528 ),
529 _ => return false,
530 };
531
532 let suggestion_param_name = generics
533 .params
534 .iter()
535 .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
536 .map(|p| p.name.ident().name)
537 .find(|i| *i != kw::UnderscoreLifetime);
538 let introduce_new = suggestion_param_name.is_none();
539
540 let mut default = "'a".to_string();
541 if let Some(parent_generics) = parent_generics {
542 let used: FxHashSet<_> = parent_generics
543 .params
544 .iter()
545 .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
546 .map(|p| p.name.ident().name)
547 .filter(|i| *i != kw::UnderscoreLifetime)
548 .map(|l| l.to_string())
549 .collect();
550 if let Some(lt) =
551 ('a'..='z').map(|it| format!("'{it}")).find(|it| !used.contains(it))
552 {
553 default = lt;
558 }
559 }
560 let suggestion_param_name =
561 suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| default);
562
563 struct ImplicitLifetimeFinder {
564 suggestions: Vec<(Span, String)>,
565 suggestion_param_name: String,
566 }
567
568 impl<'v> Visitor<'v> for ImplicitLifetimeFinder {
569 fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
570 let make_suggestion = |lifetime: &hir::Lifetime| {
571 if lifetime.is_anon_in_path == IsAnonInPath::Yes
572 && lifetime.ident.span.is_empty()
573 {
574 format!("{}, ", self.suggestion_param_name)
575 } else if lifetime.ident.name == kw::UnderscoreLifetime
576 && lifetime.ident.span.is_empty()
577 {
578 format!("{} ", self.suggestion_param_name)
579 } else {
580 self.suggestion_param_name.clone()
581 }
582 };
583 match ty.kind {
584 hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
585 for segment in path.segments {
586 if let Some(args) = segment.args {
587 if args.args.iter().all(|arg| {
588 matches!(
589 arg,
590 hir::GenericArg::Lifetime(lifetime)
591 if lifetime.is_anon_in_path == IsAnonInPath::Yes
592 )
593 }) {
594 self.suggestions.push((
595 segment.ident.span.shrink_to_hi(),
596 format!(
597 "<{}>",
598 args.args
599 .iter()
600 .map(|_| self.suggestion_param_name.clone())
601 .collect::<Vec<_>>()
602 .join(", ")
603 ),
604 ));
605 } else {
606 for arg in args.args {
607 if let hir::GenericArg::Lifetime(lifetime) = arg
608 && lifetime.is_anonymous()
609 {
610 self.suggestions.push((
611 lifetime.ident.span,
612 make_suggestion(lifetime),
613 ));
614 }
615 }
616 }
617 }
618 }
619 }
620 hir::TyKind::Ref(lifetime, ..) if lifetime.is_anonymous() => {
621 self.suggestions.push((lifetime.ident.span, make_suggestion(lifetime)));
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, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
791 match self {
792 TyOrSig::Ty(ty) => ty.into_diag_arg(path),
793 TyOrSig::ClosureSig(sig) => sig.into_diag_arg(path),
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
1122#[derive(Diagnostic)]
1123#[diag(trait_selection_but_needs_to_satisfy, code = E0759)]
1124pub struct ButNeedsToSatisfy {
1125 #[primary_span]
1126 pub sp: Span,
1127 #[label(trait_selection_influencer)]
1128 pub influencer_point: Span,
1129 #[label(trait_selection_used_here)]
1130 pub spans: Vec<Span>,
1131 #[label(trait_selection_require)]
1132 pub require_span_as_label: Option<Span>,
1133 #[note(trait_selection_require)]
1134 pub require_span_as_note: Option<Span>,
1135 #[note(trait_selection_introduced_by_bound)]
1136 pub bound: Option<Span>,
1137
1138 pub has_param_name: bool,
1139 pub param_name: String,
1140 pub spans_empty: bool,
1141 pub has_lifetime: bool,
1142 pub lifetime: String,
1143}
1144
1145#[derive(Diagnostic)]
1146#[diag(trait_selection_outlives_content, code = E0312)]
1147pub struct OutlivesContent<'a> {
1148 #[primary_span]
1149 pub span: Span,
1150 #[subdiagnostic]
1151 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1152}
1153
1154#[derive(Diagnostic)]
1155#[diag(trait_selection_outlives_bound, code = E0476)]
1156pub struct OutlivesBound<'a> {
1157 #[primary_span]
1158 pub span: Span,
1159 #[subdiagnostic]
1160 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1161}
1162
1163#[derive(Diagnostic)]
1164#[diag(trait_selection_fulfill_req_lifetime, code = E0477)]
1165pub struct FulfillReqLifetime<'a> {
1166 #[primary_span]
1167 pub span: Span,
1168 pub ty: Ty<'a>,
1169 #[subdiagnostic]
1170 pub note: Option<note_and_explain::RegionExplanation<'a>>,
1171}
1172
1173#[derive(Diagnostic)]
1174#[diag(trait_selection_lf_bound_not_satisfied, code = E0478)]
1175pub struct LfBoundNotSatisfied<'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_ref_longer_than_data, code = E0491)]
1184pub struct RefLongerThanData<'a> {
1185 #[primary_span]
1186 pub span: Span,
1187 pub ty: Ty<'a>,
1188 #[subdiagnostic]
1189 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1190}
1191
1192#[derive(Subdiagnostic)]
1193pub enum WhereClauseSuggestions {
1194 #[suggestion(
1195 trait_selection_where_remove,
1196 code = "",
1197 applicability = "machine-applicable",
1198 style = "verbose"
1199 )]
1200 Remove {
1201 #[primary_span]
1202 span: Span,
1203 },
1204 #[suggestion(
1205 trait_selection_where_copy_predicates,
1206 code = "{space}where {trait_predicates}",
1207 applicability = "machine-applicable",
1208 style = "verbose"
1209 )]
1210 CopyPredicates {
1211 #[primary_span]
1212 span: Span,
1213 space: &'static str,
1214 trait_predicates: String,
1215 },
1216}
1217
1218#[derive(Subdiagnostic)]
1219pub enum SuggestRemoveSemiOrReturnBinding {
1220 #[multipart_suggestion(
1221 trait_selection_srs_remove_and_box,
1222 applicability = "machine-applicable"
1223 )]
1224 RemoveAndBox {
1225 #[suggestion_part(code = "Box::new(")]
1226 first_lo: Span,
1227 #[suggestion_part(code = ")")]
1228 first_hi: Span,
1229 #[suggestion_part(code = "Box::new(")]
1230 second_lo: Span,
1231 #[suggestion_part(code = ")")]
1232 second_hi: Span,
1233 #[suggestion_part(code = "")]
1234 sp: Span,
1235 },
1236 #[suggestion(
1237 trait_selection_srs_remove,
1238 style = "short",
1239 code = "",
1240 applicability = "machine-applicable"
1241 )]
1242 Remove {
1243 #[primary_span]
1244 sp: Span,
1245 },
1246 #[suggestion(
1247 trait_selection_srs_add,
1248 style = "verbose",
1249 code = "{code}",
1250 applicability = "maybe-incorrect"
1251 )]
1252 Add {
1253 #[primary_span]
1254 sp: Span,
1255 code: String,
1256 ident: Ident,
1257 },
1258 #[note(trait_selection_srs_add_one)]
1259 AddOne {
1260 #[primary_span]
1261 spans: MultiSpan,
1262 },
1263}
1264
1265#[derive(Subdiagnostic)]
1266pub enum ConsiderAddingAwait {
1267 #[help(trait_selection_await_both_futures)]
1268 BothFuturesHelp,
1269 #[multipart_suggestion(trait_selection_await_both_futures, applicability = "maybe-incorrect")]
1270 BothFuturesSugg {
1271 #[suggestion_part(code = ".await")]
1272 first: Span,
1273 #[suggestion_part(code = ".await")]
1274 second: Span,
1275 },
1276 #[suggestion(
1277 trait_selection_await_future,
1278 code = ".await",
1279 style = "verbose",
1280 applicability = "maybe-incorrect"
1281 )]
1282 FutureSugg {
1283 #[primary_span]
1284 span: Span,
1285 },
1286 #[note(trait_selection_await_note)]
1287 FutureSuggNote {
1288 #[primary_span]
1289 span: Span,
1290 },
1291 #[multipart_suggestion(
1292 trait_selection_await_future,
1293 style = "verbose",
1294 applicability = "maybe-incorrect"
1295 )]
1296 FutureSuggMultiple {
1297 #[suggestion_part(code = ".await")]
1298 spans: Vec<Span>,
1299 },
1300}
1301
1302#[derive(Diagnostic)]
1303pub enum PlaceholderRelationLfNotSatisfied {
1304 #[diag(trait_selection_lf_bound_not_satisfied)]
1305 HasBoth {
1306 #[primary_span]
1307 span: Span,
1308 #[note(trait_selection_prlf_defined_with_sub)]
1309 sub_span: Span,
1310 #[note(trait_selection_prlf_must_outlive_with_sup)]
1311 sup_span: Span,
1312 sub_symbol: Symbol,
1313 sup_symbol: Symbol,
1314 #[note(trait_selection_prlf_known_limitation)]
1315 note: (),
1316 },
1317 #[diag(trait_selection_lf_bound_not_satisfied)]
1318 HasSub {
1319 #[primary_span]
1320 span: Span,
1321 #[note(trait_selection_prlf_defined_with_sub)]
1322 sub_span: Span,
1323 #[note(trait_selection_prlf_must_outlive_without_sup)]
1324 sup_span: Span,
1325 sub_symbol: Symbol,
1326 #[note(trait_selection_prlf_known_limitation)]
1327 note: (),
1328 },
1329 #[diag(trait_selection_lf_bound_not_satisfied)]
1330 HasSup {
1331 #[primary_span]
1332 span: Span,
1333 #[note(trait_selection_prlf_defined_without_sub)]
1334 sub_span: Span,
1335 #[note(trait_selection_prlf_must_outlive_with_sup)]
1336 sup_span: Span,
1337 sup_symbol: Symbol,
1338 #[note(trait_selection_prlf_known_limitation)]
1339 note: (),
1340 },
1341 #[diag(trait_selection_lf_bound_not_satisfied)]
1342 HasNone {
1343 #[primary_span]
1344 span: Span,
1345 #[note(trait_selection_prlf_defined_without_sub)]
1346 sub_span: Span,
1347 #[note(trait_selection_prlf_must_outlive_without_sup)]
1348 sup_span: Span,
1349 #[note(trait_selection_prlf_known_limitation)]
1350 note: (),
1351 },
1352 #[diag(trait_selection_lf_bound_not_satisfied)]
1353 OnlyPrimarySpan {
1354 #[primary_span]
1355 span: Span,
1356 #[note(trait_selection_prlf_known_limitation)]
1357 note: (),
1358 },
1359}
1360
1361#[derive(Diagnostic)]
1362#[diag(trait_selection_opaque_captures_lifetime, code = E0700)]
1363pub struct OpaqueCapturesLifetime<'tcx> {
1364 #[primary_span]
1365 pub span: Span,
1366 #[label]
1367 pub opaque_ty_span: Span,
1368 pub opaque_ty: Ty<'tcx>,
1369}
1370
1371#[derive(Subdiagnostic)]
1372pub enum FunctionPointerSuggestion<'a> {
1373 #[suggestion(
1374 trait_selection_fps_use_ref,
1375 code = "&",
1376 style = "verbose",
1377 applicability = "maybe-incorrect"
1378 )]
1379 UseRef {
1380 #[primary_span]
1381 span: Span,
1382 },
1383 #[suggestion(
1384 trait_selection_fps_remove_ref,
1385 code = "{fn_name}",
1386 style = "verbose",
1387 applicability = "maybe-incorrect"
1388 )]
1389 RemoveRef {
1390 #[primary_span]
1391 span: Span,
1392 #[skip_arg]
1393 fn_name: String,
1394 },
1395 #[suggestion(
1396 trait_selection_fps_cast,
1397 code = "&({fn_name} as {sig})",
1398 style = "verbose",
1399 applicability = "maybe-incorrect"
1400 )]
1401 CastRef {
1402 #[primary_span]
1403 span: Span,
1404 #[skip_arg]
1405 fn_name: String,
1406 #[skip_arg]
1407 sig: Binder<'a, FnSig<'a>>,
1408 },
1409 #[suggestion(
1410 trait_selection_fps_cast,
1411 code = " as {sig}",
1412 style = "verbose",
1413 applicability = "maybe-incorrect"
1414 )]
1415 Cast {
1416 #[primary_span]
1417 span: Span,
1418 #[skip_arg]
1419 sig: Binder<'a, FnSig<'a>>,
1420 },
1421 #[suggestion(
1422 trait_selection_fps_cast_both,
1423 code = " as {found_sig}",
1424 style = "hidden",
1425 applicability = "maybe-incorrect"
1426 )]
1427 CastBoth {
1428 #[primary_span]
1429 span: Span,
1430 #[skip_arg]
1431 found_sig: Binder<'a, FnSig<'a>>,
1432 expected_sig: Binder<'a, FnSig<'a>>,
1433 },
1434 #[suggestion(
1435 trait_selection_fps_cast_both,
1436 code = "&({fn_name} as {found_sig})",
1437 style = "hidden",
1438 applicability = "maybe-incorrect"
1439 )]
1440 CastBothRef {
1441 #[primary_span]
1442 span: Span,
1443 #[skip_arg]
1444 fn_name: String,
1445 #[skip_arg]
1446 found_sig: Binder<'a, FnSig<'a>>,
1447 expected_sig: Binder<'a, FnSig<'a>>,
1448 },
1449}
1450
1451#[derive(Subdiagnostic)]
1452#[note(trait_selection_fps_items_are_distinct)]
1453pub struct FnItemsAreDistinct;
1454
1455#[derive(Subdiagnostic)]
1456#[note(trait_selection_fn_uniq_types)]
1457pub struct FnUniqTypes;
1458
1459#[derive(Subdiagnostic)]
1460#[help(trait_selection_fn_consider_casting)]
1461pub struct FnConsiderCasting {
1462 pub casting: String,
1463}
1464
1465#[derive(Subdiagnostic)]
1466#[help(trait_selection_fn_consider_casting_both)]
1467pub struct FnConsiderCastingBoth<'a> {
1468 pub sig: Binder<'a, FnSig<'a>>,
1469}
1470
1471#[derive(Subdiagnostic)]
1472pub enum SuggestAccessingField<'a> {
1473 #[suggestion(
1474 trait_selection_suggest_accessing_field,
1475 code = "{snippet}.{name}",
1476 applicability = "maybe-incorrect"
1477 )]
1478 Safe {
1479 #[primary_span]
1480 span: Span,
1481 snippet: String,
1482 name: Symbol,
1483 ty: Ty<'a>,
1484 },
1485 #[suggestion(
1486 trait_selection_suggest_accessing_field,
1487 code = "unsafe {{ {snippet}.{name} }}",
1488 applicability = "maybe-incorrect"
1489 )]
1490 Unsafe {
1491 #[primary_span]
1492 span: Span,
1493 snippet: String,
1494 name: Symbol,
1495 ty: Ty<'a>,
1496 },
1497}
1498
1499#[derive(Subdiagnostic)]
1500#[multipart_suggestion(trait_selection_stp_wrap_one, applicability = "maybe-incorrect")]
1501pub struct SuggestTuplePatternOne {
1502 pub variant: String,
1503 #[suggestion_part(code = "{variant}(")]
1504 pub span_low: Span,
1505 #[suggestion_part(code = ")")]
1506 pub span_high: Span,
1507}
1508
1509pub struct SuggestTuplePatternMany {
1510 pub path: String,
1511 pub cause_span: Span,
1512 pub compatible_variants: Vec<String>,
1513}
1514
1515impl Subdiagnostic for SuggestTuplePatternMany {
1516 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
1517 self,
1518 diag: &mut Diag<'_, G>,
1519 f: &F,
1520 ) {
1521 diag.arg("path", self.path);
1522 let message = f(diag, crate::fluent_generated::trait_selection_stp_wrap_many.into());
1523 diag.multipart_suggestions(
1524 message,
1525 self.compatible_variants.into_iter().map(|variant| {
1526 vec![
1527 (self.cause_span.shrink_to_lo(), format!("{variant}(")),
1528 (self.cause_span.shrink_to_hi(), ")".to_string()),
1529 ]
1530 }),
1531 rustc_errors::Applicability::MaybeIncorrect,
1532 );
1533 }
1534}
1535
1536#[derive(Subdiagnostic)]
1537pub enum TypeErrorAdditionalDiags {
1538 #[suggestion(
1539 trait_selection_meant_byte_literal,
1540 code = "b'{code}'",
1541 applicability = "machine-applicable"
1542 )]
1543 MeantByteLiteral {
1544 #[primary_span]
1545 span: Span,
1546 code: String,
1547 },
1548 #[suggestion(
1549 trait_selection_meant_char_literal,
1550 code = "'{code}'",
1551 applicability = "machine-applicable"
1552 )]
1553 MeantCharLiteral {
1554 #[primary_span]
1555 span: Span,
1556 code: String,
1557 },
1558 #[multipart_suggestion(trait_selection_meant_str_literal, applicability = "machine-applicable")]
1559 MeantStrLiteral {
1560 #[suggestion_part(code = "\"")]
1561 start: Span,
1562 #[suggestion_part(code = "\"")]
1563 end: Span,
1564 },
1565 #[suggestion(
1566 trait_selection_consider_specifying_length,
1567 code = "{length}",
1568 applicability = "maybe-incorrect"
1569 )]
1570 ConsiderSpecifyingLength {
1571 #[primary_span]
1572 span: Span,
1573 length: u64,
1574 },
1575 #[note(trait_selection_try_cannot_convert)]
1576 TryCannotConvert { found: String, expected: String },
1577 #[suggestion(
1578 trait_selection_tuple_trailing_comma,
1579 code = ",",
1580 applicability = "machine-applicable"
1581 )]
1582 TupleOnlyComma {
1583 #[primary_span]
1584 span: Span,
1585 },
1586 #[multipart_suggestion(
1587 trait_selection_tuple_trailing_comma,
1588 applicability = "machine-applicable"
1589 )]
1590 TupleAlsoParentheses {
1591 #[suggestion_part(code = "(")]
1592 span_low: Span,
1593 #[suggestion_part(code = ",)")]
1594 span_high: Span,
1595 },
1596 #[suggestion(
1597 trait_selection_suggest_add_let_for_letchains,
1598 style = "verbose",
1599 applicability = "machine-applicable",
1600 code = "let "
1601 )]
1602 AddLetForLetChains {
1603 #[primary_span]
1604 span: Span,
1605 },
1606}
1607
1608#[derive(Diagnostic)]
1609pub enum ObligationCauseFailureCode {
1610 #[diag(trait_selection_oc_method_compat, code = E0308)]
1611 MethodCompat {
1612 #[primary_span]
1613 span: Span,
1614 #[subdiagnostic]
1615 subdiags: Vec<TypeErrorAdditionalDiags>,
1616 },
1617 #[diag(trait_selection_oc_type_compat, code = E0308)]
1618 TypeCompat {
1619 #[primary_span]
1620 span: Span,
1621 #[subdiagnostic]
1622 subdiags: Vec<TypeErrorAdditionalDiags>,
1623 },
1624 #[diag(trait_selection_oc_const_compat, code = E0308)]
1625 ConstCompat {
1626 #[primary_span]
1627 span: Span,
1628 #[subdiagnostic]
1629 subdiags: Vec<TypeErrorAdditionalDiags>,
1630 },
1631 #[diag(trait_selection_oc_try_compat, code = E0308)]
1632 TryCompat {
1633 #[primary_span]
1634 span: Span,
1635 #[subdiagnostic]
1636 subdiags: Vec<TypeErrorAdditionalDiags>,
1637 },
1638 #[diag(trait_selection_oc_match_compat, code = E0308)]
1639 MatchCompat {
1640 #[primary_span]
1641 span: Span,
1642 #[subdiagnostic]
1643 subdiags: Vec<TypeErrorAdditionalDiags>,
1644 },
1645 #[diag(trait_selection_oc_if_else_different, code = E0308)]
1646 IfElseDifferent {
1647 #[primary_span]
1648 span: Span,
1649 #[subdiagnostic]
1650 subdiags: Vec<TypeErrorAdditionalDiags>,
1651 },
1652 #[diag(trait_selection_oc_no_else, code = E0317)]
1653 NoElse {
1654 #[primary_span]
1655 span: Span,
1656 },
1657 #[diag(trait_selection_oc_no_diverge, code = E0308)]
1658 NoDiverge {
1659 #[primary_span]
1660 span: Span,
1661 #[subdiagnostic]
1662 subdiags: Vec<TypeErrorAdditionalDiags>,
1663 },
1664 #[diag(trait_selection_oc_fn_main_correct_type, code = E0580)]
1665 FnMainCorrectType {
1666 #[primary_span]
1667 span: Span,
1668 },
1669 #[diag(trait_selection_oc_fn_lang_correct_type, code = E0308)]
1670 FnLangCorrectType {
1671 #[primary_span]
1672 span: Span,
1673 #[subdiagnostic]
1674 subdiags: Vec<TypeErrorAdditionalDiags>,
1675 lang_item_name: Symbol,
1676 },
1677 #[diag(trait_selection_oc_intrinsic_correct_type, code = E0308)]
1678 IntrinsicCorrectType {
1679 #[primary_span]
1680 span: Span,
1681 #[subdiagnostic]
1682 subdiags: Vec<TypeErrorAdditionalDiags>,
1683 },
1684 #[diag(trait_selection_oc_method_correct_type, code = E0308)]
1685 MethodCorrectType {
1686 #[primary_span]
1687 span: Span,
1688 #[subdiagnostic]
1689 subdiags: Vec<TypeErrorAdditionalDiags>,
1690 },
1691 #[diag(trait_selection_oc_closure_selfref, code = E0644)]
1692 ClosureSelfref {
1693 #[primary_span]
1694 span: Span,
1695 },
1696 #[diag(trait_selection_oc_cant_coerce_force_inline, code = E0308)]
1697 CantCoerceForceInline {
1698 #[primary_span]
1699 span: Span,
1700 #[subdiagnostic]
1701 subdiags: Vec<TypeErrorAdditionalDiags>,
1702 },
1703 #[diag(trait_selection_oc_cant_coerce_intrinsic, code = E0308)]
1704 CantCoerceIntrinsic {
1705 #[primary_span]
1706 span: Span,
1707 #[subdiagnostic]
1708 subdiags: Vec<TypeErrorAdditionalDiags>,
1709 },
1710 #[diag(trait_selection_oc_generic, code = E0308)]
1711 Generic {
1712 #[primary_span]
1713 span: Span,
1714 #[subdiagnostic]
1715 subdiags: Vec<TypeErrorAdditionalDiags>,
1716 },
1717}
1718
1719#[derive(Subdiagnostic)]
1720pub enum AddPreciseCapturing {
1721 #[suggestion(
1722 trait_selection_precise_capturing_new,
1723 style = "verbose",
1724 code = " + use<{concatenated_bounds}>",
1725 applicability = "machine-applicable"
1726 )]
1727 New {
1728 #[primary_span]
1729 span: Span,
1730 new_lifetime: Symbol,
1731 concatenated_bounds: String,
1732 },
1733 #[suggestion(
1734 trait_selection_precise_capturing_existing,
1735 style = "verbose",
1736 code = "{pre}{new_lifetime}{post}",
1737 applicability = "machine-applicable"
1738 )]
1739 Existing {
1740 #[primary_span]
1741 span: Span,
1742 new_lifetime: Symbol,
1743 pre: &'static str,
1744 post: &'static str,
1745 },
1746}
1747
1748pub struct AddPreciseCapturingAndParams {
1749 pub suggs: Vec<(Span, String)>,
1750 pub new_lifetime: Symbol,
1751 pub apit_spans: Vec<Span>,
1752}
1753
1754impl Subdiagnostic for AddPreciseCapturingAndParams {
1755 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
1756 self,
1757 diag: &mut Diag<'_, G>,
1758 _f: &F,
1759 ) {
1760 diag.arg("new_lifetime", self.new_lifetime);
1761 diag.multipart_suggestion_verbose(
1762 fluent::trait_selection_precise_capturing_new_but_apit,
1763 self.suggs,
1764 Applicability::MaybeIncorrect,
1765 );
1766 diag.span_note(
1767 self.apit_spans,
1768 fluent::trait_selection_warn_removing_apit_params_for_undercapture,
1769 );
1770 }
1771}
1772
1773pub fn impl_trait_overcapture_suggestion<'tcx>(
1778 tcx: TyCtxt<'tcx>,
1779 opaque_def_id: LocalDefId,
1780 fn_def_id: LocalDefId,
1781 captured_args: FxIndexSet<DefId>,
1782) -> Option<AddPreciseCapturingForOvercapture> {
1783 let generics = tcx.generics_of(fn_def_id);
1784
1785 let mut captured_lifetimes = FxIndexSet::default();
1786 let mut captured_non_lifetimes = FxIndexSet::default();
1787 let mut synthetics = vec![];
1788
1789 for arg in captured_args {
1790 if tcx.def_kind(arg) == DefKind::LifetimeParam {
1791 captured_lifetimes.insert(tcx.item_name(arg));
1792 } else {
1793 let idx = generics.param_def_id_to_index(tcx, arg).expect("expected arg in scope");
1794 let param = generics.param_at(idx as usize, tcx);
1795 if param.kind.is_synthetic() {
1796 synthetics.push((tcx.def_span(arg), param.name));
1797 } else {
1798 captured_non_lifetimes.insert(tcx.item_name(arg));
1799 }
1800 }
1801 }
1802
1803 let mut next_fresh_param = || {
1804 ["T", "U", "V", "W", "X", "Y", "A", "B", "C"]
1805 .into_iter()
1806 .map(Symbol::intern)
1807 .chain((0..).map(|i| Symbol::intern(&format!("T{i}"))))
1808 .find(|s| captured_non_lifetimes.insert(*s))
1809 .unwrap()
1810 };
1811
1812 let mut suggs = vec![];
1813 let mut apit_spans = vec![];
1814
1815 if !synthetics.is_empty() {
1816 let mut new_params = String::new();
1817 for (i, (span, name)) in synthetics.into_iter().enumerate() {
1818 apit_spans.push(span);
1819
1820 let fresh_param = next_fresh_param();
1821
1822 suggs.push((span, fresh_param.to_string()));
1824
1825 if i > 0 {
1833 new_params += ", ";
1834 }
1835 let name_as_bounds = name.as_str().trim_start_matches("impl").trim_start();
1836 new_params += fresh_param.as_str();
1837 new_params += ": ";
1838 new_params += name_as_bounds;
1839 }
1840
1841 let Some(generics) = tcx.hir_get_generics(fn_def_id) else {
1842 return None;
1844 };
1845
1846 suggs.push(if let Some(params_span) = generics.span_for_param_suggestion() {
1848 (params_span, format!(", {new_params}"))
1849 } else {
1850 (generics.span, format!("<{new_params}>"))
1851 });
1852 }
1853
1854 let concatenated_bounds = captured_lifetimes
1855 .into_iter()
1856 .chain(captured_non_lifetimes)
1857 .map(|sym| sym.to_string())
1858 .collect::<Vec<_>>()
1859 .join(", ");
1860
1861 let opaque_hir_id = tcx.local_def_id_to_hir_id(opaque_def_id);
1862 let (lparen, rparen) = match tcx
1864 .hir_parent_iter(opaque_hir_id)
1865 .nth(1)
1866 .expect("expected ty to have a parent always")
1867 .1
1868 {
1869 Node::PathSegment(segment)
1870 if segment.args().paren_sugar_output().is_some_and(|ty| ty.hir_id == opaque_hir_id) =>
1871 {
1872 ("(", ")")
1873 }
1874 Node::Ty(ty) => match ty.kind {
1875 rustc_hir::TyKind::Ptr(_) | rustc_hir::TyKind::Ref(..) => ("(", ")"),
1876 _ => ("", ""),
1880 },
1881 _ => ("", ""),
1882 };
1883
1884 let rpit_span = tcx.def_span(opaque_def_id);
1885 if !lparen.is_empty() {
1886 suggs.push((rpit_span.shrink_to_lo(), lparen.to_string()));
1887 }
1888 suggs.push((rpit_span.shrink_to_hi(), format!(" + use<{concatenated_bounds}>{rparen}")));
1889
1890 Some(AddPreciseCapturingForOvercapture { suggs, apit_spans })
1891}
1892
1893pub struct AddPreciseCapturingForOvercapture {
1894 pub suggs: Vec<(Span, String)>,
1895 pub apit_spans: Vec<Span>,
1896}
1897
1898impl Subdiagnostic for AddPreciseCapturingForOvercapture {
1899 fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
1900 self,
1901 diag: &mut Diag<'_, G>,
1902 _f: &F,
1903 ) {
1904 let applicability = if self.apit_spans.is_empty() {
1905 Applicability::MachineApplicable
1906 } else {
1907 Applicability::MaybeIncorrect
1911 };
1912 diag.multipart_suggestion_verbose(
1913 fluent::trait_selection_precise_capturing_overcaptures,
1914 self.suggs,
1915 applicability,
1916 );
1917 if !self.apit_spans.is_empty() {
1918 diag.span_note(
1919 self.apit_spans,
1920 fluent::trait_selection_warn_removing_apit_params_for_overcapture,
1921 );
1922 }
1923 }
1924}