1 use rustc_errors::{fluent, AddSubdiagnostic, DiagnosticMessage, DiagnosticStyledString};
2 use rustc_hir::FnRetTy;
3 use rustc_macros::SessionDiagnostic;
4 use rustc_span::{BytePos, Span};
6 use crate::infer::error_reporting::{
7 need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind},
8 ObligationCauseAsDiagArg,
11 #[derive(SessionDiagnostic)]
12 #[diag(infer::opaque_hidden_type)]
13 pub struct OpaqueHiddenTypeDiag {
17 #[note(infer::opaque_type)]
18 pub opaque_type: Span,
19 #[note(infer::hidden_type)]
20 pub hidden_type: Span,
23 #[derive(SessionDiagnostic)]
24 #[diag(infer::type_annotations_needed, code = "E0282")]
25 pub struct AnnotationRequired<'a> {
28 pub source_kind: &'static str,
29 pub source_name: &'a str,
31 pub failure_span: Option<Span>,
33 pub bad_label: Option<InferenceBadError<'a>>,
35 pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
37 pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
40 // Copy of `AnnotationRequired` for E0283
41 #[derive(SessionDiagnostic)]
42 #[diag(infer::type_annotations_needed, code = "E0283")]
43 pub struct AmbigousImpl<'a> {
46 pub source_kind: &'static str,
47 pub source_name: &'a str,
49 pub failure_span: Option<Span>,
51 pub bad_label: Option<InferenceBadError<'a>>,
53 pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
55 pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
58 // Copy of `AnnotationRequired` for E0284
59 #[derive(SessionDiagnostic)]
60 #[diag(infer::type_annotations_needed, code = "E0284")]
61 pub struct AmbigousReturn<'a> {
64 pub source_kind: &'static str,
65 pub source_name: &'a str,
67 pub failure_span: Option<Span>,
69 pub bad_label: Option<InferenceBadError<'a>>,
71 pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
73 pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
76 #[derive(SessionDiagnostic)]
77 #[diag(infer::need_type_info_in_generator, code = "E0698")]
78 pub struct NeedTypeInfoInGenerator<'a> {
81 pub generator_kind: GeneratorKindAsDiagArg,
83 pub bad_label: InferenceBadError<'a>,
86 // Used when a better one isn't available
87 #[derive(SessionSubdiagnostic)]
88 #[label(infer::label_bad)]
89 pub struct InferenceBadError<'a> {
92 pub bad_kind: &'static str,
93 pub prefix_kind: UnderspecifiedArgKind,
96 pub parent_prefix: &'a str,
97 pub parent_name: String,
101 #[derive(SessionSubdiagnostic)]
102 pub enum SourceKindSubdiag<'a> {
103 #[suggestion_verbose(
104 infer::source_kind_subdiag_let,
105 code = ": {type_name}",
106 applicability = "has-placeholders"
114 x_kind: &'static str,
115 prefix_kind: UnderspecifiedArgKind,
119 #[label(infer::source_kind_subdiag_generic_label)]
126 parent_prefix: String,
129 #[suggestion_verbose(
130 infer::source_kind_subdiag_generic_suggestion,
132 applicability = "has-placeholders"
142 // Has to be implemented manually because multipart suggestions are not supported by the derive macro.
143 // Would be a part of `SourceKindSubdiag` otherwise.
144 pub enum SourceKindMultiSuggestion<'a> {
149 successor: (&'a str, BytePos),
153 data: &'a FnRetTy<'a>,
154 should_wrap_expr: Option<Span>,
158 impl AddSubdiagnostic for SourceKindMultiSuggestion<'_> {
159 fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
161 Self::FullyQualified { span, def_path, adjustment, successor } => {
162 let suggestion = vec![
163 (span.shrink_to_lo(), format!("{def_path}({adjustment}")),
164 (span.shrink_to_hi().with_hi(successor.1), successor.0.to_string()),
166 diag.multipart_suggestion_verbose(
167 fluent::infer::source_kind_fully_qualified,
169 rustc_errors::Applicability::HasPlaceholders,
172 Self::ClosureReturn { ty_info, data, should_wrap_expr } => {
173 let (arrow, post) = match data {
174 FnRetTy::DefaultReturn(_) => ("-> ", " "),
177 let suggestion = match should_wrap_expr {
178 Some(end_span) => vec![
179 (data.span(), format!("{}{}{}{{ ", arrow, ty_info, post)),
180 (end_span, " }".to_string()),
182 None => vec![(data.span(), format!("{}{}{}", arrow, ty_info, post))],
184 diag.multipart_suggestion_verbose(
185 fluent::infer::source_kind_closure_return,
187 rustc_errors::Applicability::HasPlaceholders,
194 pub enum RegionOriginNote<'a> {
197 msg: DiagnosticMessage,
201 msg: DiagnosticMessage,
207 requirement: ObligationCauseAsDiagArg<'a>,
208 expected_found: Option<(DiagnosticStyledString, DiagnosticStyledString)>,
212 impl AddSubdiagnostic for RegionOriginNote<'_> {
213 fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
214 let mut label_or_note = |span, msg: DiagnosticMessage| {
215 let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
216 let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
217 let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span);
218 if span_is_primary && sub_count == 0 && expanded_sub_count == 0 {
219 diag.span_label(span, msg);
220 } else if span_is_primary && expanded_sub_count == 0 {
223 diag.span_note(span, msg);
227 RegionOriginNote::Plain { span, msg } => {
228 label_or_note(span, msg);
230 RegionOriginNote::WithName { span, msg, name, continues } => {
231 label_or_note(span, msg);
232 diag.set_arg("name", name);
233 diag.set_arg("continues", continues);
235 RegionOriginNote::WithRequirement {
238 expected_found: Some((expected, found)),
240 label_or_note(span, fluent::infer::subtype);
241 diag.set_arg("requirement", requirement);
243 diag.note_expected_found(&"", expected, &"", found);
245 RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => {
246 // FIXME: this really should be handled at some earlier stage. Our
247 // handling of region checking when type errors are present is
249 label_or_note(span, fluent::infer::subtype_2);
250 diag.set_arg("requirement", requirement);