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