diff --git a/compiler/rustc_error_messages/locales/en-US/middle.ftl b/compiler/rustc_error_messages/locales/en-US/middle.ftl index b9e4499d47f..81d8e8a473b 100644 --- a/compiler/rustc_error_messages/locales/en-US/middle.ftl +++ b/compiler/rustc_error_messages/locales/en-US/middle.ftl @@ -27,3 +27,7 @@ middle_values_too_big = middle_cannot_be_normalized = unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized + +middle_strict_coherence_needs_negative_coherence = + to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled + .label = due to this attribute diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index a7a7ac0599d..43903e6739f 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -55,3 +55,12 @@ pub struct ConstEvalNonIntError { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(middle_strict_coherence_needs_negative_coherence)] +pub(crate) struct StrictCoherenceNeedsNegativeCoherence { + #[primary_span] + pub span: Span, + #[label] + pub attr_span: Option, +} diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index 0a2819feecf..f1c21588261 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -1,3 +1,4 @@ +use crate::error::StrictCoherenceNeedsNegativeCoherence; use crate::ty::fast_reject::SimplifiedType; use crate::ty::visit::TypeVisitable; use crate::ty::{self, TyCtxt}; @@ -65,9 +66,21 @@ pub fn get<'tcx>(tcx: TyCtxt<'tcx>, trait_id: DefId) -> OverlapMode { if with_negative_coherence { if strict_coherence { OverlapMode::Strict } else { OverlapMode::WithNegative } - } else if strict_coherence { - bug!("To use strict_coherence you need to set with_negative_coherence feature flag"); } else { + if strict_coherence { + let attr_span = trait_id + .as_local() + .into_iter() + .flat_map(|local_def_id| { + tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(local_def_id)) + }) + .find(|attr| attr.has_name(sym::rustc_strict_coherence)) + .map(|attr| attr.span); + tcx.sess.emit_err(StrictCoherenceNeedsNegativeCoherence { + span: tcx.def_span(trait_id), + attr_span, + }); + } OverlapMode::Stable } } diff --git a/src/test/ui/coherence/strict-coherence-needs-negative-coherence.rs b/src/test/ui/coherence/strict-coherence-needs-negative-coherence.rs new file mode 100644 index 00000000000..221683dd56f --- /dev/null +++ b/src/test/ui/coherence/strict-coherence-needs-negative-coherence.rs @@ -0,0 +1,7 @@ +#![feature(rustc_attrs)] + +#[rustc_strict_coherence] +trait Foo {} +//~^ ERROR to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled + +fn main() {} diff --git a/src/test/ui/coherence/strict-coherence-needs-negative-coherence.stderr b/src/test/ui/coherence/strict-coherence-needs-negative-coherence.stderr new file mode 100644 index 00000000000..b5472928778 --- /dev/null +++ b/src/test/ui/coherence/strict-coherence-needs-negative-coherence.stderr @@ -0,0 +1,10 @@ +error: to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled + --> $DIR/strict-coherence-needs-negative-coherence.rs:4:1 + | +LL | #[rustc_strict_coherence] + | ------------------------- due to this attribute +LL | trait Foo {} + | ^^^^^^^^^ + +error: aborting due to previous error +