1
Fork 0

Porting 'compiler/rustc_trait_selection' to translatable diagnostics - Part 1

This commit is contained in:
Gabriel Bustamante 2022-08-26 13:08:58 -05:00
parent fb888117da
commit 8e82200277
12 changed files with 180 additions and 87 deletions

View file

@ -1,6 +1,6 @@
use crate::errors::AutoDerefReachedRecursionLimit;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::{self, TraitEngine};
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_infer::infer::InferCtxt;
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
Limit(0) => Limit(2),
limit => limit * 2,
};
struct_span_err!(
tcx.sess,
tcx.sess.emit_err(AutoDerefReachedRecursionLimit {
span,
E0055,
"reached the recursion limit while auto-dereferencing `{:?}`",
ty
)
.span_label(span, "deref recursion limit reached")
.help(&format!(
"consider increasing the recursion limit by adding a \
`#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
ty,
suggested_limit,
tcx.crate_name(LOCAL_CRATE),
))
.emit();
crate_name: tcx.crate_name(LOCAL_CRATE),
});
}

View file

@ -0,0 +1,102 @@
use rustc_errors::{fluent, ErrorGuaranteed};
use rustc_macros::SessionDiagnostic;
use rustc_middle::ty::{PolyTraitRef, Ty, Unevaluated};
use rustc_session::{parse::ParseSess, Limit, SessionDiagnostic};
use rustc_span::{Span, Symbol};
#[derive(SessionDiagnostic)]
#[diag(trait_selection::dump_vtable_entries)]
pub struct DumpVTableEntries<'a> {
#[primary_span]
pub span: Span,
pub trait_ref: PolyTraitRef<'a>,
pub entries: String,
}
#[derive(SessionDiagnostic)]
#[diag(trait_selection::unable_to_construct_constant_value)]
pub struct UnableToConstructConstantValue<'a> {
#[primary_span]
pub span: Span,
pub unevaluated: Unevaluated<'a>,
}
#[derive(SessionDiagnostic)]
#[help]
#[diag(trait_selection::auto_deref_reached_recursion_limit, code = "E0055")]
pub struct AutoDerefReachedRecursionLimit<'a> {
#[primary_span]
#[label]
pub span: Span,
pub ty: Ty<'a>,
pub suggested_limit: Limit,
pub crate_name: Symbol,
}
#[derive(SessionDiagnostic)]
#[diag(trait_selection::empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
pub struct EmptyOnClauseInOnUnimplemented {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(trait_selection::invalid_on_clause_in_rustc_on_unimplemented, code = "E0232")]
pub struct InvalidOnClauseInOnUnimplemented {
#[primary_span]
#[label]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(trait_selection::no_value_in_rustc_on_unimplemented, code = "E0232")]
#[note]
pub struct NoValueInOnUnimplemented {
#[primary_span]
#[label]
pub span: Span,
}
pub struct NegativePositiveConflict<'a> {
pub impl_span: Span,
pub trait_desc: &'a str,
pub self_desc: &'a Option<String>,
pub negative_impl_span: Result<Span, Symbol>,
pub positive_impl_span: Result<Span, Symbol>,
}
impl SessionDiagnostic<'_> for NegativePositiveConflict<'_> {
fn into_diagnostic(
self,
sess: &ParseSess,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
let mut diag = sess.struct_err(fluent::trait_selection::negative_positive_conflict);
diag.set_arg("trait_desc", self.trait_desc);
diag.set_arg(
"self_desc",
self.self_desc.clone().map_or_else(|| String::from("none"), |ty| ty),
);
diag.set_span(self.impl_span);
diag.code(rustc_errors::error_code!(E0751));
match self.negative_impl_span {
Ok(span) => {
diag.span_label(span, fluent::trait_selection::negative_implementation_here);
}
Err(cname) => {
diag.note(fluent::trait_selection::negative_implementation_in_crate);
diag.set_arg("negative_impl_cname", cname.to_string());
}
}
match self.positive_impl_span {
Ok(span) => {
diag.span_label(span, fluent::trait_selection::positive_implementation_here);
}
Err(cname) => {
diag.note(fluent::trait_selection::positive_implementation_in_crate);
diag.set_arg("positive_impl_cname", cname.to_string());
}
}
diag
}
}

View file

@ -37,5 +37,6 @@ extern crate rustc_middle;
extern crate smallvec;
pub mod autoderef;
pub mod errors;
pub mod infer;
pub mod traits;

View file

@ -3,6 +3,7 @@
use super::*;
use crate::errors::UnableToConstructConstantValue;
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::InferCtxt;
use crate::traits::project::ProjectAndUnifyResult;
@ -830,8 +831,11 @@ impl<'tcx> AutoTraitFinder<'tcx> {
Ok(None) => {
let tcx = self.tcx;
let def_id = unevaluated.def.did;
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();
let reported =
tcx.sess.emit_err(UnableToConstructConstantValue {
span: tcx.def_span(def_id),
unevaluated,
});
Err(ErrorHandled::Reported(reported))
}
Err(err) => Err(err),

View file

@ -23,6 +23,7 @@ mod structural_match;
mod util;
pub mod wf;
use crate::errors::DumpVTableEntries;
use crate::infer::outlives::env::OutlivesEnvironment;
use crate::infer::{InferCtxt, TyCtxtInferExt};
use crate::traits::error_reporting::InferCtxtExt as _;
@ -763,8 +764,11 @@ fn dump_vtable_entries<'tcx>(
trait_ref: ty::PolyTraitRef<'tcx>,
entries: &[VtblEntry<'tcx>],
) {
let msg = format!("vtable entries for `{}`: {:#?}", trait_ref, entries);
tcx.sess.struct_span_err(sp, &msg).emit();
tcx.sess.emit_err(DumpVTableEntries {
span: sp,
trait_ref,
entries: format!("{:#?}", entries),
});
}
fn own_existential_vtable_entries<'tcx>(

View file

@ -8,6 +8,10 @@ use rustc_parse_format::{ParseMode, Parser, Piece, Position};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use crate::errors::{
EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
};
#[derive(Clone, Debug)]
pub struct OnUnimplementedFormatString(Symbol);
@ -35,21 +39,6 @@ pub struct OnUnimplementedNote {
pub append_const_msg: Option<Option<Symbol>>,
}
fn parse_error(
tcx: TyCtxt<'_>,
span: Span,
message: &str,
label: &str,
note: Option<&str>,
) -> ErrorGuaranteed {
let mut diag = struct_span_err!(tcx.sess, span, E0232, "{}", message);
diag.span_label(span, label);
if let Some(note) = note {
diag.note(note);
}
diag.emit()
}
impl<'tcx> OnUnimplementedDirective {
fn parse(
tcx: TyCtxt<'tcx>,
@ -70,25 +59,9 @@ impl<'tcx> OnUnimplementedDirective {
} else {
let cond = item_iter
.next()
.ok_or_else(|| {
parse_error(
tcx,
span,
"empty `on`-clause in `#[rustc_on_unimplemented]`",
"empty on-clause here",
None,
)
})?
.ok_or_else(|| tcx.sess.emit_err(EmptyOnClauseInOnUnimplemented { span }))?
.meta_item()
.ok_or_else(|| {
parse_error(
tcx,
span,
"invalid `on`-clause in `#[rustc_on_unimplemented]`",
"invalid on-clause here",
None,
)
})?;
.ok_or_else(|| tcx.sess.emit_err(InvalidOnClauseInOnUnimplemented { span }))?;
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| {
if let Some(value) = cfg.value && let Err(guar) = parse_value(value) {
errored = Some(guar);
@ -150,13 +123,7 @@ impl<'tcx> OnUnimplementedDirective {
}
// nothing found
parse_error(
tcx,
item.span(),
"this attribute must have a valid value",
"expected value here",
Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#),
);
tcx.sess.emit_err(NoValueInOnUnimplemented { span: item.span() });
}
if let Some(reported) = errored {

View file

@ -12,6 +12,7 @@
pub mod specialization_graph;
use specialization_graph::GraphExt;
use crate::errors::NegativePositiveConflict;
use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use crate::traits::select::IntercrateAmbiguityCause;
use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause};
@ -327,35 +328,13 @@ fn report_negative_positive_conflict(
positive_impl_def_id: DefId,
sg: &mut specialization_graph::Graph,
) {
let impl_span = tcx.def_span(local_impl_def_id);
let mut err = struct_span_err!(
tcx.sess,
impl_span,
E0751,
"found both positive and negative implementation of trait `{}`{}:",
overlap.trait_desc,
overlap.self_desc.clone().map_or_else(String::new, |ty| format!(" for type `{}`", ty))
);
match tcx.span_of_impl(negative_impl_def_id) {
Ok(span) => {
err.span_label(span, "negative implementation here");
}
Err(cname) => {
err.note(&format!("negative implementation in crate `{}`", cname));
}
}
match tcx.span_of_impl(positive_impl_def_id) {
Ok(span) => {
err.span_label(span, "positive implementation here");
}
Err(cname) => {
err.note(&format!("positive implementation in crate `{}`", cname));
}
}
let mut err = tcx.sess.create_err(NegativePositiveConflict {
impl_span: tcx.def_span(local_impl_def_id),
trait_desc: &overlap.trait_desc,
self_desc: &overlap.self_desc,
negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
});
sg.has_errored = Some(err.emit());
}