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