about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs43
1 files changed, 25 insertions, 18 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 80ed9023d96..ab1dc8fcbfe 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -13,6 +13,7 @@ use crate::traits::{
     self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation,
     PredicateObligations, SelectionContext,
 };
+use rustc_ast::Attribute;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences};
 use rustc_middle::ty::fold::TypeFoldable;
@@ -160,24 +161,30 @@ impl OverlapMode {
 }
 
 fn overlap_mode<'tcx>(tcx: TyCtxt<'tcx>, impl1_def_id: DefId, impl2_def_id: DefId) -> OverlapMode {
-    if tcx.has_attr(impl1_def_id, sym::rustc_strict_coherence)
-        != tcx.has_attr(impl2_def_id, sym::rustc_strict_coherence)
-    {
-        bug!("Use strict coherence on both impls",);
-    }
-
-    if tcx.has_attr(impl1_def_id, sym::rustc_with_negative_coherence)
-        != tcx.has_attr(impl2_def_id, sym::rustc_with_negative_coherence)
-    {
-        bug!("Use with negative coherence on both impls",);
-    }
-
-    if tcx.has_attr(impl1_def_id, sym::rustc_strict_coherence) {
-        OverlapMode::Strict
-    } else if tcx.has_attr(impl1_def_id, sym::rustc_with_negative_coherence) {
-        OverlapMode::WithNegative
-    } else {
-        OverlapMode::Stable
+    // Find the possible coherence mode override opt-in attributes for each `DefId`
+    let find_coherence_attr = |attr: &Attribute| {
+        let name = attr.name_or_empty();
+        match name {
+            sym::rustc_with_negative_coherence | sym::rustc_strict_coherence => Some(name),
+            _ => None,
+        }
+    };
+    let impl1_coherence_mode = tcx.get_attrs(impl1_def_id).iter().find_map(find_coherence_attr);
+    let impl2_coherence_mode = tcx.get_attrs(impl2_def_id).iter().find_map(find_coherence_attr);
+
+    // If there are any (that currently happens in tests), they need to match. Otherwise, the
+    // default 1.0 rules are used.
+    match (impl1_coherence_mode, impl2_coherence_mode) {
+        (None, None) => OverlapMode::Stable,
+        (Some(sym::rustc_with_negative_coherence), Some(sym::rustc_with_negative_coherence)) => {
+            OverlapMode::WithNegative
+        }
+        (Some(sym::rustc_strict_coherence), Some(sym::rustc_strict_coherence)) => {
+            OverlapMode::Strict
+        }
+        (Some(mode), _) | (_, Some(mode)) => {
+            bug!("Use the same coherence mode on both impls: {}", mode)
+        }
     }
 }