]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_infer/src/errors.rs
Rollup merge of #101447 - cjgillot:no-remap-resolver, r=spastorino
[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 use crate::infer::error_reporting::{
7     need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind},
8     ObligationCauseAsDiagArg,
9 };
10
11 #[derive(SessionDiagnostic)]
12 #[diag(infer::opaque_hidden_type)]
13 pub struct OpaqueHiddenTypeDiag {
14     #[primary_span]
15     #[label]
16     pub span: Span,
17     #[note(infer::opaque_type)]
18     pub opaque_type: Span,
19     #[note(infer::hidden_type)]
20     pub hidden_type: Span,
21 }
22
23 #[derive(SessionDiagnostic)]
24 #[diag(infer::type_annotations_needed, code = "E0282")]
25 pub struct AnnotationRequired<'a> {
26     #[primary_span]
27     pub span: Span,
28     pub source_kind: &'static str,
29     pub source_name: &'a str,
30     #[label]
31     pub failure_span: Option<Span>,
32     #[subdiagnostic]
33     pub bad_label: Option<InferenceBadError<'a>>,
34     #[subdiagnostic]
35     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
36     #[subdiagnostic]
37     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
38 }
39
40 // Copy of `AnnotationRequired` for E0283
41 #[derive(SessionDiagnostic)]
42 #[diag(infer::type_annotations_needed, code = "E0283")]
43 pub struct AmbigousImpl<'a> {
44     #[primary_span]
45     pub span: Span,
46     pub source_kind: &'static str,
47     pub source_name: &'a str,
48     #[label]
49     pub failure_span: Option<Span>,
50     #[subdiagnostic]
51     pub bad_label: Option<InferenceBadError<'a>>,
52     #[subdiagnostic]
53     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
54     #[subdiagnostic]
55     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
56 }
57
58 // Copy of `AnnotationRequired` for E0284
59 #[derive(SessionDiagnostic)]
60 #[diag(infer::type_annotations_needed, code = "E0284")]
61 pub struct AmbigousReturn<'a> {
62     #[primary_span]
63     pub span: Span,
64     pub source_kind: &'static str,
65     pub source_name: &'a str,
66     #[label]
67     pub failure_span: Option<Span>,
68     #[subdiagnostic]
69     pub bad_label: Option<InferenceBadError<'a>>,
70     #[subdiagnostic]
71     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
72     #[subdiagnostic]
73     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
74 }
75
76 #[derive(SessionDiagnostic)]
77 #[diag(infer::need_type_info_in_generator, code = "E0698")]
78 pub struct NeedTypeInfoInGenerator<'a> {
79     #[primary_span]
80     pub span: Span,
81     pub generator_kind: GeneratorKindAsDiagArg,
82     #[subdiagnostic]
83     pub bad_label: InferenceBadError<'a>,
84 }
85
86 // Used when a better one isn't available
87 #[derive(SessionSubdiagnostic)]
88 #[label(infer::label_bad)]
89 pub struct InferenceBadError<'a> {
90     #[primary_span]
91     pub span: Span,
92     pub bad_kind: &'static str,
93     pub prefix_kind: UnderspecifiedArgKind,
94     pub has_parent: bool,
95     pub prefix: &'a str,
96     pub parent_prefix: &'a str,
97     pub parent_name: String,
98     pub name: String,
99 }
100
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"
107     )]
108     LetLike {
109         #[primary_span]
110         span: Span,
111         name: String,
112         type_name: String,
113         kind: &'static str,
114         x_kind: &'static str,
115         prefix_kind: UnderspecifiedArgKind,
116         prefix: &'a str,
117         arg_name: String,
118     },
119     #[label(infer::source_kind_subdiag_generic_label)]
120     GenericLabel {
121         #[primary_span]
122         span: Span,
123         is_type: bool,
124         param_name: String,
125         parent_exists: bool,
126         parent_prefix: String,
127         parent_name: String,
128     },
129     #[suggestion_verbose(
130         infer::source_kind_subdiag_generic_suggestion,
131         code = "::<{args}>",
132         applicability = "has-placeholders"
133     )]
134     GenericSuggestion {
135         #[primary_span]
136         span: Span,
137         arg_count: usize,
138         args: String,
139     },
140 }
141
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> {
145     FullyQualified {
146         span: Span,
147         def_path: String,
148         adjustment: &'a str,
149         successor: (&'a str, BytePos),
150     },
151     ClosureReturn {
152         ty_info: String,
153         data: &'a FnRetTy<'a>,
154         should_wrap_expr: Option<Span>,
155     },
156 }
157
158 impl AddSubdiagnostic for SourceKindMultiSuggestion<'_> {
159     fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
160         match self {
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()),
165                 ];
166                 diag.multipart_suggestion_verbose(
167                     fluent::infer::source_kind_fully_qualified,
168                     suggestion,
169                     rustc_errors::Applicability::HasPlaceholders,
170                 );
171             }
172             Self::ClosureReturn { ty_info, data, should_wrap_expr } => {
173                 let (arrow, post) = match data {
174                     FnRetTy::DefaultReturn(_) => ("-> ", " "),
175                     _ => ("", ""),
176                 };
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()),
181                     ],
182                     None => vec![(data.span(), format!("{}{}{}", arrow, ty_info, post))],
183                 };
184                 diag.multipart_suggestion_verbose(
185                     fluent::infer::source_kind_closure_return,
186                     suggestion,
187                     rustc_errors::Applicability::HasPlaceholders,
188                 );
189             }
190         }
191     }
192 }
193
194 pub enum RegionOriginNote<'a> {
195     Plain {
196         span: Span,
197         msg: DiagnosticMessage,
198     },
199     WithName {
200         span: Span,
201         msg: DiagnosticMessage,
202         name: &'a str,
203         continues: bool,
204     },
205     WithRequirement {
206         span: Span,
207         requirement: ObligationCauseAsDiagArg<'a>,
208         expected_found: Option<(DiagnosticStyledString, DiagnosticStyledString)>,
209     },
210 }
211
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 {
221                 diag.note(msg);
222             } else {
223                 diag.span_note(span, msg);
224             }
225         };
226         match self {
227             RegionOriginNote::Plain { span, msg } => {
228                 label_or_note(span, msg);
229             }
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);
234             }
235             RegionOriginNote::WithRequirement {
236                 span,
237                 requirement,
238                 expected_found: Some((expected, found)),
239             } => {
240                 label_or_note(span, fluent::infer::subtype);
241                 diag.set_arg("requirement", requirement);
242
243                 diag.note_expected_found(&"", expected, &"", found);
244             }
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
248                 // *terrible*.
249                 label_or_note(span, fluent::infer::subtype_2);
250                 diag.set_arg("requirement", requirement);
251             }
252         };
253     }
254 }