Skip to content

Commit 1e2f33c

Browse files
authored
Rollup merge of rust-lang#100843 - IntQuant:issue-100717-infer, r=compiler-errors
Migrate part of rustc_infer to session diagnostic
2 parents 91de6b6 + e1765a9 commit 1e2f33c

File tree

10 files changed

+649
-212
lines changed

10 files changed

+649
-212
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3631,6 +3631,7 @@ dependencies = [
36313631
"rustc_macros",
36323632
"rustc_middle",
36333633
"rustc_serialize",
3634+
"rustc_session",
36343635
"rustc_span",
36353636
"rustc_target",
36363637
"smallvec",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
infer_opaque_hidden_type =
2+
opaque type's hidden type cannot be another opaque type from the same scope
3+
.label = one of the two opaque types used here has to be outside its defining scope
4+
.opaque_type = opaque type whose hidden type is being assigned
5+
.hidden_type = opaque type being used as hidden type
6+
7+
infer_type_annotations_needed = {$source_kind ->
8+
[closure] type annotations needed for the closure `{$source_name}`
9+
[normal] type annotations needed for `{$source_name}`
10+
*[other] type annotations needed
11+
}
12+
.label = type must be known at this point
13+
14+
infer_label_bad = {$bad_kind ->
15+
*[other] cannot infer type
16+
[more_info] cannot infer {$prefix_kind ->
17+
*[type] type for {$prefix}
18+
[const_with_param] the value of const parameter
19+
[const] the value of the constant
20+
} `{$name}`{$has_parent ->
21+
[true] {" "}declared on the {$parent_prefix} `{$parent_name}`
22+
*[false] {""}
23+
}
24+
}
25+
26+
infer_source_kind_subdiag_let = {$kind ->
27+
[with_pattern] consider giving `{$name}` an explicit type
28+
[closure] consider giving this closure parameter an explicit type
29+
*[other] consider giving this pattern a type
30+
}{$x_kind ->
31+
[has_name] , where the {$prefix_kind ->
32+
*[type] type for {$prefix}
33+
[const_with_param] the value of const parameter
34+
[const] the value of the constant
35+
} `{$arg_name}` is specified
36+
[underscore] , where the placeholders `_` are specified
37+
*[empty] {""}
38+
}
39+
40+
infer_source_kind_subdiag_generic_label =
41+
cannot infer {$is_type ->
42+
[true] type
43+
*[false] the value
44+
} of the {$is_type ->
45+
[true] type
46+
*[false] const
47+
} {$parent_exists ->
48+
[true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}`
49+
*[false] parameter {$param_name}
50+
}
51+
52+
infer_source_kind_subdiag_generic_suggestion =
53+
consider specifying the generic {$arg_count ->
54+
[one] argument
55+
*[other] arguments
56+
}
57+
58+
infer_source_kind_fully_qualified =
59+
try using a fully qualified path to specify the expected types
60+
61+
infer_source_kind_closure_return =
62+
try giving this closure an explicit return type
63+
64+
# generator_kind may need to be translated
65+
infer_need_type_info_in_generator =
66+
type inside {$generator_kind ->
67+
[async_block] `async` block
68+
[async_closure] `async` closure
69+
[async_fn] `async fn` body
70+
*[generator] generator
71+
} must be known in this context
72+
73+
74+
infer_subtype = ...so that the {$requirement ->
75+
[method_compat] method type is compatible with trait
76+
[type_compat] associated type is compatible with trait
77+
[const_compat] const is compatible with trait
78+
[expr_assignable] expression is assignable
79+
[if_else_different] `if` and `else` have incompatible types
80+
[no_else] `if` missing an `else` returns `()`
81+
[fn_main_correct_type] `main` function has the correct type
82+
[fn_start_correct_type] #[start]` function has the correct type
83+
[intristic_correct_type] intrinsic has the correct type
84+
[method_correct_type] method receiver has the correct type
85+
*[other] types are compatible
86+
}
87+
infer_subtype_2 = ...so that {$requirement ->
88+
[method_compat] method type is compatible with trait
89+
[type_compat] associated type is compatible with trait
90+
[const_compat] const is compatible with trait
91+
[expr_assignable] expression is assignable
92+
[if_else_different] `if` and `else` have incompatible types
93+
[no_else] `if` missing an `else` returns `()`
94+
[fn_main_correct_type] `main` function has the correct type
95+
[fn_start_correct_type] #[start]` function has the correct type
96+
[intristic_correct_type] intrinsic has the correct type
97+
[method_correct_type] method receiver has the correct type
98+
*[other] types are compatible
99+
}
100+
101+
infer_reborrow = ...so that reference does not outlive borrowed content
102+
infer_reborrow_upvar = ...so that closure can access `{$name}`
103+
infer_relate_object_bound = ...so that it can be closed over into an object
104+
infer_data_borrowed = ...so that the type `{$name}` is not borrowed for too long
105+
infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
106+
infer_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
107+
[true] ...
108+
*[false] {""}
109+
}
110+
infer_relate_param_bound_2 = ...that is required by this bound
111+
infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied
112+
infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait

compiler/rustc_error_messages/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ fluent_messages! {
4141
driver => "../locales/en-US/driver.ftl",
4242
expand => "../locales/en-US/expand.ftl",
4343
interface => "../locales/en-US/interface.ftl",
44+
infer => "../locales/en-US/infer.ftl",
4445
lint => "../locales/en-US/lint.ftl",
4546
parser => "../locales/en-US/parser.ftl",
4647
passes => "../locales/en-US/passes.ftl",

compiler/rustc_infer/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ rustc_hir = { path = "../rustc_hir" }
1515
rustc_index = { path = "../rustc_index" }
1616
rustc_macros = { path = "../rustc_macros" }
1717
rustc_serialize = { path = "../rustc_serialize" }
18+
rustc_session = { path = "../rustc_session" }
1819
rustc_span = { path = "../rustc_span" }
1920
rustc_target = { path = "../rustc_target" }
2021
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }

compiler/rustc_infer/src/errors.rs

+254
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
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+
}

0 commit comments

Comments
 (0)