Skip to content

Commit

Permalink
Add NegativePositiveConflict diagnostic to trait_selection
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielBusta committed Aug 24, 2022
1 parent 7bb855a commit 2fbc967
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ trait_selection_invalid_on_clause_in_rustc_on_unimplemented = invalid `on`-claus
trait_selection_no_value_in_rustc_on_unimplemented = this attribute must have a valid value
.label = expected value here
.note = eg `#[rustc_on_unimplemented(message="foo")]`
trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc}:
.negative_implementation_here = negative implementation here
.negative_implementation_in_crate = negative implementation in crate `{$negative_impl_cname}`
.positive_implementation_here = positive implementation here
.positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}`
47 changes: 46 additions & 1 deletion compiler/rustc_trait_selection/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use rustc_errors::{fluent, ErrorGuaranteed};
use rustc_macros::SessionDiagnostic;
use rustc_span::Span;
use rustc_session::{parse::ParseSess, SessionDiagnostic};
use rustc_span::{Span, Symbol};

#[derive(SessionDiagnostic)]
#[diag(trait_selection::dump_vtable_entries)]
Expand Down Expand Up @@ -54,3 +56,46 @@ pub struct NoValueInOnUnimplemented {
#[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::new, |ty| format!(" for type `{}`", 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
}
}
37 changes: 8 additions & 29 deletions compiler/rustc_trait_selection/src/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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());
}

Expand Down

0 comments on commit 2fbc967

Please sign in to comment.