about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRémy Rakic <remy.rakic+github@gmail.com>2022-01-26 18:32:02 +0100
committerRémy Rakic <remy.rakic+github@gmail.com>2022-01-26 18:32:02 +0100
commit644c22d3ad742abfd480ce2fbc6d5b6429f0c2a3 (patch)
tree5fd1a9d0d7dab6d5c48f62079583047de0b7312b
parentd502eda250d0090f4990cc6880c88b95a92b4818 (diff)
downloadrust-644c22d3ad742abfd480ce2fbc6d5b6429f0c2a3.tar.gz
rust-644c22d3ad742abfd480ce2fbc6d5b6429f0c2a3.zip
Only traverse attrs once while checking for coherence override
-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)
+        }
     }
 }