1use std::path::PathBuf;
2
3use rustc_ast::Path;
4use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
5use rustc_errors::codes::*;
6use rustc_errors::{
7 Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic,
8 EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic,
9};
10use rustc_hir::def::DefKind;
11use rustc_hir::def_id::{DefId, LocalDefId};
12use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty};
13use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, Node};
14use rustc_macros::{Diagnostic, Subdiagnostic};
15use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
16use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, GenericArg, Region, Ty, TyCtxt};
17use rustc_span::{BytePos, Ident, Span, Symbol, kw};
18
19use crate::error_reporting::infer::ObligationCauseAsDiagArg;
20use crate::error_reporting::infer::need_type_info::UnderspecifiedArgKind;
21use crate::error_reporting::infer::nice_region_error::placeholder_error::Highlighted;
22use crate::fluent_generated as fluent;
23
24pub mod note_and_explain;
25
26#[derive(Diagnostic)]
27#[diag(trait_selection_unable_to_construct_constant_value)]
28pub struct UnableToConstructConstantValue<'a> {
29 #[primary_span]
30 pub span: Span,
31 pub unevaluated: ty::UnevaluatedConst<'a>,
32}
33
34#[derive(Diagnostic)]
35pub enum InvalidOnClause {
36 #[diag(trait_selection_rustc_on_unimplemented_empty_on_clause, code = E0232)]
37 Empty {
38 #[primary_span]
39 #[label]
40 span: Span,
41 },
42 #[diag(trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not, code = E0232)]
43 ExpectedOnePredInNot {
44 #[primary_span]
45 #[label]
46 span: Span,
47 },
48 #[diag(trait_selection_rustc_on_unimplemented_unsupported_literal_in_on, code = E0232)]
49 UnsupportedLiteral {
50 #[primary_span]
51 #[label]
52 span: Span,
53 },
54 #[diag(trait_selection_rustc_on_unimplemented_expected_identifier, code = E0232)]
55 ExpectedIdentifier {
56 #[primary_span]
57 #[label]
58 span: Span,
59 path: Path,
60 },
61 #[diag(trait_selection_rustc_on_unimplemented_invalid_predicate, code = E0232)]
62 InvalidPredicate {
63 #[primary_span]
64 #[label]
65 span: Span,
66 invalid_pred: Symbol,
67 },
68 #[diag(trait_selection_rustc_on_unimplemented_invalid_flag, code = E0232)]
69 InvalidFlag {
70 #[primary_span]
71 #[label]
72 span: Span,
73 invalid_flag: Symbol,
74 },
75 #[diag(trait_selection_rustc_on_unimplemented_invalid_name, code = E0232)]
76 InvalidName {
77 #[primary_span]
78 #[label]
79 span: Span,
80 invalid_name: Symbol,
81 },
82}
83
84#[derive(Diagnostic)]
85#[diag(trait_selection_rustc_on_unimplemented_missing_value, code = E0232)]
86#[note]
87pub struct NoValueInOnUnimplemented {
88 #[primary_span]
89 #[label]
90 pub span: Span,
91}
92
93pub struct NegativePositiveConflict<'tcx> {
94 pub impl_span: Span,
95 pub trait_desc: ty::TraitRef<'tcx>,
96 pub self_ty: Option<Ty<'tcx>>,
97 pub negative_impl_span: Result<Span, Symbol>,
98 pub positive_impl_span: Result<Span, Symbol>,
99}
100
101impl<G: EmissionGuarantee> Diagnostic<'_, G> for NegativePositiveConflict<'_> {
102 #[track_caller]
103 fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
104 let mut diag = Diag::new(dcx, level, fluent::trait_selection_negative_positive_conflict);
105 diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string());
106 diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string()));
107 diag.span(self.impl_span);
108 diag.code(E0751);
109 match self.negative_impl_span {
110 Ok(span) => {
111 diag.span_label(span, fluent::trait_selection_negative_implementation_here);
112 }
113 Err(cname) => {
114 diag.note(fluent::trait_selection_negative_implementation_in_crate);
115 diag.arg("negative_impl_cname", cname.to_string());
116 }
117 }
118 match self.positive_impl_span {
119 Ok(span) => {
120 diag.span_label(span, fluent::trait_selection_positive_implementation_here);
121 }
122 Err(cname) => {
123 diag.note(fluent::trait_selection_positive_implementation_in_crate);
124 diag.arg("positive_impl_cname", cname.to_string());
125 }
126 }
127 diag
128 }
129}
130
131#[derive(Diagnostic)]
132#[diag(trait_selection_inherent_projection_normalization_overflow)]
133pub struct InherentProjectionNormalizationOverflow {
134 #[primary_span]
135 pub span: Span,
136 pub ty: String,
137}
138
139pub enum AdjustSignatureBorrow {
140 Borrow { to_borrow: Vec<(Span, String)> },
141 RemoveBorrow { remove_borrow: Vec<(Span, String)> },
142}
143
144impl Subdiagnostic for AdjustSignatureBorrow {
145 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
146 match self {
147 AdjustSignatureBorrow::Borrow { to_borrow } => {
148 diag.arg("len", to_borrow.len());
149 diag.multipart_suggestion_verbose(
150 fluent::trait_selection_adjust_signature_borrow,
151 to_borrow,
152 Applicability::MaybeIncorrect,
153 );
154 }
155 AdjustSignatureBorrow::RemoveBorrow { remove_borrow } => {
156 diag.arg("len", remove_borrow.len());
157 diag.multipart_suggestion_verbose(
158 fluent::trait_selection_adjust_signature_remove_borrow,
159 remove_borrow,
160 Applicability::MaybeIncorrect,
161 );
162 }
163 }
164 }
165}
166
167#[derive(Diagnostic)]
168#[diag(trait_selection_closure_kind_mismatch, code = E0525)]
169pub struct ClosureKindMismatch {
170 #[primary_span]
171 #[label]
172 pub closure_span: Span,
173 pub expected: ClosureKind,
174 pub found: ClosureKind,
175 #[label(trait_selection_closure_kind_requirement)]
176 pub cause_span: Span,
177
178 pub trait_prefix: &'static str,
179
180 #[subdiagnostic]
181 pub fn_once_label: Option<ClosureFnOnceLabel>,
182
183 #[subdiagnostic]
184 pub fn_mut_label: Option<ClosureFnMutLabel>,
185}
186
187#[derive(Subdiagnostic)]
188#[label(trait_selection_closure_fn_once_label)]
189pub struct ClosureFnOnceLabel {
190 #[primary_span]
191 pub span: Span,
192 pub place: String,
193}
194
195#[derive(Subdiagnostic)]
196#[label(trait_selection_closure_fn_mut_label)]
197pub struct ClosureFnMutLabel {
198 #[primary_span]
199 pub span: Span,
200 pub place: String,
201}
202
203#[derive(Diagnostic)]
204#[diag(trait_selection_async_closure_not_fn)]
205pub(crate) struct AsyncClosureNotFn {
206 #[primary_span]
207 pub span: Span,
208 pub kind: &'static str,
209}
210
211#[derive(Diagnostic)]
212#[diag(trait_selection_type_annotations_needed, code = E0282)]
213pub struct AnnotationRequired<'a> {
214 #[primary_span]
215 pub span: Span,
216 pub source_kind: &'static str,
217 pub source_name: &'a str,
218 #[label]
219 pub failure_span: Option<Span>,
220 #[subdiagnostic]
221 pub bad_label: Option<InferenceBadError<'a>>,
222 #[subdiagnostic]
223 pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
224 #[subdiagnostic]
225 pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
226 #[note(trait_selection_full_type_written)]
227 pub was_written: bool,
228 pub path: PathBuf,
229}
230
231#[derive(Diagnostic)]
233#[diag(trait_selection_type_annotations_needed, code = E0283)]
234pub struct AmbiguousImpl<'a> {
235 #[primary_span]
236 pub span: Span,
237 pub source_kind: &'static str,
238 pub source_name: &'a str,
239 #[label]
240 pub failure_span: Option<Span>,
241 #[subdiagnostic]
242 pub bad_label: Option<InferenceBadError<'a>>,
243 #[subdiagnostic]
244 pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
245 #[subdiagnostic]
246 pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
247 #[note(trait_selection_full_type_written)]
248 pub was_written: bool,
249 pub path: PathBuf,
250}
251
252#[derive(Diagnostic)]
254#[diag(trait_selection_type_annotations_needed, code = E0284)]
255pub struct AmbiguousReturn<'a> {
256 #[primary_span]
257 pub span: Span,
258 pub source_kind: &'static str,
259 pub source_name: &'a str,
260 #[label]
261 pub failure_span: Option<Span>,
262 #[subdiagnostic]
263 pub bad_label: Option<InferenceBadError<'a>>,
264 #[subdiagnostic]
265 pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
266 #[subdiagnostic]
267 pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
268 #[note(trait_selection_full_type_written)]
269 pub was_written: bool,
270 pub path: PathBuf,
271}
272
273#[derive(Subdiagnostic)]
275#[label(trait_selection_label_bad)]
276pub struct InferenceBadError<'a> {
277 #[primary_span]
278 pub span: Span,
279 pub bad_kind: &'static str,
280 pub prefix_kind: UnderspecifiedArgKind,
281 pub has_parent: bool,
282 pub prefix: &'a str,
283 pub parent_prefix: &'a str,
284 pub parent_name: String,
285 pub name: String,
286}
287
288#[derive(Subdiagnostic)]
289pub enum SourceKindSubdiag<'a> {
290 #[suggestion(
291 trait_selection_source_kind_subdiag_let,
292 style = "verbose",
293 code = ": {type_name}",
294 applicability = "has-placeholders"
295 )]
296 LetLike {
297 #[primary_span]
298 span: Span,
299 name: String,
300 type_name: String,
301 kind: &'static str,
302 x_kind: &'static str,
303 prefix_kind: UnderspecifiedArgKind,
304 prefix: &'a str,
305 arg_name: String,
306 },
307 #[label(trait_selection_source_kind_subdiag_generic_label)]
308 GenericLabel {
309 #[primary_span]
310 span: Span,
311 is_type: bool,
312 param_name: String,
313 parent_exists: bool,
314 parent_prefix: String,
315 parent_name: String,
316 },
317 #[suggestion(
318 trait_selection_source_kind_subdiag_generic_suggestion,
319 style = "verbose",
320 code = "::<{args}>",
321 applicability = "has-placeholders"
322 )]
323 GenericSuggestion {
324 #[primary_span]
325 span: Span,
326 arg_count: usize,
327 args: String,
328 },
329}
330
331#[derive(Subdiagnostic)]
332pub enum SourceKindMultiSuggestion<'a> {
333 #[multipart_suggestion(
334 trait_selection_source_kind_fully_qualified,
335 style = "verbose",
336 applicability = "has-placeholders"
337 )]
338 FullyQualified {
339 #[suggestion_part(code = "{def_path}({adjustment}")]
340 span_lo: Span,
341 #[suggestion_part(code = "{successor_pos}")]
342 span_hi: Span,
343 def_path: String,
344 adjustment: &'a str,
345 successor_pos: &'a str,
346 },
347 #[multipart_suggestion(
348 trait_selection_source_kind_closure_return,
349 style = "verbose",
350 applicability = "has-placeholders"
351 )]
352 ClosureReturn {
353 #[suggestion_part(code = "{start_span_code}")]
354 start_span: Span,
355 start_span_code: String,
356 #[suggestion_part(code = " }}")]
357 end_span: Option<Span>,
358 },
359}
360
361impl<'a> SourceKindMultiSuggestion<'a> {
362 pub fn new_fully_qualified(
363 span: Span,
364 def_path: String,
365 adjustment: &'a str,
366 successor: (&'a str, BytePos),
367 ) -> Self {
368 Self::FullyQualified {
369 span_lo: span.shrink_to_lo(),
370 span_hi: span.shrink_to_hi().with_hi(successor.1),
371 def_path,
372 adjustment,
373 successor_pos: successor.0,
374 }
375 }
376
377 pub fn new_closure_return(
378 ty_info: String,
379 data: &'a FnRetTy<'a>,
380 should_wrap_expr: Option<Span>,
381 ) -> Self {
382 let arrow = match data {
383 FnRetTy::DefaultReturn(_) => " -> ",
384 _ => "",
385 };
386 let (start_span, start_span_code, end_span) = match should_wrap_expr {
387 Some(end_span) => (data.span(), format!("{arrow}{ty_info} {{"), Some(end_span)),
388 None => (data.span(), format!("{arrow}{ty_info}"), None),
389 };
390 Self::ClosureReturn { start_span, start_span_code, end_span }
391 }
392}
393
394pub enum RegionOriginNote<'a> {
395 Plain {
396 span: Span,
397 msg: DiagMessage,
398 },
399 WithName {
400 span: Span,
401 msg: DiagMessage,
402 name: &'a str,
403 continues: bool,
404 },
405 WithRequirement {
406 span: Span,
407 requirement: ObligationCauseAsDiagArg<'a>,
408 expected_found: Option<(DiagStyledString, DiagStyledString)>,
409 },
410}
411
412impl Subdiagnostic for RegionOriginNote<'_> {
413 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
414 let mut label_or_note = |span, msg: DiagMessage| {
415 let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
416 let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
417 let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span);
418 if span_is_primary && sub_count == 0 && expanded_sub_count == 0 {
419 diag.span_label(span, msg);
420 } else if span_is_primary && expanded_sub_count == 0 {
421 diag.note(msg);
422 } else {
423 diag.span_note(span, msg);
424 }
425 };
426 match self {
427 RegionOriginNote::Plain { span, msg } => {
428 label_or_note(span, msg);
429 }
430 RegionOriginNote::WithName { span, msg, name, continues } => {
431 label_or_note(span, msg);
432 diag.arg("name", name);
433 diag.arg("continues", continues);
434 }
435 RegionOriginNote::WithRequirement {
436 span,
437 requirement,
438 expected_found: Some((expected, found)),
439 } => {
440 label_or_note(span, fluent::trait_selection_subtype);
441 diag.arg("requirement", requirement);
442
443 diag.note_expected_found("", expected, "", found);
444 }
445 RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => {
446 label_or_note(span, fluent::trait_selection_subtype_2);
450 diag.arg("requirement", requirement);
451 }
452 };
453 }
454}
455
456pub enum LifetimeMismatchLabels {
457 InRet {
458 param_span: Span,
459 ret_span: Span,
460 span: Span,
461 label_var1: Option<Ident>,
462 },
463 Normal {
464 hir_equal: bool,
465 ty_sup: Span,
466 ty_sub: Span,
467 span: Span,
468 sup: Option<Ident>,
469 sub: Option<Ident>,
470 },
471}
472
473impl Subdiagnostic for LifetimeMismatchLabels {
474 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
475 match self {
476 LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
477 diag.span_label(param_span, fluent::trait_selection_declared_different);
478 diag.span_label(ret_span, fluent::trait_selection_nothing);
479 diag.span_label(span, fluent::trait_selection_data_returned);
480 diag.arg("label_var1_exists", label_var1.is_some());
481 diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
482 }
483 LifetimeMismatchLabels::Normal {
484 hir_equal,
485 ty_sup,
486 ty_sub,
487 span,
488 sup: label_var1,
489 sub: label_var2,
490 } => {
491 if hir_equal {
492 diag.span_label(ty_sup, fluent::trait_selection_declared_multiple);
493 diag.span_label(ty_sub, fluent::trait_selection_nothing);
494 diag.span_label(span, fluent::trait_selection_data_lifetime_flow);
495 } else {
496 diag.span_label(ty_sup, fluent::trait_selection_types_declared_different);
497 diag.span_label(ty_sub, fluent::trait_selection_nothing);
498 diag.span_label(span, fluent::trait_selection_data_flows);
499 diag.arg("label_var1_exists", label_var1.is_some());
500 diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
501 diag.arg("label_var2_exists", label_var2.is_some());
502 diag.arg("label_var2", label_var2.map(|x| x.to_string()).unwrap_or_default());
503 }
504 }
505 }
506 }
507}
508
509pub struct AddLifetimeParamsSuggestion<'a> {
510 pub tcx: TyCtxt<'a>,
511 pub generic_param_scope: LocalDefId,
512 pub sub: Region<'a>,
513 pub ty_sup: &'a hir::Ty<'a>,
514 pub ty_sub: &'a hir::Ty<'a>,
515 pub add_note: bool,
516}
517
518impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
519 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
520 let mut mk_suggestion = || {
521 let Some(anon_reg) = self.tcx.is_suitable_region(self.generic_param_scope, self.sub)
522 else {
523 return false;
524 };
525
526 let node = self.tcx.hir_node_by_def_id(anon_reg.scope);
527 let is_impl = matches!(&node, hir::Node::ImplItem(_));
528 let (generics, parent_generics) = match node {
529 hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. })
530 | hir::Node::TraitItem(hir::TraitItem { generics, .. })
531 | hir::Node::ImplItem(hir::ImplItem { generics, .. }) => (
532 generics,
533 match self.tcx.parent_hir_node(self.tcx.local_def_id_to_hir_id(anon_reg.scope))
534 {
535 hir::Node::Item(hir::Item {
536 kind: hir::ItemKind::Trait(_, _, _, generics, ..),
537 ..
538 })
539 | hir::Node::Item(hir::Item {
540 kind: hir::ItemKind::Impl(hir::Impl { generics, .. }),
541 ..
542 }) => Some(generics),
543 _ => None,
544 },
545 ),
546 _ => return false,
547 };
548
549 let suggestion_param_name = generics
550 .params
551 .iter()
552 .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
553 .map(|p| p.name.ident().name)
554 .find(|i| *i != kw::UnderscoreLifetime);
555 let introduce_new = suggestion_param_name.is_none();
556
557 let mut default = "'a".to_string();
558 if let Some(parent_generics) = parent_generics {
559 let used: FxHashSet<_> = parent_generics
560 .params
561 .iter()
562 .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
563 .map(|p| p.name.ident().name)
564 .filter(|i| *i != kw::UnderscoreLifetime)
565 .map(|l| l.to_string())
566 .collect();
567 if let Some(lt) =
568 ('a'..='z').map(|it| format!("'{it}")).find(|it| !used.contains(it))
569 {
570 default = lt;
575 }
576 }
577 let suggestion_param_name =
578 suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| default);
579
580 struct ImplicitLifetimeFinder {
581 suggestions: Vec<(Span, String)>,
582 suggestion_param_name: String,
583 }
584
585 impl<'v> Visitor<'v> for ImplicitLifetimeFinder {
586 fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
587 match ty.kind {
588 hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
589 for segment in path.segments {
590 if let Some(args) = segment.args {
591 if args.args.iter().all(|arg| {
592 matches!(
593 arg,
594 hir::GenericArg::Lifetime(lifetime)
595 if lifetime.is_syntactically_hidden()
596 )
597 }) {
598 self.suggestions.push((
599 segment.ident.span.shrink_to_hi(),
600 format!(
601 "<{}>",
602 args.args
603 .iter()
604 .map(|_| self.suggestion_param_name.clone())
605 .collect::<Vec<_>>()
606 .join(", ")
607 ),
608 ));
609 } else {
610 for arg in args.args {
611 if let hir::GenericArg::Lifetime(lifetime) = arg
612 && lifetime.is_anonymous()
613 {
614 self.suggestions.push(
615 lifetime
616 .suggestion(&self.suggestion_param_name),
617 );
618 }
619 }
620 }
621 }
622 }
623 }
624 hir::TyKind::Ref(lifetime, ..) if lifetime.is_anonymous() => {
625 self.suggestions.push(lifetime.suggestion(&self.suggestion_param_name));
626 }
627 _ => {}
628 }
629 walk_ty(self, ty);
630 }
631 }
632 let mut visitor = ImplicitLifetimeFinder {
633 suggestions: vec![],
634 suggestion_param_name: suggestion_param_name.clone(),
635 };
636 if let Some(fn_decl) = node.fn_decl()
637 && let hir::FnRetTy::Return(ty) = fn_decl.output
638 {
639 visitor.visit_ty_unambig(ty);
640 }
641 if visitor.suggestions.is_empty() {
642 visitor.visit_ty_unambig(self.ty_sup);
647 }
648 visitor.visit_ty_unambig(self.ty_sub);
649 if visitor.suggestions.is_empty() {
650 return false;
651 }
652 if introduce_new {
653 let new_param_suggestion = if let Some(first) =
654 generics.params.iter().find(|p| !p.name.ident().span.is_empty())
655 {
656 (first.span.shrink_to_lo(), format!("{suggestion_param_name}, "))
657 } else {
658 (generics.span, format!("<{suggestion_param_name}>"))
659 };
660
661 visitor.suggestions.push(new_param_suggestion);
662 }
663 diag.multipart_suggestion_verbose(
664 fluent::trait_selection_lifetime_param_suggestion,
665 visitor.suggestions,
666 Applicability::MaybeIncorrect,
667 );
668 diag.arg("is_impl", is_impl);
669 diag.arg("is_reuse", !introduce_new);
670
671 true
672 };
673 if mk_suggestion() && self.add_note {
674 diag.note(fluent::trait_selection_lifetime_param_suggestion_elided);
675 }
676 }
677}
678
679#[derive(Diagnostic)]
680#[diag(trait_selection_lifetime_mismatch, code = E0623)]
681pub struct LifetimeMismatch<'a> {
682 #[primary_span]
683 pub span: Span,
684 #[subdiagnostic]
685 pub labels: LifetimeMismatchLabels,
686 #[subdiagnostic]
687 pub suggestion: AddLifetimeParamsSuggestion<'a>,
688}
689
690pub struct IntroducesStaticBecauseUnmetLifetimeReq {
691 pub unmet_requirements: MultiSpan,
692 pub binding_span: Span,
693}
694
695impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
696 fn add_to_diag<G: EmissionGuarantee>(mut self, diag: &mut Diag<'_, G>) {
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<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1012 let mut type_param_span: MultiSpan = self.spans.clone().into();
1013 for &span in &self.spans {
1014 type_param_span.push_span_label(span, fluent::trait_selection_tid_consider_borrowing);
1016 }
1017 let msg = diag.eagerly_translate(fluent::trait_selection_tid_param_help);
1018 diag.span_help(type_param_span, msg);
1019 }
1020}
1021
1022#[derive(Subdiagnostic)]
1023#[help(trait_selection_tid_rel_help)]
1024pub struct RelationshipHelp;
1025
1026#[derive(Diagnostic)]
1027#[diag(trait_selection_trait_impl_diff)]
1028pub struct TraitImplDiff {
1029 #[primary_span]
1030 #[label(trait_selection_found)]
1031 pub sp: Span,
1032 #[label(trait_selection_expected)]
1033 pub trait_sp: Span,
1034 #[note(trait_selection_expected_found)]
1035 pub note: (),
1036 #[subdiagnostic]
1037 pub param_help: ConsiderBorrowingParamHelp,
1038 #[subdiagnostic]
1039 pub rel_help: Option<RelationshipHelp>,
1042 pub expected: String,
1043 pub found: String,
1044}
1045
1046pub struct DynTraitConstraintSuggestion {
1047 pub span: Span,
1048 pub ident: Ident,
1049}
1050
1051impl Subdiagnostic for DynTraitConstraintSuggestion {
1052 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1053 let mut multi_span: MultiSpan = vec![self.span].into();
1054 multi_span.push_span_label(self.span, fluent::trait_selection_dtcs_has_lifetime_req_label);
1055 multi_span
1056 .push_span_label(self.ident.span, fluent::trait_selection_dtcs_introduces_requirement);
1057 let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_has_req_note);
1058 diag.span_note(multi_span, msg);
1059 let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_suggestion);
1060 diag.span_suggestion_verbose(
1061 self.span.shrink_to_hi(),
1062 msg,
1063 " + '_",
1064 Applicability::MaybeIncorrect,
1065 );
1066 }
1067}
1068
1069#[derive(Diagnostic)]
1070#[diag(trait_selection_but_calling_introduces, code = E0772)]
1071pub struct ButCallingIntroduces {
1072 #[label(trait_selection_label1)]
1073 pub param_ty_span: Span,
1074 #[primary_span]
1075 #[label(trait_selection_label2)]
1076 pub cause_span: Span,
1077
1078 pub has_param_name: bool,
1079 pub param_name: String,
1080 pub has_lifetime: bool,
1081 pub lifetime: String,
1082 pub assoc_item: Symbol,
1083 pub has_impl_path: bool,
1084 pub impl_path: String,
1085}
1086
1087pub struct ReqIntroducedLocations {
1088 pub span: MultiSpan,
1089 pub spans: Vec<Span>,
1090 pub fn_decl_span: Span,
1091 pub cause_span: Span,
1092 pub add_label: bool,
1093}
1094
1095impl Subdiagnostic for ReqIntroducedLocations {
1096 fn add_to_diag<G: EmissionGuarantee>(mut self, diag: &mut Diag<'_, G>) {
1097 for sp in self.spans {
1098 self.span.push_span_label(sp, fluent::trait_selection_ril_introduced_here);
1099 }
1100
1101 if self.add_label {
1102 self.span.push_span_label(self.fn_decl_span, fluent::trait_selection_ril_introduced_by);
1103 }
1104 self.span.push_span_label(self.cause_span, fluent::trait_selection_ril_because_of);
1105 let msg = diag.eagerly_translate(fluent::trait_selection_ril_static_introduced_by);
1106 diag.span_note(self.span, msg);
1107 }
1108}
1109
1110#[derive(Diagnostic)]
1111#[diag(trait_selection_but_needs_to_satisfy, code = E0759)]
1112pub struct ButNeedsToSatisfy {
1113 #[primary_span]
1114 pub sp: Span,
1115 #[label(trait_selection_influencer)]
1116 pub influencer_point: Span,
1117 #[label(trait_selection_used_here)]
1118 pub spans: Vec<Span>,
1119 #[label(trait_selection_require)]
1120 pub require_span_as_label: Option<Span>,
1121 #[note(trait_selection_require)]
1122 pub require_span_as_note: Option<Span>,
1123 #[note(trait_selection_introduced_by_bound)]
1124 pub bound: Option<Span>,
1125
1126 pub has_param_name: bool,
1127 pub param_name: String,
1128 pub spans_empty: bool,
1129 pub has_lifetime: bool,
1130 pub lifetime: String,
1131}
1132
1133#[derive(Diagnostic)]
1134#[diag(trait_selection_outlives_content, code = E0312)]
1135pub struct OutlivesContent<'a> {
1136 #[primary_span]
1137 pub span: Span,
1138 #[subdiagnostic]
1139 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1140}
1141
1142#[derive(Diagnostic)]
1143#[diag(trait_selection_outlives_bound, code = E0476)]
1144pub struct OutlivesBound<'a> {
1145 #[primary_span]
1146 pub span: Span,
1147 #[subdiagnostic]
1148 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1149}
1150
1151#[derive(Diagnostic)]
1152#[diag(trait_selection_fulfill_req_lifetime, code = E0477)]
1153pub struct FulfillReqLifetime<'a> {
1154 #[primary_span]
1155 pub span: Span,
1156 pub ty: Ty<'a>,
1157 #[subdiagnostic]
1158 pub note: Option<note_and_explain::RegionExplanation<'a>>,
1159}
1160
1161#[derive(Diagnostic)]
1162#[diag(trait_selection_lf_bound_not_satisfied, code = E0478)]
1163pub struct LfBoundNotSatisfied<'a> {
1164 #[primary_span]
1165 pub span: Span,
1166 #[subdiagnostic]
1167 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1168}
1169
1170#[derive(Diagnostic)]
1171#[diag(trait_selection_ref_longer_than_data, code = E0491)]
1172pub struct RefLongerThanData<'a> {
1173 #[primary_span]
1174 pub span: Span,
1175 pub ty: Ty<'a>,
1176 #[subdiagnostic]
1177 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1178}
1179
1180#[derive(Subdiagnostic)]
1181pub enum WhereClauseSuggestions {
1182 #[suggestion(
1183 trait_selection_where_remove,
1184 code = "",
1185 applicability = "machine-applicable",
1186 style = "verbose"
1187 )]
1188 Remove {
1189 #[primary_span]
1190 span: Span,
1191 },
1192 #[suggestion(
1193 trait_selection_where_copy_predicates,
1194 code = "{space}where {trait_predicates}",
1195 applicability = "machine-applicable",
1196 style = "verbose"
1197 )]
1198 CopyPredicates {
1199 #[primary_span]
1200 span: Span,
1201 space: &'static str,
1202 trait_predicates: String,
1203 },
1204}
1205
1206#[derive(Subdiagnostic)]
1207pub enum SuggestRemoveSemiOrReturnBinding {
1208 #[multipart_suggestion(
1209 trait_selection_srs_remove_and_box,
1210 applicability = "machine-applicable"
1211 )]
1212 RemoveAndBox {
1213 #[suggestion_part(code = "Box::new(")]
1214 first_lo: Span,
1215 #[suggestion_part(code = ")")]
1216 first_hi: Span,
1217 #[suggestion_part(code = "Box::new(")]
1218 second_lo: Span,
1219 #[suggestion_part(code = ")")]
1220 second_hi: Span,
1221 #[suggestion_part(code = "")]
1222 sp: Span,
1223 },
1224 #[suggestion(
1225 trait_selection_srs_remove,
1226 style = "short",
1227 code = "",
1228 applicability = "machine-applicable"
1229 )]
1230 Remove {
1231 #[primary_span]
1232 sp: Span,
1233 },
1234 #[suggestion(
1235 trait_selection_srs_add,
1236 style = "verbose",
1237 code = "{code}",
1238 applicability = "maybe-incorrect"
1239 )]
1240 Add {
1241 #[primary_span]
1242 sp: Span,
1243 code: String,
1244 ident: Ident,
1245 },
1246 #[note(trait_selection_srs_add_one)]
1247 AddOne {
1248 #[primary_span]
1249 spans: MultiSpan,
1250 },
1251}
1252
1253#[derive(Subdiagnostic)]
1254pub enum ConsiderAddingAwait {
1255 #[help(trait_selection_await_both_futures)]
1256 BothFuturesHelp,
1257 #[multipart_suggestion(trait_selection_await_both_futures, applicability = "maybe-incorrect")]
1258 BothFuturesSugg {
1259 #[suggestion_part(code = ".await")]
1260 first: Span,
1261 #[suggestion_part(code = ".await")]
1262 second: Span,
1263 },
1264 #[suggestion(
1265 trait_selection_await_future,
1266 code = ".await",
1267 style = "verbose",
1268 applicability = "maybe-incorrect"
1269 )]
1270 FutureSugg {
1271 #[primary_span]
1272 span: Span,
1273 },
1274 #[note(trait_selection_await_note)]
1275 FutureSuggNote {
1276 #[primary_span]
1277 span: Span,
1278 },
1279 #[multipart_suggestion(
1280 trait_selection_await_future,
1281 style = "verbose",
1282 applicability = "maybe-incorrect"
1283 )]
1284 FutureSuggMultiple {
1285 #[suggestion_part(code = ".await")]
1286 spans: Vec<Span>,
1287 },
1288}
1289
1290#[derive(Diagnostic)]
1291pub enum PlaceholderRelationLfNotSatisfied {
1292 #[diag(trait_selection_lf_bound_not_satisfied)]
1293 HasBoth {
1294 #[primary_span]
1295 span: Span,
1296 #[note(trait_selection_prlf_defined_with_sub)]
1297 sub_span: Span,
1298 #[note(trait_selection_prlf_must_outlive_with_sup)]
1299 sup_span: Span,
1300 sub_symbol: Symbol,
1301 sup_symbol: Symbol,
1302 #[note(trait_selection_prlf_known_limitation)]
1303 note: (),
1304 },
1305 #[diag(trait_selection_lf_bound_not_satisfied)]
1306 HasSub {
1307 #[primary_span]
1308 span: Span,
1309 #[note(trait_selection_prlf_defined_with_sub)]
1310 sub_span: Span,
1311 #[note(trait_selection_prlf_must_outlive_without_sup)]
1312 sup_span: Span,
1313 sub_symbol: Symbol,
1314 #[note(trait_selection_prlf_known_limitation)]
1315 note: (),
1316 },
1317 #[diag(trait_selection_lf_bound_not_satisfied)]
1318 HasSup {
1319 #[primary_span]
1320 span: Span,
1321 #[note(trait_selection_prlf_defined_without_sub)]
1322 sub_span: Span,
1323 #[note(trait_selection_prlf_must_outlive_with_sup)]
1324 sup_span: Span,
1325 sup_symbol: Symbol,
1326 #[note(trait_selection_prlf_known_limitation)]
1327 note: (),
1328 },
1329 #[diag(trait_selection_lf_bound_not_satisfied)]
1330 HasNone {
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_without_sup)]
1336 sup_span: Span,
1337 #[note(trait_selection_prlf_known_limitation)]
1338 note: (),
1339 },
1340 #[diag(trait_selection_lf_bound_not_satisfied)]
1341 OnlyPrimarySpan {
1342 #[primary_span]
1343 span: Span,
1344 #[note(trait_selection_prlf_known_limitation)]
1345 note: (),
1346 },
1347}
1348
1349#[derive(Diagnostic)]
1350#[diag(trait_selection_opaque_captures_lifetime, code = E0700)]
1351pub struct OpaqueCapturesLifetime<'tcx> {
1352 #[primary_span]
1353 pub span: Span,
1354 #[label]
1355 pub opaque_ty_span: Span,
1356 pub opaque_ty: Ty<'tcx>,
1357}
1358
1359#[derive(Subdiagnostic)]
1360pub enum FunctionPointerSuggestion<'a> {
1361 #[suggestion(
1362 trait_selection_fps_use_ref,
1363 code = "&",
1364 style = "verbose",
1365 applicability = "maybe-incorrect"
1366 )]
1367 UseRef {
1368 #[primary_span]
1369 span: Span,
1370 },
1371 #[suggestion(
1372 trait_selection_fps_remove_ref,
1373 code = "{fn_name}",
1374 style = "verbose",
1375 applicability = "maybe-incorrect"
1376 )]
1377 RemoveRef {
1378 #[primary_span]
1379 span: Span,
1380 #[skip_arg]
1381 fn_name: String,
1382 },
1383 #[suggestion(
1384 trait_selection_fps_cast,
1385 code = "&({fn_name} as {sig})",
1386 style = "verbose",
1387 applicability = "maybe-incorrect"
1388 )]
1389 CastRef {
1390 #[primary_span]
1391 span: Span,
1392 #[skip_arg]
1393 fn_name: String,
1394 #[skip_arg]
1395 sig: Binder<'a, FnSig<'a>>,
1396 },
1397 #[suggestion(
1398 trait_selection_fps_cast,
1399 code = " as {sig}",
1400 style = "verbose",
1401 applicability = "maybe-incorrect"
1402 )]
1403 Cast {
1404 #[primary_span]
1405 span: Span,
1406 #[skip_arg]
1407 sig: Binder<'a, FnSig<'a>>,
1408 },
1409 #[suggestion(
1410 trait_selection_fps_cast_both,
1411 code = " as {found_sig}",
1412 style = "hidden",
1413 applicability = "maybe-incorrect"
1414 )]
1415 CastBoth {
1416 #[primary_span]
1417 span: Span,
1418 #[skip_arg]
1419 found_sig: Binder<'a, FnSig<'a>>,
1420 expected_sig: Binder<'a, FnSig<'a>>,
1421 },
1422 #[suggestion(
1423 trait_selection_fps_cast_both,
1424 code = "&({fn_name} as {found_sig})",
1425 style = "hidden",
1426 applicability = "maybe-incorrect"
1427 )]
1428 CastBothRef {
1429 #[primary_span]
1430 span: Span,
1431 #[skip_arg]
1432 fn_name: String,
1433 #[skip_arg]
1434 found_sig: Binder<'a, FnSig<'a>>,
1435 expected_sig: Binder<'a, FnSig<'a>>,
1436 },
1437}
1438
1439#[derive(Subdiagnostic)]
1440#[note(trait_selection_fps_items_are_distinct)]
1441pub struct FnItemsAreDistinct;
1442
1443#[derive(Subdiagnostic)]
1444#[note(trait_selection_fn_uniq_types)]
1445pub struct FnUniqTypes;
1446
1447#[derive(Subdiagnostic)]
1448#[help(trait_selection_fn_consider_casting)]
1449pub struct FnConsiderCasting {
1450 pub casting: String,
1451}
1452
1453#[derive(Subdiagnostic)]
1454#[help(trait_selection_fn_consider_casting_both)]
1455pub struct FnConsiderCastingBoth<'a> {
1456 pub sig: Binder<'a, FnSig<'a>>,
1457}
1458
1459#[derive(Subdiagnostic)]
1460pub enum SuggestAccessingField<'a> {
1461 #[suggestion(
1462 trait_selection_suggest_accessing_field,
1463 code = "{snippet}.{name}",
1464 applicability = "maybe-incorrect"
1465 )]
1466 Safe {
1467 #[primary_span]
1468 span: Span,
1469 snippet: String,
1470 name: Symbol,
1471 ty: Ty<'a>,
1472 },
1473 #[suggestion(
1474 trait_selection_suggest_accessing_field,
1475 code = "unsafe {{ {snippet}.{name} }}",
1476 applicability = "maybe-incorrect"
1477 )]
1478 Unsafe {
1479 #[primary_span]
1480 span: Span,
1481 snippet: String,
1482 name: Symbol,
1483 ty: Ty<'a>,
1484 },
1485}
1486
1487#[derive(Subdiagnostic)]
1488#[multipart_suggestion(trait_selection_stp_wrap_one, applicability = "maybe-incorrect")]
1489pub struct SuggestTuplePatternOne {
1490 pub variant: String,
1491 #[suggestion_part(code = "{variant}(")]
1492 pub span_low: Span,
1493 #[suggestion_part(code = ")")]
1494 pub span_high: Span,
1495}
1496
1497pub struct SuggestTuplePatternMany {
1498 pub path: String,
1499 pub cause_span: Span,
1500 pub compatible_variants: Vec<String>,
1501}
1502
1503impl Subdiagnostic for SuggestTuplePatternMany {
1504 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1505 diag.arg("path", self.path);
1506 let message = diag.eagerly_translate(fluent::trait_selection_stp_wrap_many);
1507 diag.multipart_suggestions(
1508 message,
1509 self.compatible_variants.into_iter().map(|variant| {
1510 vec![
1511 (self.cause_span.shrink_to_lo(), format!("{variant}(")),
1512 (self.cause_span.shrink_to_hi(), ")".to_string()),
1513 ]
1514 }),
1515 rustc_errors::Applicability::MaybeIncorrect,
1516 );
1517 }
1518}
1519
1520#[derive(Subdiagnostic)]
1521pub enum TypeErrorAdditionalDiags {
1522 #[suggestion(
1523 trait_selection_meant_byte_literal,
1524 code = "b'{code}'",
1525 applicability = "machine-applicable"
1526 )]
1527 MeantByteLiteral {
1528 #[primary_span]
1529 span: Span,
1530 code: String,
1531 },
1532 #[suggestion(
1533 trait_selection_meant_char_literal,
1534 code = "'{code}'",
1535 applicability = "machine-applicable"
1536 )]
1537 MeantCharLiteral {
1538 #[primary_span]
1539 span: Span,
1540 code: String,
1541 },
1542 #[multipart_suggestion(trait_selection_meant_str_literal, applicability = "machine-applicable")]
1543 MeantStrLiteral {
1544 #[suggestion_part(code = "\"")]
1545 start: Span,
1546 #[suggestion_part(code = "\"")]
1547 end: Span,
1548 },
1549 #[suggestion(
1550 trait_selection_consider_specifying_length,
1551 code = "{length}",
1552 applicability = "maybe-incorrect"
1553 )]
1554 ConsiderSpecifyingLength {
1555 #[primary_span]
1556 span: Span,
1557 length: u64,
1558 },
1559 #[note(trait_selection_try_cannot_convert)]
1560 TryCannotConvert { found: String, expected: String },
1561 #[suggestion(
1562 trait_selection_tuple_trailing_comma,
1563 code = ",",
1564 applicability = "machine-applicable"
1565 )]
1566 TupleOnlyComma {
1567 #[primary_span]
1568 span: Span,
1569 },
1570 #[multipart_suggestion(
1571 trait_selection_tuple_trailing_comma,
1572 applicability = "machine-applicable"
1573 )]
1574 TupleAlsoParentheses {
1575 #[suggestion_part(code = "(")]
1576 span_low: Span,
1577 #[suggestion_part(code = ",)")]
1578 span_high: Span,
1579 },
1580 #[suggestion(
1581 trait_selection_suggest_add_let_for_letchains,
1582 style = "verbose",
1583 applicability = "machine-applicable",
1584 code = "let "
1585 )]
1586 AddLetForLetChains {
1587 #[primary_span]
1588 span: Span,
1589 },
1590}
1591
1592#[derive(Diagnostic)]
1593pub enum ObligationCauseFailureCode {
1594 #[diag(trait_selection_oc_method_compat, code = E0308)]
1595 MethodCompat {
1596 #[primary_span]
1597 span: Span,
1598 #[subdiagnostic]
1599 subdiags: Vec<TypeErrorAdditionalDiags>,
1600 },
1601 #[diag(trait_selection_oc_type_compat, code = E0308)]
1602 TypeCompat {
1603 #[primary_span]
1604 span: Span,
1605 #[subdiagnostic]
1606 subdiags: Vec<TypeErrorAdditionalDiags>,
1607 },
1608 #[diag(trait_selection_oc_const_compat, code = E0308)]
1609 ConstCompat {
1610 #[primary_span]
1611 span: Span,
1612 #[subdiagnostic]
1613 subdiags: Vec<TypeErrorAdditionalDiags>,
1614 },
1615 #[diag(trait_selection_oc_try_compat, code = E0308)]
1616 TryCompat {
1617 #[primary_span]
1618 span: Span,
1619 #[subdiagnostic]
1620 subdiags: Vec<TypeErrorAdditionalDiags>,
1621 },
1622 #[diag(trait_selection_oc_match_compat, code = E0308)]
1623 MatchCompat {
1624 #[primary_span]
1625 span: Span,
1626 #[subdiagnostic]
1627 subdiags: Vec<TypeErrorAdditionalDiags>,
1628 },
1629 #[diag(trait_selection_oc_if_else_different, code = E0308)]
1630 IfElseDifferent {
1631 #[primary_span]
1632 span: Span,
1633 #[subdiagnostic]
1634 subdiags: Vec<TypeErrorAdditionalDiags>,
1635 },
1636 #[diag(trait_selection_oc_no_else, code = E0317)]
1637 NoElse {
1638 #[primary_span]
1639 span: Span,
1640 },
1641 #[diag(trait_selection_oc_no_diverge, code = E0308)]
1642 NoDiverge {
1643 #[primary_span]
1644 span: Span,
1645 #[subdiagnostic]
1646 subdiags: Vec<TypeErrorAdditionalDiags>,
1647 },
1648 #[diag(trait_selection_oc_fn_main_correct_type, code = E0580)]
1649 FnMainCorrectType {
1650 #[primary_span]
1651 span: Span,
1652 },
1653 #[diag(trait_selection_oc_fn_lang_correct_type, code = E0308)]
1654 FnLangCorrectType {
1655 #[primary_span]
1656 span: Span,
1657 #[subdiagnostic]
1658 subdiags: Vec<TypeErrorAdditionalDiags>,
1659 lang_item_name: Symbol,
1660 },
1661 #[diag(trait_selection_oc_intrinsic_correct_type, code = E0308)]
1662 IntrinsicCorrectType {
1663 #[primary_span]
1664 span: Span,
1665 #[subdiagnostic]
1666 subdiags: Vec<TypeErrorAdditionalDiags>,
1667 },
1668 #[diag(trait_selection_oc_method_correct_type, code = E0308)]
1669 MethodCorrectType {
1670 #[primary_span]
1671 span: Span,
1672 #[subdiagnostic]
1673 subdiags: Vec<TypeErrorAdditionalDiags>,
1674 },
1675 #[diag(trait_selection_oc_closure_selfref, code = E0644)]
1676 ClosureSelfref {
1677 #[primary_span]
1678 span: Span,
1679 },
1680 #[diag(trait_selection_oc_cant_coerce_force_inline, code = E0308)]
1681 CantCoerceForceInline {
1682 #[primary_span]
1683 span: Span,
1684 #[subdiagnostic]
1685 subdiags: Vec<TypeErrorAdditionalDiags>,
1686 },
1687 #[diag(trait_selection_oc_cant_coerce_intrinsic, code = E0308)]
1688 CantCoerceIntrinsic {
1689 #[primary_span]
1690 span: Span,
1691 #[subdiagnostic]
1692 subdiags: Vec<TypeErrorAdditionalDiags>,
1693 },
1694 #[diag(trait_selection_oc_generic, code = E0308)]
1695 Generic {
1696 #[primary_span]
1697 span: Span,
1698 #[subdiagnostic]
1699 subdiags: Vec<TypeErrorAdditionalDiags>,
1700 },
1701}
1702
1703#[derive(Subdiagnostic)]
1704pub enum AddPreciseCapturing {
1705 #[suggestion(
1706 trait_selection_precise_capturing_new,
1707 style = "verbose",
1708 code = " + use<{concatenated_bounds}>",
1709 applicability = "machine-applicable"
1710 )]
1711 New {
1712 #[primary_span]
1713 span: Span,
1714 new_lifetime: Symbol,
1715 concatenated_bounds: String,
1716 },
1717 #[suggestion(
1718 trait_selection_precise_capturing_existing,
1719 style = "verbose",
1720 code = "{pre}{new_lifetime}{post}",
1721 applicability = "machine-applicable"
1722 )]
1723 Existing {
1724 #[primary_span]
1725 span: Span,
1726 new_lifetime: Symbol,
1727 pre: &'static str,
1728 post: &'static str,
1729 },
1730}
1731
1732pub struct AddPreciseCapturingAndParams {
1733 pub suggs: Vec<(Span, String)>,
1734 pub new_lifetime: Symbol,
1735 pub apit_spans: Vec<Span>,
1736}
1737
1738impl Subdiagnostic for AddPreciseCapturingAndParams {
1739 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1740 diag.arg("new_lifetime", self.new_lifetime);
1741 diag.multipart_suggestion_verbose(
1742 fluent::trait_selection_precise_capturing_new_but_apit,
1743 self.suggs,
1744 Applicability::MaybeIncorrect,
1745 );
1746 diag.span_note(
1747 self.apit_spans,
1748 fluent::trait_selection_warn_removing_apit_params_for_undercapture,
1749 );
1750 }
1751}
1752
1753pub fn impl_trait_overcapture_suggestion<'tcx>(
1758 tcx: TyCtxt<'tcx>,
1759 opaque_def_id: LocalDefId,
1760 fn_def_id: LocalDefId,
1761 captured_args: FxIndexSet<DefId>,
1762) -> Option<AddPreciseCapturingForOvercapture> {
1763 let generics = tcx.generics_of(fn_def_id);
1764
1765 let mut captured_lifetimes = FxIndexSet::default();
1766 let mut captured_non_lifetimes = FxIndexSet::default();
1767 let mut synthetics = vec![];
1768
1769 for arg in captured_args {
1770 if tcx.def_kind(arg) == DefKind::LifetimeParam {
1771 captured_lifetimes.insert(tcx.item_name(arg));
1772 } else {
1773 let idx = generics.param_def_id_to_index(tcx, arg).expect("expected arg in scope");
1774 let param = generics.param_at(idx as usize, tcx);
1775 if param.kind.is_synthetic() {
1776 synthetics.push((tcx.def_span(arg), param.name));
1777 } else {
1778 captured_non_lifetimes.insert(tcx.item_name(arg));
1779 }
1780 }
1781 }
1782
1783 let mut next_fresh_param = || {
1784 ["T", "U", "V", "W", "X", "Y", "A", "B", "C"]
1785 .into_iter()
1786 .map(Symbol::intern)
1787 .chain((0..).map(|i| Symbol::intern(&format!("T{i}"))))
1788 .find(|s| captured_non_lifetimes.insert(*s))
1789 .unwrap()
1790 };
1791
1792 let mut suggs = vec![];
1793 let mut apit_spans = vec![];
1794
1795 if !synthetics.is_empty() {
1796 let mut new_params = String::new();
1797 for (i, (span, name)) in synthetics.into_iter().enumerate() {
1798 apit_spans.push(span);
1799
1800 let fresh_param = next_fresh_param();
1801
1802 suggs.push((span, fresh_param.to_string()));
1804
1805 if i > 0 {
1813 new_params += ", ";
1814 }
1815 let name_as_bounds = name.as_str().trim_start_matches("impl").trim_start();
1816 new_params += fresh_param.as_str();
1817 new_params += ": ";
1818 new_params += name_as_bounds;
1819 }
1820
1821 let Some(generics) = tcx.hir_get_generics(fn_def_id) else {
1822 return None;
1824 };
1825
1826 suggs.push(if let Some(params_span) = generics.span_for_param_suggestion() {
1828 (params_span, format!(", {new_params}"))
1829 } else {
1830 (generics.span, format!("<{new_params}>"))
1831 });
1832 }
1833
1834 let concatenated_bounds = captured_lifetimes
1835 .into_iter()
1836 .chain(captured_non_lifetimes)
1837 .map(|sym| sym.to_string())
1838 .collect::<Vec<_>>()
1839 .join(", ");
1840
1841 let opaque_hir_id = tcx.local_def_id_to_hir_id(opaque_def_id);
1842 let (lparen, rparen) = match tcx
1844 .hir_parent_iter(opaque_hir_id)
1845 .nth(1)
1846 .expect("expected ty to have a parent always")
1847 .1
1848 {
1849 Node::PathSegment(segment)
1850 if segment.args().paren_sugar_output().is_some_and(|ty| ty.hir_id == opaque_hir_id) =>
1851 {
1852 ("(", ")")
1853 }
1854 Node::Ty(ty) => match ty.kind {
1855 rustc_hir::TyKind::Ptr(_) | rustc_hir::TyKind::Ref(..) => ("(", ")"),
1856 _ => ("", ""),
1860 },
1861 _ => ("", ""),
1862 };
1863
1864 let rpit_span = tcx.def_span(opaque_def_id);
1865 if !lparen.is_empty() {
1866 suggs.push((rpit_span.shrink_to_lo(), lparen.to_string()));
1867 }
1868 suggs.push((rpit_span.shrink_to_hi(), format!(" + use<{concatenated_bounds}>{rparen}")));
1869
1870 Some(AddPreciseCapturingForOvercapture { suggs, apit_spans })
1871}
1872
1873pub struct AddPreciseCapturingForOvercapture {
1874 pub suggs: Vec<(Span, String)>,
1875 pub apit_spans: Vec<Span>,
1876}
1877
1878impl Subdiagnostic for AddPreciseCapturingForOvercapture {
1879 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1880 let applicability = if self.apit_spans.is_empty() {
1881 Applicability::MachineApplicable
1882 } else {
1883 Applicability::MaybeIncorrect
1887 };
1888 diag.multipart_suggestion_verbose(
1889 fluent::trait_selection_precise_capturing_overcaptures,
1890 self.suggs,
1891 applicability,
1892 );
1893 if !self.apit_spans.is_empty() {
1894 diag.span_note(
1895 self.apit_spans,
1896 fluent::trait_selection_warn_removing_apit_params_for_overcapture,
1897 );
1898 }
1899 }
1900}
1901
1902#[derive(Diagnostic)]
1903#[diag(trait_selection_opaque_type_non_generic_param, code = E0792)]
1904pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
1905 pub arg: GenericArg<'tcx>,
1906 pub kind: &'a str,
1907 #[primary_span]
1908 pub span: Span,
1909 #[label]
1910 pub param_span: Span,
1911}