]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_infer/src/errors.rs
Migrate note_region_origin function
[rust.git] / compiler / rustc_infer / src / errors.rs
1 use rustc_errors::{fluent, AddSubdiagnostic, DiagnosticMessage, DiagnosticStyledString};
2 use rustc_hir::FnRetTy;
3 use rustc_macros::SessionDiagnostic;
4 use rustc_span::{BytePos, Span};
5
6 #[derive(SessionDiagnostic)]
7 #[diag(infer::opaque_hidden_type)]
8 pub struct OpaqueHiddenTypeDiag {
9     #[primary_span]
10     #[label]
11     pub span: Span,
12     #[note(infer::opaque_type)]
13     pub opaque_type: Span,
14     #[note(infer::hidden_type)]
15     pub hidden_type: Span,
16 }
17
18 #[derive(SessionDiagnostic)]
19 #[diag(infer::type_annotations_needed, code = "E0282")]
20 pub struct AnnotationRequired<'a> {
21     #[primary_span]
22     pub span: Span,
23     pub source_kind: &'static str,
24     pub source_name: &'a str,
25     #[label]
26     pub failure_span: Option<Span>,
27     #[subdiagnostic]
28     pub bad_label: Option<InferenceBadError<'a>>,
29     #[subdiagnostic]
30     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
31     #[subdiagnostic]
32     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
33 }
34
35 // Copy of `AnnotationRequired` for E0283
36 #[derive(SessionDiagnostic)]
37 #[diag(infer::type_annotations_needed, code = "E0283")]
38 pub struct AmbigousImpl<'a> {
39     #[primary_span]
40     pub span: Span,
41     pub source_kind: &'static str,
42     pub source_name: &'a str,
43     #[label]
44     pub failure_span: Option<Span>,
45     #[subdiagnostic]
46     pub bad_label: Option<InferenceBadError<'a>>,
47     #[subdiagnostic]
48     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
49     #[subdiagnostic]
50     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
51 }
52
53 // Copy of `AnnotationRequired` for E0284
54 #[derive(SessionDiagnostic)]
55 #[diag(infer::type_annotations_needed, code = "E0284")]
56 pub struct AmbigousReturn<'a> {
57     #[primary_span]
58     pub span: Span,
59     pub source_kind: &'static str,
60     pub source_name: &'a str,
61     #[label]
62     pub failure_span: Option<Span>,
63     #[subdiagnostic]
64     pub bad_label: Option<InferenceBadError<'a>>,
65     #[subdiagnostic]
66     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
67     #[subdiagnostic]
68     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
69 }
70
71 #[derive(SessionDiagnostic)]
72 #[diag(infer::need_type_info_in_generator, code = "E0698")]
73 pub struct NeedTypeInfoInGenerator<'a> {
74     #[primary_span]
75     pub span: Span,
76     pub generator_kind: &'static str,
77     #[subdiagnostic]
78     pub bad_label: InferenceBadError<'a>,
79 }
80
81 // Used when a better one isn't available
82 #[derive(SessionSubdiagnostic)]
83 #[label(infer::label_bad)]
84 pub struct InferenceBadError<'a> {
85     #[primary_span]
86     pub span: Span,
87     pub bad_kind: &'static str,
88     pub prefix_kind: &'static str,
89     pub has_parent: bool,
90     pub prefix: &'a str,
91     pub parent_prefix: &'a str,
92     pub parent_name: String,
93     pub name: String,
94 }
95
96 #[derive(SessionSubdiagnostic)]
97 pub enum SourceKindSubdiag<'a> {
98     #[suggestion_verbose(
99         infer::source_kind_subdiag_let,
100         code = ": {type_name}",
101         applicability = "has-placeholders"
102     )]
103     LetLike {
104         #[primary_span]
105         span: Span,
106         name: String,
107         type_name: String,
108         kind: &'static str,
109         x_kind: &'static str,
110         prefix_kind: &'static str,
111         prefix: &'a str,
112         arg_name: String,
113     },
114     #[label(infer::source_kind_subdiag_generic_label)]
115     GenericLabel {
116         #[primary_span]
117         span: Span,
118         is_type: bool,
119         param_name: String,
120         parent_exists: bool,
121         parent_prefix: String,
122         parent_name: String,
123     },
124     #[suggestion_verbose(
125         infer::source_kind_subdiag_generic_suggestion,
126         code = "::<{args}>",
127         applicability = "has-placeholders"
128     )]
129     GenericSuggestion {
130         #[primary_span]
131         span: Span,
132         arg_count: usize,
133         args: String,
134     },
135 }
136
137 // Has to be implemented manually because multipart suggestions are not supported by the derive macro.
138 // Would be a part of `SourceKindSubdiag` otherwise.
139 pub enum SourceKindMultiSuggestion<'a> {
140     FullyQualified {
141         span: Span,
142         def_path: String,
143         adjustment: &'a str,
144         successor: (&'a str, BytePos),
145     },
146     ClosureReturn {
147         ty_info: String,
148         data: &'a FnRetTy<'a>,
149         should_wrap_expr: Option<Span>,
150     },
151 }
152
153 impl AddSubdiagnostic for SourceKindMultiSuggestion<'_> {
154     fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
155         match self {
156             Self::FullyQualified { span, def_path, adjustment, successor } => {
157                 let suggestion = vec![
158                     (span.shrink_to_lo(), format!("{def_path}({adjustment}")),
159                     (span.shrink_to_hi().with_hi(successor.1), successor.0.to_string()),
160                 ];
161                 diag.multipart_suggestion_verbose(
162                     fluent::infer::source_kind_fully_qualified,
163                     suggestion,
164                     rustc_errors::Applicability::HasPlaceholders,
165                 );
166             }
167             Self::ClosureReturn { ty_info, data, should_wrap_expr } => {
168                 let (arrow, post) = match data {
169                     FnRetTy::DefaultReturn(_) => ("-> ", " "),
170                     _ => ("", ""),
171                 };
172                 let suggestion = match should_wrap_expr {
173                     Some(end_span) => vec![
174                         (data.span(), format!("{}{}{}{{ ", arrow, ty_info, post)),
175                         (end_span, " }".to_string()),
176                     ],
177                     None => vec![(data.span(), format!("{}{}{}", arrow, ty_info, post))],
178                 };
179                 diag.multipart_suggestion_verbose(
180                     fluent::infer::source_kind_closure_return,
181                     suggestion,
182                     rustc_errors::Applicability::HasPlaceholders,
183                 );
184             }
185         }
186     }
187 }
188
189 pub enum RegionOriginNote<'a> {
190     Plain {
191         span: Span,
192         msg: DiagnosticMessage,
193     },
194     WithName {
195         span: Span,
196         msg: DiagnosticMessage,
197         name: &'a str,
198         continues: bool,
199     },
200     WithRequirement {
201         span: Span,
202         requirement: &'static str,
203         expected_found: Option<(DiagnosticStyledString, DiagnosticStyledString)>,
204     },
205 }
206
207 impl AddSubdiagnostic for RegionOriginNote<'_> {
208     fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
209         let mut label_or_note = |span, msg: DiagnosticMessage| {
210             let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
211             let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
212             let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span);
213             if span_is_primary && sub_count == 0 && expanded_sub_count == 0 {
214                 diag.span_label(span, msg);
215             } else if span_is_primary && expanded_sub_count == 0 {
216                 diag.note(msg);
217             } else {
218                 diag.span_note(span, msg);
219             }
220         };
221         match self {
222             RegionOriginNote::Plain { span, msg } => {
223                 label_or_note(span, msg);
224             }
225             RegionOriginNote::WithName { span, msg, name, continues } => {
226                 label_or_note(span, msg);
227                 diag.set_arg("name", name);
228                 diag.set_arg("continues", continues);
229             }
230             RegionOriginNote::WithRequirement {
231                 span,
232                 requirement,
233                 expected_found: Some((expected, found)),
234             } => {
235                 label_or_note(span, fluent::infer::subtype);
236                 diag.set_arg("requirement", requirement);
237
238                 diag.note_expected_found(&"", expected, &"", found);
239             }
240             RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => {
241                 // FIXME: this really should be handled at some earlier stage. Our
242                 // handling of region checking when type errors are present is
243                 // *terrible*.
244                 label_or_note(span, fluent::infer::subtype_2);
245                 diag.set_arg("requirement", requirement);
246             }
247         };
248     }
249 }