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 style = "verbose"
764 )]
765 new_ty_span: Span,
766 #[skip_arg]
767 new_ty: Ty<'a>,
768 },
769 #[diag(trait_selection_explicit_lifetime_required_with_param_type, code = E0621)]
770 WithParamType {
771 #[primary_span]
772 #[label]
773 span: Span,
774 named: String,
775 #[suggestion(
776 trait_selection_explicit_lifetime_required_sugg_with_param_type,
777 code = "{new_ty}",
778 applicability = "unspecified",
779 style = "verbose"
780 )]
781 new_ty_span: Span,
782 #[skip_arg]
783 new_ty: Ty<'a>,
784 },
785}
786
787pub enum TyOrSig<'tcx> {
788 Ty(Highlighted<'tcx, Ty<'tcx>>),
789 ClosureSig(Highlighted<'tcx, Binder<'tcx, FnSig<'tcx>>>),
790}
791
792impl IntoDiagArg for TyOrSig<'_> {
793 fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
794 match self {
795 TyOrSig::Ty(ty) => ty.into_diag_arg(path),
796 TyOrSig::ClosureSig(sig) => sig.into_diag_arg(path),
797 }
798 }
799}
800
801#[derive(Subdiagnostic)]
802pub enum ActualImplExplNotes<'tcx> {
803 #[note(trait_selection_actual_impl_expl_expected_signature_two)]
804 ExpectedSignatureTwo {
805 leading_ellipsis: bool,
806 ty_or_sig: TyOrSig<'tcx>,
807 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
808 lifetime_1: usize,
809 lifetime_2: usize,
810 },
811 #[note(trait_selection_actual_impl_expl_expected_signature_any)]
812 ExpectedSignatureAny {
813 leading_ellipsis: bool,
814 ty_or_sig: TyOrSig<'tcx>,
815 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
816 lifetime_1: usize,
817 },
818 #[note(trait_selection_actual_impl_expl_expected_signature_some)]
819 ExpectedSignatureSome {
820 leading_ellipsis: bool,
821 ty_or_sig: TyOrSig<'tcx>,
822 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
823 lifetime_1: usize,
824 },
825 #[note(trait_selection_actual_impl_expl_expected_signature_nothing)]
826 ExpectedSignatureNothing {
827 leading_ellipsis: bool,
828 ty_or_sig: TyOrSig<'tcx>,
829 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
830 },
831 #[note(trait_selection_actual_impl_expl_expected_passive_two)]
832 ExpectedPassiveTwo {
833 leading_ellipsis: bool,
834 ty_or_sig: TyOrSig<'tcx>,
835 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
836 lifetime_1: usize,
837 lifetime_2: usize,
838 },
839 #[note(trait_selection_actual_impl_expl_expected_passive_any)]
840 ExpectedPassiveAny {
841 leading_ellipsis: bool,
842 ty_or_sig: TyOrSig<'tcx>,
843 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
844 lifetime_1: usize,
845 },
846 #[note(trait_selection_actual_impl_expl_expected_passive_some)]
847 ExpectedPassiveSome {
848 leading_ellipsis: bool,
849 ty_or_sig: TyOrSig<'tcx>,
850 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
851 lifetime_1: usize,
852 },
853 #[note(trait_selection_actual_impl_expl_expected_passive_nothing)]
854 ExpectedPassiveNothing {
855 leading_ellipsis: bool,
856 ty_or_sig: TyOrSig<'tcx>,
857 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
858 },
859 #[note(trait_selection_actual_impl_expl_expected_other_two)]
860 ExpectedOtherTwo {
861 leading_ellipsis: bool,
862 ty_or_sig: TyOrSig<'tcx>,
863 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
864 lifetime_1: usize,
865 lifetime_2: usize,
866 },
867 #[note(trait_selection_actual_impl_expl_expected_other_any)]
868 ExpectedOtherAny {
869 leading_ellipsis: bool,
870 ty_or_sig: TyOrSig<'tcx>,
871 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
872 lifetime_1: usize,
873 },
874 #[note(trait_selection_actual_impl_expl_expected_other_some)]
875 ExpectedOtherSome {
876 leading_ellipsis: bool,
877 ty_or_sig: TyOrSig<'tcx>,
878 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
879 lifetime_1: usize,
880 },
881 #[note(trait_selection_actual_impl_expl_expected_other_nothing)]
882 ExpectedOtherNothing {
883 leading_ellipsis: bool,
884 ty_or_sig: TyOrSig<'tcx>,
885 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
886 },
887 #[note(trait_selection_actual_impl_expl_but_actually_implements_trait)]
888 ButActuallyImplementsTrait {
889 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
890 has_lifetime: bool,
891 lifetime: usize,
892 },
893 #[note(trait_selection_actual_impl_expl_but_actually_implemented_for_ty)]
894 ButActuallyImplementedForTy {
895 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
896 has_lifetime: bool,
897 lifetime: usize,
898 ty: String,
899 },
900 #[note(trait_selection_actual_impl_expl_but_actually_ty_implements)]
901 ButActuallyTyImplements {
902 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
903 has_lifetime: bool,
904 lifetime: usize,
905 ty: String,
906 },
907}
908
909pub enum ActualImplExpectedKind {
910 Signature,
911 Passive,
912 Other,
913}
914
915pub enum ActualImplExpectedLifetimeKind {
916 Two,
917 Any,
918 Some,
919 Nothing,
920}
921
922impl<'tcx> ActualImplExplNotes<'tcx> {
923 pub fn new_expected(
924 kind: ActualImplExpectedKind,
925 lt_kind: ActualImplExpectedLifetimeKind,
926 leading_ellipsis: bool,
927 ty_or_sig: TyOrSig<'tcx>,
928 trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
929 lifetime_1: usize,
930 lifetime_2: usize,
931 ) -> Self {
932 match (kind, lt_kind) {
933 (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => {
934 Self::ExpectedSignatureTwo {
935 leading_ellipsis,
936 ty_or_sig,
937 trait_path,
938 lifetime_1,
939 lifetime_2,
940 }
941 }
942 (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => {
943 Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
944 }
945 (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => {
946 Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
947 }
948 (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => {
949 Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path }
950 }
951 (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => {
952 Self::ExpectedPassiveTwo {
953 leading_ellipsis,
954 ty_or_sig,
955 trait_path,
956 lifetime_1,
957 lifetime_2,
958 }
959 }
960 (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => {
961 Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
962 }
963 (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => {
964 Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
965 }
966 (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => {
967 Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path }
968 }
969 (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => {
970 Self::ExpectedOtherTwo {
971 leading_ellipsis,
972 ty_or_sig,
973 trait_path,
974 lifetime_1,
975 lifetime_2,
976 }
977 }
978 (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => {
979 Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
980 }
981 (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => {
982 Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
983 }
984 (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => {
985 Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path }
986 }
987 }
988 }
989}
990
991#[derive(Diagnostic)]
992#[diag(trait_selection_trait_placeholder_mismatch)]
993pub struct TraitPlaceholderMismatch<'tcx> {
994 #[primary_span]
995 pub span: Span,
996 #[label(trait_selection_label_satisfy)]
997 pub satisfy_span: Option<Span>,
998 #[label(trait_selection_label_where)]
999 pub where_span: Option<Span>,
1000 #[label(trait_selection_label_dup)]
1001 pub dup_span: Option<Span>,
1002 pub def_id: String,
1003 pub trait_def_id: String,
1004
1005 #[subdiagnostic]
1006 pub actual_impl_expl_notes: Vec<ActualImplExplNotes<'tcx>>,
1007}
1008
1009pub struct ConsiderBorrowingParamHelp {
1010 pub spans: Vec<Span>,
1011}
1012
1013impl Subdiagnostic for ConsiderBorrowingParamHelp {
1014 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1015 let mut type_param_span: MultiSpan = self.spans.clone().into();
1016 for &span in &self.spans {
1017 type_param_span.push_span_label(span, fluent::trait_selection_tid_consider_borrowing);
1019 }
1020 let msg = diag.eagerly_translate(fluent::trait_selection_tid_param_help);
1021 diag.span_help(type_param_span, msg);
1022 }
1023}
1024
1025#[derive(Subdiagnostic)]
1026#[help(trait_selection_tid_rel_help)]
1027pub struct RelationshipHelp;
1028
1029#[derive(Diagnostic)]
1030#[diag(trait_selection_trait_impl_diff)]
1031pub struct TraitImplDiff {
1032 #[primary_span]
1033 #[label(trait_selection_found)]
1034 pub sp: Span,
1035 #[label(trait_selection_expected)]
1036 pub trait_sp: Span,
1037 #[note(trait_selection_expected_found)]
1038 pub note: (),
1039 #[subdiagnostic]
1040 pub param_help: ConsiderBorrowingParamHelp,
1041 #[subdiagnostic]
1042 pub rel_help: Option<RelationshipHelp>,
1045 pub expected: String,
1046 pub found: String,
1047}
1048
1049pub struct DynTraitConstraintSuggestion {
1050 pub span: Span,
1051 pub ident: Ident,
1052}
1053
1054impl Subdiagnostic for DynTraitConstraintSuggestion {
1055 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1056 let mut multi_span: MultiSpan = vec![self.span].into();
1057 multi_span.push_span_label(self.span, fluent::trait_selection_dtcs_has_lifetime_req_label);
1058 multi_span
1059 .push_span_label(self.ident.span, fluent::trait_selection_dtcs_introduces_requirement);
1060 let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_has_req_note);
1061 diag.span_note(multi_span, msg);
1062 let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_suggestion);
1063 diag.span_suggestion_verbose(
1064 self.span.shrink_to_hi(),
1065 msg,
1066 " + '_",
1067 Applicability::MaybeIncorrect,
1068 );
1069 }
1070}
1071
1072#[derive(Diagnostic)]
1073#[diag(trait_selection_but_calling_introduces, code = E0772)]
1074pub struct ButCallingIntroduces {
1075 #[label(trait_selection_label1)]
1076 pub param_ty_span: Span,
1077 #[primary_span]
1078 #[label(trait_selection_label2)]
1079 pub cause_span: Span,
1080
1081 pub has_param_name: bool,
1082 pub param_name: String,
1083 pub has_lifetime: bool,
1084 pub lifetime: String,
1085 pub assoc_item: Symbol,
1086 pub has_impl_path: bool,
1087 pub impl_path: String,
1088}
1089
1090pub struct ReqIntroducedLocations {
1091 pub span: MultiSpan,
1092 pub spans: Vec<Span>,
1093 pub fn_decl_span: Span,
1094 pub cause_span: Span,
1095 pub add_label: bool,
1096}
1097
1098impl Subdiagnostic for ReqIntroducedLocations {
1099 fn add_to_diag<G: EmissionGuarantee>(mut self, diag: &mut Diag<'_, G>) {
1100 for sp in self.spans {
1101 self.span.push_span_label(sp, fluent::trait_selection_ril_introduced_here);
1102 }
1103
1104 if self.add_label {
1105 self.span.push_span_label(self.fn_decl_span, fluent::trait_selection_ril_introduced_by);
1106 }
1107 self.span.push_span_label(self.cause_span, fluent::trait_selection_ril_because_of);
1108 let msg = diag.eagerly_translate(fluent::trait_selection_ril_static_introduced_by);
1109 diag.span_note(self.span, msg);
1110 }
1111}
1112
1113#[derive(Diagnostic)]
1114#[diag(trait_selection_but_needs_to_satisfy, code = E0759)]
1115pub struct ButNeedsToSatisfy {
1116 #[primary_span]
1117 pub sp: Span,
1118 #[label(trait_selection_influencer)]
1119 pub influencer_point: Span,
1120 #[label(trait_selection_used_here)]
1121 pub spans: Vec<Span>,
1122 #[label(trait_selection_require)]
1123 pub require_span_as_label: Option<Span>,
1124 #[note(trait_selection_require)]
1125 pub require_span_as_note: Option<Span>,
1126 #[note(trait_selection_introduced_by_bound)]
1127 pub bound: Option<Span>,
1128
1129 pub has_param_name: bool,
1130 pub param_name: String,
1131 pub spans_empty: bool,
1132 pub has_lifetime: bool,
1133 pub lifetime: String,
1134}
1135
1136#[derive(Diagnostic)]
1137#[diag(trait_selection_outlives_content, code = E0312)]
1138pub struct OutlivesContent<'a> {
1139 #[primary_span]
1140 pub span: Span,
1141 #[subdiagnostic]
1142 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1143}
1144
1145#[derive(Diagnostic)]
1146#[diag(trait_selection_outlives_bound, code = E0476)]
1147pub struct OutlivesBound<'a> {
1148 #[primary_span]
1149 pub span: Span,
1150 #[subdiagnostic]
1151 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1152}
1153
1154#[derive(Diagnostic)]
1155#[diag(trait_selection_fulfill_req_lifetime, code = E0477)]
1156pub struct FulfillReqLifetime<'a> {
1157 #[primary_span]
1158 pub span: Span,
1159 pub ty: Ty<'a>,
1160 #[subdiagnostic]
1161 pub note: Option<note_and_explain::RegionExplanation<'a>>,
1162}
1163
1164#[derive(Diagnostic)]
1165#[diag(trait_selection_lf_bound_not_satisfied, code = E0478)]
1166pub struct LfBoundNotSatisfied<'a> {
1167 #[primary_span]
1168 pub span: Span,
1169 #[subdiagnostic]
1170 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1171}
1172
1173#[derive(Diagnostic)]
1174#[diag(trait_selection_ref_longer_than_data, code = E0491)]
1175pub struct RefLongerThanData<'a> {
1176 #[primary_span]
1177 pub span: Span,
1178 pub ty: Ty<'a>,
1179 #[subdiagnostic]
1180 pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
1181}
1182
1183#[derive(Subdiagnostic)]
1184pub enum WhereClauseSuggestions {
1185 #[suggestion(
1186 trait_selection_where_remove,
1187 code = "",
1188 applicability = "machine-applicable",
1189 style = "verbose"
1190 )]
1191 Remove {
1192 #[primary_span]
1193 span: Span,
1194 },
1195 #[suggestion(
1196 trait_selection_where_copy_predicates,
1197 code = "{space}where {trait_predicates}",
1198 applicability = "machine-applicable",
1199 style = "verbose"
1200 )]
1201 CopyPredicates {
1202 #[primary_span]
1203 span: Span,
1204 space: &'static str,
1205 trait_predicates: String,
1206 },
1207}
1208
1209#[derive(Subdiagnostic)]
1210pub enum SuggestRemoveSemiOrReturnBinding {
1211 #[multipart_suggestion(
1212 trait_selection_srs_remove_and_box,
1213 applicability = "machine-applicable"
1214 )]
1215 RemoveAndBox {
1216 #[suggestion_part(code = "Box::new(")]
1217 first_lo: Span,
1218 #[suggestion_part(code = ")")]
1219 first_hi: Span,
1220 #[suggestion_part(code = "Box::new(")]
1221 second_lo: Span,
1222 #[suggestion_part(code = ")")]
1223 second_hi: Span,
1224 #[suggestion_part(code = "")]
1225 sp: Span,
1226 },
1227 #[suggestion(
1228 trait_selection_srs_remove,
1229 style = "short",
1230 code = "",
1231 applicability = "machine-applicable"
1232 )]
1233 Remove {
1234 #[primary_span]
1235 sp: Span,
1236 },
1237 #[suggestion(
1238 trait_selection_srs_add,
1239 style = "verbose",
1240 code = "{code}",
1241 applicability = "maybe-incorrect"
1242 )]
1243 Add {
1244 #[primary_span]
1245 sp: Span,
1246 code: String,
1247 ident: Ident,
1248 },
1249 #[note(trait_selection_srs_add_one)]
1250 AddOne {
1251 #[primary_span]
1252 spans: MultiSpan,
1253 },
1254}
1255
1256#[derive(Subdiagnostic)]
1257pub enum ConsiderAddingAwait {
1258 #[help(trait_selection_await_both_futures)]
1259 BothFuturesHelp,
1260 #[multipart_suggestion(trait_selection_await_both_futures, applicability = "maybe-incorrect")]
1261 BothFuturesSugg {
1262 #[suggestion_part(code = ".await")]
1263 first: Span,
1264 #[suggestion_part(code = ".await")]
1265 second: Span,
1266 },
1267 #[suggestion(
1268 trait_selection_await_future,
1269 code = ".await",
1270 style = "verbose",
1271 applicability = "maybe-incorrect"
1272 )]
1273 FutureSugg {
1274 #[primary_span]
1275 span: Span,
1276 },
1277 #[note(trait_selection_await_note)]
1278 FutureSuggNote {
1279 #[primary_span]
1280 span: Span,
1281 },
1282 #[multipart_suggestion(
1283 trait_selection_await_future,
1284 style = "verbose",
1285 applicability = "maybe-incorrect"
1286 )]
1287 FutureSuggMultiple {
1288 #[suggestion_part(code = ".await")]
1289 spans: Vec<Span>,
1290 },
1291}
1292
1293#[derive(Diagnostic)]
1294pub enum PlaceholderRelationLfNotSatisfied {
1295 #[diag(trait_selection_lf_bound_not_satisfied)]
1296 HasBoth {
1297 #[primary_span]
1298 span: Span,
1299 #[note(trait_selection_prlf_defined_with_sub)]
1300 sub_span: Span,
1301 #[note(trait_selection_prlf_must_outlive_with_sup)]
1302 sup_span: Span,
1303 sub_symbol: Symbol,
1304 sup_symbol: Symbol,
1305 #[note(trait_selection_prlf_known_limitation)]
1306 note: (),
1307 },
1308 #[diag(trait_selection_lf_bound_not_satisfied)]
1309 HasSub {
1310 #[primary_span]
1311 span: Span,
1312 #[note(trait_selection_prlf_defined_with_sub)]
1313 sub_span: Span,
1314 #[note(trait_selection_prlf_must_outlive_without_sup)]
1315 sup_span: Span,
1316 sub_symbol: Symbol,
1317 #[note(trait_selection_prlf_known_limitation)]
1318 note: (),
1319 },
1320 #[diag(trait_selection_lf_bound_not_satisfied)]
1321 HasSup {
1322 #[primary_span]
1323 span: Span,
1324 #[note(trait_selection_prlf_defined_without_sub)]
1325 sub_span: Span,
1326 #[note(trait_selection_prlf_must_outlive_with_sup)]
1327 sup_span: Span,
1328 sup_symbol: Symbol,
1329 #[note(trait_selection_prlf_known_limitation)]
1330 note: (),
1331 },
1332 #[diag(trait_selection_lf_bound_not_satisfied)]
1333 HasNone {
1334 #[primary_span]
1335 span: Span,
1336 #[note(trait_selection_prlf_defined_without_sub)]
1337 sub_span: Span,
1338 #[note(trait_selection_prlf_must_outlive_without_sup)]
1339 sup_span: Span,
1340 #[note(trait_selection_prlf_known_limitation)]
1341 note: (),
1342 },
1343 #[diag(trait_selection_lf_bound_not_satisfied)]
1344 OnlyPrimarySpan {
1345 #[primary_span]
1346 span: Span,
1347 #[note(trait_selection_prlf_known_limitation)]
1348 note: (),
1349 },
1350}
1351
1352#[derive(Diagnostic)]
1353#[diag(trait_selection_opaque_captures_lifetime, code = E0700)]
1354pub struct OpaqueCapturesLifetime<'tcx> {
1355 #[primary_span]
1356 pub span: Span,
1357 #[label]
1358 pub opaque_ty_span: Span,
1359 pub opaque_ty: Ty<'tcx>,
1360}
1361
1362#[derive(Subdiagnostic)]
1363pub enum FunctionPointerSuggestion<'a> {
1364 #[suggestion(
1365 trait_selection_fps_use_ref,
1366 code = "&",
1367 style = "verbose",
1368 applicability = "maybe-incorrect"
1369 )]
1370 UseRef {
1371 #[primary_span]
1372 span: Span,
1373 },
1374 #[suggestion(
1375 trait_selection_fps_remove_ref,
1376 code = "{fn_name}",
1377 style = "verbose",
1378 applicability = "maybe-incorrect"
1379 )]
1380 RemoveRef {
1381 #[primary_span]
1382 span: Span,
1383 #[skip_arg]
1384 fn_name: String,
1385 },
1386 #[suggestion(
1387 trait_selection_fps_cast,
1388 code = "&({fn_name} as {sig})",
1389 style = "verbose",
1390 applicability = "maybe-incorrect"
1391 )]
1392 CastRef {
1393 #[primary_span]
1394 span: Span,
1395 #[skip_arg]
1396 fn_name: String,
1397 #[skip_arg]
1398 sig: Binder<'a, FnSig<'a>>,
1399 },
1400 #[suggestion(
1401 trait_selection_fps_cast,
1402 code = " as {sig}",
1403 style = "verbose",
1404 applicability = "maybe-incorrect"
1405 )]
1406 Cast {
1407 #[primary_span]
1408 span: Span,
1409 #[skip_arg]
1410 sig: Binder<'a, FnSig<'a>>,
1411 },
1412 #[suggestion(
1413 trait_selection_fps_cast_both,
1414 code = " as {found_sig}",
1415 style = "hidden",
1416 applicability = "maybe-incorrect"
1417 )]
1418 CastBoth {
1419 #[primary_span]
1420 span: Span,
1421 #[skip_arg]
1422 found_sig: Binder<'a, FnSig<'a>>,
1423 expected_sig: Binder<'a, FnSig<'a>>,
1424 },
1425 #[suggestion(
1426 trait_selection_fps_cast_both,
1427 code = "&({fn_name} as {found_sig})",
1428 style = "hidden",
1429 applicability = "maybe-incorrect"
1430 )]
1431 CastBothRef {
1432 #[primary_span]
1433 span: Span,
1434 #[skip_arg]
1435 fn_name: String,
1436 #[skip_arg]
1437 found_sig: Binder<'a, FnSig<'a>>,
1438 expected_sig: Binder<'a, FnSig<'a>>,
1439 },
1440}
1441
1442#[derive(Subdiagnostic)]
1443#[note(trait_selection_fps_items_are_distinct)]
1444pub struct FnItemsAreDistinct;
1445
1446#[derive(Subdiagnostic)]
1447#[note(trait_selection_fn_uniq_types)]
1448pub struct FnUniqTypes;
1449
1450#[derive(Subdiagnostic)]
1451#[help(trait_selection_fn_consider_casting)]
1452pub struct FnConsiderCasting {
1453 pub casting: String,
1454}
1455
1456#[derive(Subdiagnostic)]
1457#[help(trait_selection_fn_consider_casting_both)]
1458pub struct FnConsiderCastingBoth<'a> {
1459 pub sig: Binder<'a, FnSig<'a>>,
1460}
1461
1462#[derive(Subdiagnostic)]
1463pub enum SuggestAccessingField<'a> {
1464 #[suggestion(
1465 trait_selection_suggest_accessing_field,
1466 code = "{snippet}.{name}",
1467 applicability = "maybe-incorrect",
1468 style = "verbose"
1469 )]
1470 Safe {
1471 #[primary_span]
1472 span: Span,
1473 snippet: String,
1474 name: Symbol,
1475 ty: Ty<'a>,
1476 },
1477 #[suggestion(
1478 trait_selection_suggest_accessing_field,
1479 code = "unsafe {{ {snippet}.{name} }}",
1480 applicability = "maybe-incorrect",
1481 style = "verbose"
1482 )]
1483 Unsafe {
1484 #[primary_span]
1485 span: Span,
1486 snippet: String,
1487 name: Symbol,
1488 ty: Ty<'a>,
1489 },
1490}
1491
1492#[derive(Subdiagnostic)]
1493#[multipart_suggestion(trait_selection_stp_wrap_one, applicability = "maybe-incorrect")]
1494pub struct SuggestTuplePatternOne {
1495 pub variant: String,
1496 #[suggestion_part(code = "{variant}(")]
1497 pub span_low: Span,
1498 #[suggestion_part(code = ")")]
1499 pub span_high: Span,
1500}
1501
1502pub struct SuggestTuplePatternMany {
1503 pub path: String,
1504 pub cause_span: Span,
1505 pub compatible_variants: Vec<String>,
1506}
1507
1508impl Subdiagnostic for SuggestTuplePatternMany {
1509 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1510 diag.arg("path", self.path);
1511 let message = diag.eagerly_translate(fluent::trait_selection_stp_wrap_many);
1512 diag.multipart_suggestions(
1513 message,
1514 self.compatible_variants.into_iter().map(|variant| {
1515 vec![
1516 (self.cause_span.shrink_to_lo(), format!("{variant}(")),
1517 (self.cause_span.shrink_to_hi(), ")".to_string()),
1518 ]
1519 }),
1520 rustc_errors::Applicability::MaybeIncorrect,
1521 );
1522 }
1523}
1524
1525#[derive(Subdiagnostic)]
1526pub enum TypeErrorAdditionalDiags {
1527 #[suggestion(
1528 trait_selection_meant_byte_literal,
1529 code = "b'{code}'",
1530 applicability = "machine-applicable"
1531 )]
1532 MeantByteLiteral {
1533 #[primary_span]
1534 span: Span,
1535 code: String,
1536 },
1537 #[suggestion(
1538 trait_selection_meant_char_literal,
1539 code = "'{code}'",
1540 applicability = "machine-applicable"
1541 )]
1542 MeantCharLiteral {
1543 #[primary_span]
1544 span: Span,
1545 code: String,
1546 },
1547 #[multipart_suggestion(trait_selection_meant_str_literal, applicability = "machine-applicable")]
1548 MeantStrLiteral {
1549 #[suggestion_part(code = "\"")]
1550 start: Span,
1551 #[suggestion_part(code = "\"")]
1552 end: Span,
1553 },
1554 #[suggestion(
1555 trait_selection_consider_specifying_length,
1556 code = "{length}",
1557 applicability = "maybe-incorrect"
1558 )]
1559 ConsiderSpecifyingLength {
1560 #[primary_span]
1561 span: Span,
1562 length: u64,
1563 },
1564 #[note(trait_selection_try_cannot_convert)]
1565 TryCannotConvert { found: String, expected: String },
1566 #[suggestion(
1567 trait_selection_tuple_trailing_comma,
1568 code = ",",
1569 applicability = "machine-applicable"
1570 )]
1571 TupleOnlyComma {
1572 #[primary_span]
1573 span: Span,
1574 },
1575 #[multipart_suggestion(
1576 trait_selection_tuple_trailing_comma,
1577 applicability = "machine-applicable"
1578 )]
1579 TupleAlsoParentheses {
1580 #[suggestion_part(code = "(")]
1581 span_low: Span,
1582 #[suggestion_part(code = ",)")]
1583 span_high: Span,
1584 },
1585 #[suggestion(
1586 trait_selection_suggest_add_let_for_letchains,
1587 style = "verbose",
1588 applicability = "machine-applicable",
1589 code = "let "
1590 )]
1591 AddLetForLetChains {
1592 #[primary_span]
1593 span: Span,
1594 },
1595}
1596
1597#[derive(Diagnostic)]
1598pub enum ObligationCauseFailureCode {
1599 #[diag(trait_selection_oc_method_compat, code = E0308)]
1600 MethodCompat {
1601 #[primary_span]
1602 span: Span,
1603 #[subdiagnostic]
1604 subdiags: Vec<TypeErrorAdditionalDiags>,
1605 },
1606 #[diag(trait_selection_oc_type_compat, code = E0308)]
1607 TypeCompat {
1608 #[primary_span]
1609 span: Span,
1610 #[subdiagnostic]
1611 subdiags: Vec<TypeErrorAdditionalDiags>,
1612 },
1613 #[diag(trait_selection_oc_const_compat, code = E0308)]
1614 ConstCompat {
1615 #[primary_span]
1616 span: Span,
1617 #[subdiagnostic]
1618 subdiags: Vec<TypeErrorAdditionalDiags>,
1619 },
1620 #[diag(trait_selection_oc_try_compat, code = E0308)]
1621 TryCompat {
1622 #[primary_span]
1623 span: Span,
1624 #[subdiagnostic]
1625 subdiags: Vec<TypeErrorAdditionalDiags>,
1626 },
1627 #[diag(trait_selection_oc_match_compat, code = E0308)]
1628 MatchCompat {
1629 #[primary_span]
1630 span: Span,
1631 #[subdiagnostic]
1632 subdiags: Vec<TypeErrorAdditionalDiags>,
1633 },
1634 #[diag(trait_selection_oc_if_else_different, code = E0308)]
1635 IfElseDifferent {
1636 #[primary_span]
1637 span: Span,
1638 #[subdiagnostic]
1639 subdiags: Vec<TypeErrorAdditionalDiags>,
1640 },
1641 #[diag(trait_selection_oc_no_else, code = E0317)]
1642 NoElse {
1643 #[primary_span]
1644 span: Span,
1645 },
1646 #[diag(trait_selection_oc_no_diverge, code = E0308)]
1647 NoDiverge {
1648 #[primary_span]
1649 span: Span,
1650 #[subdiagnostic]
1651 subdiags: Vec<TypeErrorAdditionalDiags>,
1652 },
1653 #[diag(trait_selection_oc_fn_main_correct_type, code = E0580)]
1654 FnMainCorrectType {
1655 #[primary_span]
1656 span: Span,
1657 },
1658 #[diag(trait_selection_oc_fn_lang_correct_type, code = E0308)]
1659 FnLangCorrectType {
1660 #[primary_span]
1661 span: Span,
1662 #[subdiagnostic]
1663 subdiags: Vec<TypeErrorAdditionalDiags>,
1664 lang_item_name: Symbol,
1665 },
1666 #[diag(trait_selection_oc_intrinsic_correct_type, code = E0308)]
1667 IntrinsicCorrectType {
1668 #[primary_span]
1669 span: Span,
1670 #[subdiagnostic]
1671 subdiags: Vec<TypeErrorAdditionalDiags>,
1672 },
1673 #[diag(trait_selection_oc_method_correct_type, code = E0308)]
1674 MethodCorrectType {
1675 #[primary_span]
1676 span: Span,
1677 #[subdiagnostic]
1678 subdiags: Vec<TypeErrorAdditionalDiags>,
1679 },
1680 #[diag(trait_selection_oc_closure_selfref, code = E0644)]
1681 ClosureSelfref {
1682 #[primary_span]
1683 span: Span,
1684 },
1685 #[diag(trait_selection_oc_cant_coerce_force_inline, code = E0308)]
1686 CantCoerceForceInline {
1687 #[primary_span]
1688 span: Span,
1689 #[subdiagnostic]
1690 subdiags: Vec<TypeErrorAdditionalDiags>,
1691 },
1692 #[diag(trait_selection_oc_cant_coerce_intrinsic, code = E0308)]
1693 CantCoerceIntrinsic {
1694 #[primary_span]
1695 span: Span,
1696 #[subdiagnostic]
1697 subdiags: Vec<TypeErrorAdditionalDiags>,
1698 },
1699 #[diag(trait_selection_oc_generic, code = E0308)]
1700 Generic {
1701 #[primary_span]
1702 span: Span,
1703 #[subdiagnostic]
1704 subdiags: Vec<TypeErrorAdditionalDiags>,
1705 },
1706}
1707
1708#[derive(Subdiagnostic)]
1709pub enum AddPreciseCapturing {
1710 #[suggestion(
1711 trait_selection_precise_capturing_new,
1712 style = "verbose",
1713 code = " + use<{concatenated_bounds}>",
1714 applicability = "machine-applicable"
1715 )]
1716 New {
1717 #[primary_span]
1718 span: Span,
1719 new_lifetime: Symbol,
1720 concatenated_bounds: String,
1721 },
1722 #[suggestion(
1723 trait_selection_precise_capturing_existing,
1724 style = "verbose",
1725 code = "{pre}{new_lifetime}{post}",
1726 applicability = "machine-applicable"
1727 )]
1728 Existing {
1729 #[primary_span]
1730 span: Span,
1731 new_lifetime: Symbol,
1732 pre: &'static str,
1733 post: &'static str,
1734 },
1735}
1736
1737pub struct AddPreciseCapturingAndParams {
1738 pub suggs: Vec<(Span, String)>,
1739 pub new_lifetime: Symbol,
1740 pub apit_spans: Vec<Span>,
1741}
1742
1743impl Subdiagnostic for AddPreciseCapturingAndParams {
1744 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1745 diag.arg("new_lifetime", self.new_lifetime);
1746 diag.multipart_suggestion_verbose(
1747 fluent::trait_selection_precise_capturing_new_but_apit,
1748 self.suggs,
1749 Applicability::MaybeIncorrect,
1750 );
1751 diag.span_note(
1752 self.apit_spans,
1753 fluent::trait_selection_warn_removing_apit_params_for_undercapture,
1754 );
1755 }
1756}
1757
1758pub fn impl_trait_overcapture_suggestion<'tcx>(
1763 tcx: TyCtxt<'tcx>,
1764 opaque_def_id: LocalDefId,
1765 fn_def_id: LocalDefId,
1766 captured_args: FxIndexSet<DefId>,
1767) -> Option<AddPreciseCapturingForOvercapture> {
1768 let generics = tcx.generics_of(fn_def_id);
1769
1770 let mut captured_lifetimes = FxIndexSet::default();
1771 let mut captured_non_lifetimes = FxIndexSet::default();
1772 let mut synthetics = vec![];
1773
1774 for arg in captured_args {
1775 if tcx.def_kind(arg) == DefKind::LifetimeParam {
1776 captured_lifetimes.insert(tcx.item_name(arg));
1777 } else {
1778 let idx = generics.param_def_id_to_index(tcx, arg).expect("expected arg in scope");
1779 let param = generics.param_at(idx as usize, tcx);
1780 if param.kind.is_synthetic() {
1781 synthetics.push((tcx.def_span(arg), param.name));
1782 } else {
1783 captured_non_lifetimes.insert(tcx.item_name(arg));
1784 }
1785 }
1786 }
1787
1788 let mut next_fresh_param = || {
1789 ["T", "U", "V", "W", "X", "Y", "A", "B", "C"]
1790 .into_iter()
1791 .map(Symbol::intern)
1792 .chain((0..).map(|i| Symbol::intern(&format!("T{i}"))))
1793 .find(|s| captured_non_lifetimes.insert(*s))
1794 .unwrap()
1795 };
1796
1797 let mut suggs = vec![];
1798 let mut apit_spans = vec![];
1799
1800 if !synthetics.is_empty() {
1801 let mut new_params = String::new();
1802 for (i, (span, name)) in synthetics.into_iter().enumerate() {
1803 apit_spans.push(span);
1804
1805 let fresh_param = next_fresh_param();
1806
1807 suggs.push((span, fresh_param.to_string()));
1809
1810 if i > 0 {
1818 new_params += ", ";
1819 }
1820 let name_as_bounds = name.as_str().trim_start_matches("impl").trim_start();
1821 new_params += fresh_param.as_str();
1822 new_params += ": ";
1823 new_params += name_as_bounds;
1824 }
1825
1826 let Some(generics) = tcx.hir_get_generics(fn_def_id) else {
1827 return None;
1829 };
1830
1831 suggs.push(if let Some(params_span) = generics.span_for_param_suggestion() {
1833 (params_span, format!(", {new_params}"))
1834 } else {
1835 (generics.span, format!("<{new_params}>"))
1836 });
1837 }
1838
1839 let concatenated_bounds = captured_lifetimes
1840 .into_iter()
1841 .chain(captured_non_lifetimes)
1842 .map(|sym| sym.to_string())
1843 .collect::<Vec<_>>()
1844 .join(", ");
1845
1846 let opaque_hir_id = tcx.local_def_id_to_hir_id(opaque_def_id);
1847 let (lparen, rparen) = match tcx
1849 .hir_parent_iter(opaque_hir_id)
1850 .nth(1)
1851 .expect("expected ty to have a parent always")
1852 .1
1853 {
1854 Node::PathSegment(segment)
1855 if segment.args().paren_sugar_output().is_some_and(|ty| ty.hir_id == opaque_hir_id) =>
1856 {
1857 ("(", ")")
1858 }
1859 Node::Ty(ty) => match ty.kind {
1860 rustc_hir::TyKind::Ptr(_) | rustc_hir::TyKind::Ref(..) => ("(", ")"),
1861 _ => ("", ""),
1865 },
1866 _ => ("", ""),
1867 };
1868
1869 let rpit_span = tcx.def_span(opaque_def_id);
1870 if !lparen.is_empty() {
1871 suggs.push((rpit_span.shrink_to_lo(), lparen.to_string()));
1872 }
1873 suggs.push((rpit_span.shrink_to_hi(), format!(" + use<{concatenated_bounds}>{rparen}")));
1874
1875 Some(AddPreciseCapturingForOvercapture { suggs, apit_spans })
1876}
1877
1878pub struct AddPreciseCapturingForOvercapture {
1879 pub suggs: Vec<(Span, String)>,
1880 pub apit_spans: Vec<Span>,
1881}
1882
1883impl Subdiagnostic for AddPreciseCapturingForOvercapture {
1884 fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
1885 let applicability = if self.apit_spans.is_empty() {
1886 Applicability::MachineApplicable
1887 } else {
1888 Applicability::MaybeIncorrect
1892 };
1893 diag.multipart_suggestion_verbose(
1894 fluent::trait_selection_precise_capturing_overcaptures,
1895 self.suggs,
1896 applicability,
1897 );
1898 if !self.apit_spans.is_empty() {
1899 diag.span_note(
1900 self.apit_spans,
1901 fluent::trait_selection_warn_removing_apit_params_for_overcapture,
1902 );
1903 }
1904 }
1905}
1906
1907#[derive(Diagnostic)]
1908#[diag(trait_selection_opaque_type_non_generic_param, code = E0792)]
1909pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
1910 pub arg: GenericArg<'tcx>,
1911 pub kind: &'a str,
1912 #[primary_span]
1913 pub span: Span,
1914 #[label]
1915 pub param_span: Span,
1916}