@@ -13,6 +13,7 @@ use crate::traits::{
1313    self ,  FulfillmentContext ,  Normalized ,  Obligation ,  ObligationCause ,  PredicateObligation , 
1414    PredicateObligations ,  SelectionContext , 
1515} ; 
16+ use  rustc_ast:: Attribute ; 
1617use  rustc_hir:: def_id:: { DefId ,  LOCAL_CRATE } ; 
1718use  rustc_middle:: ty:: fast_reject:: { self ,  SimplifyParams ,  StripReferences } ; 
1819use  rustc_middle:: ty:: fold:: TypeFoldable ; 
@@ -160,24 +161,30 @@ impl OverlapMode {
160161} 
161162
162163fn  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+         } 
181188    } 
182189} 
183190
0 commit comments