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