@@ -13,6 +13,7 @@ use crate::traits::{
13
13
self , FulfillmentContext , Normalized , Obligation , ObligationCause , PredicateObligation ,
14
14
PredicateObligations , SelectionContext ,
15
15
} ;
16
+ use rustc_ast:: Attribute ;
16
17
use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
17
18
use rustc_middle:: ty:: fast_reject:: { self , SimplifyParams , StripReferences } ;
18
19
use rustc_middle:: ty:: fold:: TypeFoldable ;
@@ -160,24 +161,30 @@ impl OverlapMode {
160
161
}
161
162
162
163
fn overlap_mode < ' tcx > ( tcx : TyCtxt < ' tcx > , impl1_def_id : DefId , impl2_def_id : DefId ) -> OverlapMode {
163
- if tcx. has_attr ( impl1_def_id, sym:: rustc_strict_coherence)
164
- != tcx. has_attr ( impl2_def_id, sym:: rustc_strict_coherence)
165
- {
166
- bug ! ( "Use strict coherence on both impls" , ) ;
167
- }
168
-
169
- if tcx. has_attr ( impl1_def_id, sym:: rustc_with_negative_coherence)
170
- != tcx. has_attr ( impl2_def_id, sym:: rustc_with_negative_coherence)
171
- {
172
- bug ! ( "Use with negative coherence on both impls" , ) ;
173
- }
174
-
175
- if tcx. has_attr ( impl1_def_id, sym:: rustc_strict_coherence) {
176
- OverlapMode :: Strict
177
- } else if tcx. has_attr ( impl1_def_id, sym:: rustc_with_negative_coherence) {
178
- OverlapMode :: WithNegative
179
- } else {
180
- OverlapMode :: Stable
164
+ // Find the possible coherence mode override opt-in attributes for each `DefId`
165
+ let find_coherence_attr = |attr : & Attribute | {
166
+ let name = attr. name_or_empty ( ) ;
167
+ match name {
168
+ sym:: rustc_with_negative_coherence | sym:: rustc_strict_coherence => Some ( name) ,
169
+ _ => None ,
170
+ }
171
+ } ;
172
+ let impl1_coherence_mode = tcx. get_attrs ( impl1_def_id) . iter ( ) . find_map ( find_coherence_attr) ;
173
+ let impl2_coherence_mode = tcx. get_attrs ( impl2_def_id) . iter ( ) . find_map ( find_coherence_attr) ;
174
+
175
+ // If there are any (that currently happens in tests), they need to match. Otherwise, the
176
+ // default 1.0 rules are used.
177
+ match ( impl1_coherence_mode, impl2_coherence_mode) {
178
+ ( None , None ) => OverlapMode :: Stable ,
179
+ ( Some ( sym:: rustc_with_negative_coherence) , Some ( sym:: rustc_with_negative_coherence) ) => {
180
+ OverlapMode :: WithNegative
181
+ }
182
+ ( Some ( sym:: rustc_strict_coherence) , Some ( sym:: rustc_strict_coherence) ) => {
183
+ OverlapMode :: Strict
184
+ }
185
+ ( Some ( mode) , _) | ( _, Some ( mode) ) => {
186
+ bug ! ( "Use the same coherence mode on both impls: {}" , mode)
187
+ }
181
188
}
182
189
}
183
190
0 commit comments