Skip to content

Commit f50d171

Browse files
committed
Migrate note_region_origin function
1 parent 3f6cb47 commit f50d171

File tree

4 files changed

+173
-53
lines changed

4 files changed

+173
-53
lines changed

compiler/rustc_error_messages/locales/en-US/infer.ftl

+43
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,48 @@ infer_source_kind_fully_qualified =
6161
infer_source_kind_closure_return =
6262
try giving this closure an explicit return type
6363
64+
# generator_kind may need to be translated
6465
infer_need_type_info_in_generator =
6566
type inside {$generator_kind} must be known in this context
67+
68+
69+
infer_subtype = ...so that the {$requirement ->
70+
[method_compat] method type is compatible with trait
71+
[type_compat] associated type is compatible with trait
72+
[const_compat] const is compatible with trait
73+
[expr_assignable] expression is assignable
74+
[if_else_different] `if` and `else` have incompatible types
75+
[no_else] `if` missing an `else` returns `()`
76+
[fn_main_correct_type] `main` function has the correct type
77+
[fn_start_correct_type] #[start]` function has the correct type
78+
[intristic_correct_type] intrinsic has the correct type
79+
[method_correct_type] method receiver has the correct type
80+
*[other] types are compatible
81+
}
82+
infer_subtype_2 = ...so that {$requirement ->
83+
[method_compat] method type is compatible with trait
84+
[type_compat] associated type is compatible with trait
85+
[const_compat] const is compatible with trait
86+
[expr_assignable] expression is assignable
87+
[if_else_different] `if` and `else` have incompatible types
88+
[no_else] `if` missing an `else` returns `()`
89+
[fn_main_correct_type] `main` function has the correct type
90+
[fn_start_correct_type] #[start]` function has the correct type
91+
[intristic_correct_type] intrinsic has the correct type
92+
[method_correct_type] method receiver has the correct type
93+
*[other] types are compatible
94+
}
95+
96+
infer_reborrow = ...so that reference does not outlive borrowed content
97+
infer_reborrow_upvar = ...so that closure can access `{$name}`
98+
infer_relate_object_bound = ...so that it can be closed over into an object
99+
infer_data_borrowed = ...so that the type `{$name}` is not borrowed for too long
100+
infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at
101+
infer_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues ->
102+
[true] ...
103+
*[false] {""}
104+
}
105+
infer_relate_param_bound_2 = ...that is required by this bound
106+
infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied
107+
infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait
108+

compiler/rustc_infer/src/errors.rs

+63-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_errors::{fluent, AddSubdiagnostic};
1+
use rustc_errors::{fluent, AddSubdiagnostic, DiagnosticMessage, DiagnosticStyledString};
22
use rustc_hir::FnRetTy;
33
use rustc_macros::SessionDiagnostic;
44
use rustc_span::{BytePos, Span};
@@ -185,3 +185,65 @@ impl AddSubdiagnostic for SourceKindMultiSuggestion<'_> {
185185
}
186186
}
187187
}
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+
}

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+18
Original file line numberDiff line numberDiff line change
@@ -2811,6 +2811,7 @@ pub enum FailureCode {
28112811
pub trait ObligationCauseExt<'tcx> {
28122812
fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode;
28132813
fn as_requirement_str(&self) -> &'static str;
2814+
fn as_requirement_localised(&self) -> &'static str;
28142815
}
28152816

28162817
impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
@@ -2879,6 +2880,23 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
28792880
_ => "types are compatible",
28802881
}
28812882
}
2883+
2884+
fn as_requirement_localised(&self) -> &'static str {
2885+
use crate::traits::ObligationCauseCode::*;
2886+
match self.code() {
2887+
CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => "method_compat",
2888+
CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => "type_compat",
2889+
CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => "const_compat",
2890+
ExprAssignable => "expr_assignable",
2891+
IfExpression { .. } => "if_else_different",
2892+
IfExpressionWithNoElse => "no_else",
2893+
MainFunctionType => "fn_main_correct_type",
2894+
StartFunctionType => "fn_start_correct_type",
2895+
IntrinsicType => "intristic_correct_type",
2896+
MethodReceiver => "method_correct_type",
2897+
_ => "other",
2898+
}
2899+
}
28822900
}
28832901

28842902
/// This is a bare signal of what kind of type we're dealing with. `ty::TyKind` tracks

compiler/rustc_infer/src/infer/error_reporting/note.rs

+49-52
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1+
use crate::errors::RegionOriginNote;
12
use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt};
23
use crate::infer::{self, InferCtxt, SubregionOrigin};
3-
use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
4+
use rustc_errors::{
5+
fluent, struct_span_err, AddSubdiagnostic, Diagnostic, DiagnosticBuilder, DiagnosticMessage,
6+
ErrorGuaranteed,
7+
};
48
use rustc_middle::traits::ObligationCauseCode;
59
use rustc_middle::ty::error::TypeError;
610
use rustc_middle::ty::{self, Region};
711

812
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
913
pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) {
10-
let mut label_or_note = |span, msg: &str| {
14+
let mut label_or_note = |span, msg: DiagnosticMessage| {
1115
let sub_count = err.children.iter().filter(|d| d.span.is_dummy()).count();
1216
let expanded_sub_count = err.children.iter().filter(|d| !d.span.is_dummy()).count();
1317
let span_is_primary = err.span.primary_spans().iter().all(|&sp| sp == span);
@@ -20,77 +24,70 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
2024
}
2125
};
2226
match *origin {
23-
infer::Subtype(ref trace) => {
24-
if let Some((expected, found)) = self.values_str(trace.values) {
25-
label_or_note(
26-
trace.cause.span,
27-
&format!("...so that the {}", trace.cause.as_requirement_str()),
28-
);
29-
30-
err.note_expected_found(&"", expected, &"", found);
31-
} else {
32-
// FIXME: this really should be handled at some earlier stage. Our
33-
// handling of region checking when type errors are present is
34-
// *terrible*.
35-
36-
label_or_note(
37-
trace.cause.span,
38-
&format!("...so that {}", trace.cause.as_requirement_str()),
39-
);
40-
}
27+
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
28+
span: trace.cause.span,
29+
requirement: trace.cause.as_requirement_localised(),
30+
expected_found: self.values_str(trace.values),
4131
}
32+
.add_to_diagnostic(err),
4233
infer::Reborrow(span) => {
43-
label_or_note(span, "...so that reference does not outlive borrowed content");
34+
label_or_note(span, fluent::infer::reborrow);
35+
RegionOriginNote::Plain { span, msg: fluent::infer::reborrow }
36+
.add_to_diagnostic(err)
4437
}
4538
infer::ReborrowUpvar(span, ref upvar_id) => {
4639
let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
47-
label_or_note(span, &format!("...so that closure can access `{}`", var_name));
40+
RegionOriginNote::WithName {
41+
span,
42+
msg: fluent::infer::reborrow,
43+
name: &var_name.to_string(),
44+
continues: false,
45+
}
46+
.add_to_diagnostic(err);
4847
}
4948
infer::RelateObjectBound(span) => {
50-
label_or_note(span, "...so that it can be closed over into an object");
49+
label_or_note(span, fluent::infer::relate_object_bound);
50+
RegionOriginNote::Plain { span, msg: fluent::infer::relate_object_bound }
51+
.add_to_diagnostic(err);
5152
}
5253
infer::DataBorrowed(ty, span) => {
53-
label_or_note(
54+
RegionOriginNote::WithName {
5455
span,
55-
&format!(
56-
"...so that the type `{}` is not borrowed for too long",
57-
self.ty_to_string(ty)
58-
),
59-
);
56+
msg: fluent::infer::data_borrowed,
57+
name: &self.ty_to_string(ty),
58+
continues: false,
59+
}
60+
.add_to_diagnostic(err);
6061
}
6162
infer::ReferenceOutlivesReferent(ty, span) => {
62-
label_or_note(
63+
RegionOriginNote::WithName {
6364
span,
64-
&format!(
65-
"...so that the reference type `{}` does not outlive the data it points at",
66-
self.ty_to_string(ty)
67-
),
68-
);
65+
msg: fluent::infer::reference_outlives_referent,
66+
name: &self.ty_to_string(ty),
67+
continues: false,
68+
}
69+
.add_to_diagnostic(err);
6970
}
70-
infer::RelateParamBound(span, t, opt_span) => {
71-
label_or_note(
71+
infer::RelateParamBound(span, ty, opt_span) => {
72+
RegionOriginNote::WithName {
7273
span,
73-
&format!(
74-
"...so that the type `{}` will meet its required lifetime bounds{}",
75-
self.ty_to_string(t),
76-
if opt_span.is_some() { "..." } else { "" },
77-
),
78-
);
74+
msg: fluent::infer::relate_param_bound,
75+
name: &self.ty_to_string(ty),
76+
continues: opt_span.is_some(),
77+
}
78+
.add_to_diagnostic(err);
7979
if let Some(span) = opt_span {
80-
err.span_note(span, "...that is required by this bound");
80+
RegionOriginNote::Plain { span, msg: fluent::infer::relate_param_bound_2 }
81+
.add_to_diagnostic(err);
8182
}
8283
}
8384
infer::RelateRegionParamBound(span) => {
84-
label_or_note(
85-
span,
86-
"...so that the declared lifetime parameter bounds are satisfied",
87-
);
85+
RegionOriginNote::Plain { span, msg: fluent::infer::relate_region_param_bound }
86+
.add_to_diagnostic(err);
8887
}
8988
infer::CompareImplItemObligation { span, .. } => {
90-
label_or_note(
91-
span,
92-
"...so that the definition in impl matches the definition from the trait",
93-
);
89+
RegionOriginNote::Plain { span, msg: fluent::infer::compare_impl_item_obligation }
90+
.add_to_diagnostic(err);
9491
}
9592
infer::CheckAssociatedTypeBounds { ref parent, .. } => {
9693
self.note_region_origin(err, &parent);

0 commit comments

Comments
 (0)