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