Skip to content

Commit 8e82200

Browse files
committed
Porting 'compiler/rustc_trait_selection' to translatable diagnostics - Part 1
1 parent fb88811 commit 8e82200

File tree

12 files changed

+180
-87
lines changed

12 files changed

+180
-87
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries}
2+
3+
trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
4+
5+
trait_selection_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
6+
.label = deref recursion limit reached
7+
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
8+
9+
trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
10+
.label = empty on-clause here
11+
12+
trait_selection_invalid_on_clause_in_rustc_on_unimplemented = invalid `on`-clause in `#[rustc_on_unimplemented]`
13+
.label = invalid on-clause here
14+
15+
trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a valid value
16+
.label = expected value here
17+
.note = eg `#[rustc_on_unimplemented(message="foo")]`
18+
19+
trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc ->
20+
[none] {""}
21+
*[default] {" "}for type `{$self_desc}`
22+
}:
23+
.negative_implementation_here = negative implementation here
24+
.negative_implementation_in_crate = negative implementation in crate `{$negative_impl_cname}`
25+
.positive_implementation_here = positive implementation here
26+
.positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}`

Diff for: compiler/rustc_error_messages/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ fluent_messages! {
5151
plugin_impl => "../locales/en-US/plugin_impl.ftl",
5252
privacy => "../locales/en-US/privacy.ftl",
5353
query_system => "../locales/en-US/query_system.ftl",
54+
trait_selection => "../locales/en-US/trait_selection.ftl",
5455
save_analysis => "../locales/en-US/save_analysis.ftl",
5556
ty_utils => "../locales/en-US/ty_utils.ftl",
5657
typeck => "../locales/en-US/typeck.ftl",

Diff for: compiler/rustc_middle/src/ty/consts/kind.rs

+6
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ pub struct Unevaluated<'tcx, P = Option<Promoted>> {
2020
pub promoted: P,
2121
}
2222

23+
impl rustc_errors::IntoDiagnosticArg for Unevaluated<'_> {
24+
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
25+
format!("{:?}", self).into_diagnostic_arg()
26+
}
27+
}
28+
2329
impl<'tcx> Unevaluated<'tcx> {
2430
#[inline]
2531
pub fn shrink(self) -> Unevaluated<'tcx, ()> {

Diff for: compiler/rustc_middle/src/ty/sty.rs

+6
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,12 @@ impl<'tcx> PolyTraitRef<'tcx> {
849849
}
850850
}
851851

852+
impl rustc_errors::IntoDiagnosticArg for PolyTraitRef<'_> {
853+
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
854+
self.to_string().into_diagnostic_arg()
855+
}
856+
}
857+
852858
/// An existential reference to a trait, where `Self` is erased.
853859
/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
854860
/// ```ignore (illustrative)

Diff for: compiler/rustc_session/src/session.rs

+6
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ impl Mul<usize> for Limit {
110110
}
111111
}
112112

113+
impl rustc_errors::IntoDiagnosticArg for Limit {
114+
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
115+
self.to_string().into_diagnostic_arg()
116+
}
117+
}
118+
113119
#[derive(Clone, Copy, Debug, HashStable_Generic)]
114120
pub struct Limits {
115121
/// The maximum recursion limit for potentially infinitely recursive

Diff for: compiler/rustc_trait_selection/src/autoderef.rs

+5-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
use crate::errors::AutoDerefReachedRecursionLimit;
12
use crate::traits::query::evaluate_obligation::InferCtxtExt;
23
use crate::traits::{self, TraitEngine};
3-
use rustc_errors::struct_span_err;
44
use rustc_hir as hir;
55
use rustc_infer::infer::InferCtxt;
66
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt};
@@ -222,19 +222,10 @@ pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Spa
222222
Limit(0) => Limit(2),
223223
limit => limit * 2,
224224
};
225-
struct_span_err!(
226-
tcx.sess,
225+
tcx.sess.emit_err(AutoDerefReachedRecursionLimit {
227226
span,
228-
E0055,
229-
"reached the recursion limit while auto-dereferencing `{:?}`",
230-
ty
231-
)
232-
.span_label(span, "deref recursion limit reached")
233-
.help(&format!(
234-
"consider increasing the recursion limit by adding a \
235-
`#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
227+
ty,
236228
suggested_limit,
237-
tcx.crate_name(LOCAL_CRATE),
238-
))
239-
.emit();
229+
crate_name: tcx.crate_name(LOCAL_CRATE),
230+
});
240231
}

Diff for: compiler/rustc_trait_selection/src/errors.rs

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
use rustc_errors::{fluent, ErrorGuaranteed};
2+
use rustc_macros::SessionDiagnostic;
3+
use rustc_middle::ty::{PolyTraitRef, Ty, Unevaluated};
4+
use rustc_session::{parse::ParseSess, Limit, SessionDiagnostic};
5+
use rustc_span::{Span, Symbol};
6+
7+
#[derive(SessionDiagnostic)]
8+
#[diag(trait_selection::dump_vtable_entries)]
9+
pub struct DumpVTableEntries<'a> {
10+
#[primary_span]
11+
pub span: Span,
12+
pub trait_ref: PolyTraitRef<'a>,
13+
pub entries: String,
14+
}
15+
16+
#[derive(SessionDiagnostic)]
17+
#[diag(trait_selection::unable_to_construct_constant_value)]
18+
pub struct UnableToConstructConstantValue<'a> {
19+
#[primary_span]
20+
pub span: Span,
21+
pub unevaluated: Unevaluated<'a>,
22+
}
23+
24+
#[derive(SessionDiagnostic)]
25+
#[help]
26+
#[diag(trait_selection::auto_deref_reached_recursion_limit, code = "E0055")]
27+
pub struct AutoDerefReachedRecursionLimit<'a> {
28+
#[primary_span]
29+
#[label]
30+
pub span: Span,
31+
pub ty: Ty<'a>,
32+
pub suggested_limit: Limit,
33+
pub crate_name: Symbol,
34+
}
35+
36+
#[derive(SessionDiagnostic)]
37+
#[diag(trait_selection::empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
38+
pub struct EmptyOnClauseInOnUnimplemented {
39+
#[primary_span]
40+
#[label]
41+
pub span: Span,
42+
}
43+
44+
#[derive(SessionDiagnostic)]
45+
#[diag(trait_selection::invalid_on_clause_in_rustc_on_unimplemented, code = "E0232")]
46+
pub struct InvalidOnClauseInOnUnimplemented {
47+
#[primary_span]
48+
#[label]
49+
pub span: Span,
50+
}
51+
52+
#[derive(SessionDiagnostic)]
53+
#[diag(trait_selection::no_value_in_rustc_on_unimplemented, code = "E0232")]
54+
#[note]
55+
pub struct NoValueInOnUnimplemented {
56+
#[primary_span]
57+
#[label]
58+
pub span: Span,
59+
}
60+
61+
pub struct NegativePositiveConflict<'a> {
62+
pub impl_span: Span,
63+
pub trait_desc: &'a str,
64+
pub self_desc: &'a Option<String>,
65+
pub negative_impl_span: Result<Span, Symbol>,
66+
pub positive_impl_span: Result<Span, Symbol>,
67+
}
68+
69+
impl SessionDiagnostic<'_> for NegativePositiveConflict<'_> {
70+
fn into_diagnostic(
71+
self,
72+
sess: &ParseSess,
73+
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
74+
let mut diag = sess.struct_err(fluent::trait_selection::negative_positive_conflict);
75+
diag.set_arg("trait_desc", self.trait_desc);
76+
diag.set_arg(
77+
"self_desc",
78+
self.self_desc.clone().map_or_else(|| String::from("none"), |ty| ty),
79+
);
80+
diag.set_span(self.impl_span);
81+
diag.code(rustc_errors::error_code!(E0751));
82+
match self.negative_impl_span {
83+
Ok(span) => {
84+
diag.span_label(span, fluent::trait_selection::negative_implementation_here);
85+
}
86+
Err(cname) => {
87+
diag.note(fluent::trait_selection::negative_implementation_in_crate);
88+
diag.set_arg("negative_impl_cname", cname.to_string());
89+
}
90+
}
91+
match self.positive_impl_span {
92+
Ok(span) => {
93+
diag.span_label(span, fluent::trait_selection::positive_implementation_here);
94+
}
95+
Err(cname) => {
96+
diag.note(fluent::trait_selection::positive_implementation_in_crate);
97+
diag.set_arg("positive_impl_cname", cname.to_string());
98+
}
99+
}
100+
diag
101+
}
102+
}

Diff for: compiler/rustc_trait_selection/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,6 @@ extern crate rustc_middle;
3737
extern crate smallvec;
3838

3939
pub mod autoderef;
40+
pub mod errors;
4041
pub mod infer;
4142
pub mod traits;

Diff for: compiler/rustc_trait_selection/src/traits/auto_trait.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
44
use super::*;
55

6+
use crate::errors::UnableToConstructConstantValue;
67
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
78
use crate::infer::InferCtxt;
89
use crate::traits::project::ProjectAndUnifyResult;
@@ -830,8 +831,11 @@ impl<'tcx> AutoTraitFinder<'tcx> {
830831
Ok(None) => {
831832
let tcx = self.tcx;
832833
let def_id = unevaluated.def.did;
833-
let reported = tcx.sess.struct_span_err(tcx.def_span(def_id), &format!("unable to construct a constant value for the unevaluated constant {:?}", unevaluated)).emit();
834-
834+
let reported =
835+
tcx.sess.emit_err(UnableToConstructConstantValue {
836+
span: tcx.def_span(def_id),
837+
unevaluated,
838+
});
835839
Err(ErrorHandled::Reported(reported))
836840
}
837841
Err(err) => Err(err),

Diff for: compiler/rustc_trait_selection/src/traits/mod.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ mod structural_match;
2323
mod util;
2424
pub mod wf;
2525

26+
use crate::errors::DumpVTableEntries;
2627
use crate::infer::outlives::env::OutlivesEnvironment;
2728
use crate::infer::{InferCtxt, TyCtxtInferExt};
2829
use crate::traits::error_reporting::InferCtxtExt as _;
@@ -763,8 +764,11 @@ fn dump_vtable_entries<'tcx>(
763764
trait_ref: ty::PolyTraitRef<'tcx>,
764765
entries: &[VtblEntry<'tcx>],
765766
) {
766-
let msg = format!("vtable entries for `{}`: {:#?}", trait_ref, entries);
767-
tcx.sess.struct_span_err(sp, &msg).emit();
767+
tcx.sess.emit_err(DumpVTableEntries {
768+
span: sp,
769+
trait_ref,
770+
entries: format!("{:#?}", entries),
771+
});
768772
}
769773

770774
fn own_existential_vtable_entries<'tcx>(

Diff for: compiler/rustc_trait_selection/src/traits/on_unimplemented.rs

+7-40
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ use rustc_parse_format::{ParseMode, Parser, Piece, Position};
88
use rustc_span::symbol::{kw, sym, Symbol};
99
use rustc_span::{Span, DUMMY_SP};
1010

11+
use crate::errors::{
12+
EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
13+
};
14+
1115
#[derive(Clone, Debug)]
1216
pub struct OnUnimplementedFormatString(Symbol);
1317

@@ -35,21 +39,6 @@ pub struct OnUnimplementedNote {
3539
pub append_const_msg: Option<Option<Symbol>>,
3640
}
3741

38-
fn parse_error(
39-
tcx: TyCtxt<'_>,
40-
span: Span,
41-
message: &str,
42-
label: &str,
43-
note: Option<&str>,
44-
) -> ErrorGuaranteed {
45-
let mut diag = struct_span_err!(tcx.sess, span, E0232, "{}", message);
46-
diag.span_label(span, label);
47-
if let Some(note) = note {
48-
diag.note(note);
49-
}
50-
diag.emit()
51-
}
52-
5342
impl<'tcx> OnUnimplementedDirective {
5443
fn parse(
5544
tcx: TyCtxt<'tcx>,
@@ -70,25 +59,9 @@ impl<'tcx> OnUnimplementedDirective {
7059
} else {
7160
let cond = item_iter
7261
.next()
73-
.ok_or_else(|| {
74-
parse_error(
75-
tcx,
76-
span,
77-
"empty `on`-clause in `#[rustc_on_unimplemented]`",
78-
"empty on-clause here",
79-
None,
80-
)
81-
})?
62+
.ok_or_else(|| tcx.sess.emit_err(EmptyOnClauseInOnUnimplemented { span }))?
8263
.meta_item()
83-
.ok_or_else(|| {
84-
parse_error(
85-
tcx,
86-
span,
87-
"invalid `on`-clause in `#[rustc_on_unimplemented]`",
88-
"invalid on-clause here",
89-
None,
90-
)
91-
})?;
64+
.ok_or_else(|| tcx.sess.emit_err(InvalidOnClauseInOnUnimplemented { span }))?;
9265
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| {
9366
if let Some(value) = cfg.value && let Err(guar) = parse_value(value) {
9467
errored = Some(guar);
@@ -150,13 +123,7 @@ impl<'tcx> OnUnimplementedDirective {
150123
}
151124

152125
// nothing found
153-
parse_error(
154-
tcx,
155-
item.span(),
156-
"this attribute must have a valid value",
157-
"expected value here",
158-
Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#),
159-
);
126+
tcx.sess.emit_err(NoValueInOnUnimplemented { span: item.span() });
160127
}
161128

162129
if let Some(reported) = errored {

Diff for: compiler/rustc_trait_selection/src/traits/specialize/mod.rs

+8-29
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
pub mod specialization_graph;
1313
use specialization_graph::GraphExt;
1414

15+
use crate::errors::NegativePositiveConflict;
1516
use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
1617
use crate::traits::select::IntercrateAmbiguityCause;
1718
use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause};
@@ -327,35 +328,13 @@ fn report_negative_positive_conflict(
327328
positive_impl_def_id: DefId,
328329
sg: &mut specialization_graph::Graph,
329330
) {
330-
let impl_span = tcx.def_span(local_impl_def_id);
331-
332-
let mut err = struct_span_err!(
333-
tcx.sess,
334-
impl_span,
335-
E0751,
336-
"found both positive and negative implementation of trait `{}`{}:",
337-
overlap.trait_desc,
338-
overlap.self_desc.clone().map_or_else(String::new, |ty| format!(" for type `{}`", ty))
339-
);
340-
341-
match tcx.span_of_impl(negative_impl_def_id) {
342-
Ok(span) => {
343-
err.span_label(span, "negative implementation here");
344-
}
345-
Err(cname) => {
346-
err.note(&format!("negative implementation in crate `{}`", cname));
347-
}
348-
}
349-
350-
match tcx.span_of_impl(positive_impl_def_id) {
351-
Ok(span) => {
352-
err.span_label(span, "positive implementation here");
353-
}
354-
Err(cname) => {
355-
err.note(&format!("positive implementation in crate `{}`", cname));
356-
}
357-
}
358-
331+
let mut err = tcx.sess.create_err(NegativePositiveConflict {
332+
impl_span: tcx.def_span(local_impl_def_id),
333+
trait_desc: &overlap.trait_desc,
334+
self_desc: &overlap.self_desc,
335+
negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
336+
positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
337+
});
359338
sg.has_errored = Some(err.emit());
360339
}
361340

0 commit comments

Comments
 (0)