@@ -13,8 +13,8 @@ use crate::traits::{
1313 self , FulfillmentContext , Normalized , Obligation , ObligationCause , PredicateObligation ,
1414 PredicateObligations , SelectionContext ,
1515} ;
16- use rustc_ast:: Attribute ;
1716use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
17+ use rustc_middle:: traits:: specialization_graph:: OverlapMode ;
1818use rustc_middle:: ty:: fast_reject:: { self , SimplifyParams , StripReferences } ;
1919use rustc_middle:: ty:: fold:: TypeFoldable ;
2020use rustc_middle:: ty:: subst:: Subst ;
@@ -62,6 +62,7 @@ pub fn overlapping_impls<F1, F2, R>(
6262 impl1_def_id : DefId ,
6363 impl2_def_id : DefId ,
6464 skip_leak_check : SkipLeakCheck ,
65+ overlap_mode : OverlapMode ,
6566 on_overlap : F1 ,
6667 no_overlap : F2 ,
6768) -> R
99100
100101 let overlaps = tcx. infer_ctxt ( ) . enter ( |infcx| {
101102 let selcx = & mut SelectionContext :: intercrate ( & infcx) ;
102- overlap ( selcx, skip_leak_check, impl1_def_id, impl2_def_id) . is_some ( )
103+ overlap ( selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode ) . is_some ( )
103104 } ) ;
104105
105106 if !overlaps {
@@ -112,7 +113,9 @@ where
112113 tcx. infer_ctxt ( ) . enter ( |infcx| {
113114 let selcx = & mut SelectionContext :: intercrate ( & infcx) ;
114115 selcx. enable_tracking_intercrate_ambiguity_causes ( ) ;
115- on_overlap ( overlap ( selcx, skip_leak_check, impl1_def_id, impl2_def_id) . unwrap ( ) )
116+ on_overlap (
117+ overlap ( selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode) . unwrap ( ) ,
118+ )
116119 } )
117120}
118121
@@ -138,68 +141,26 @@ fn with_fresh_ty_vars<'cx, 'tcx>(
138141 header
139142}
140143
141- /// What kind of overlap check are we doing -- this exists just for testing and feature-gating
142- /// purposes.
143- #[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
144- enum OverlapMode {
145- /// The 1.0 rules (either types fail to unify, or where clauses are not implemented for crate-local types)
146- Stable ,
147- /// Feature-gated test: Stable, *or* there is an explicit negative impl that rules out one of the where-clauses.
148- WithNegative ,
149- /// Just check for negative impls, not for "where clause not implemented": used for testing.
150- Strict ,
151- }
152-
153- impl OverlapMode {
154- fn use_negative_impl ( & self ) -> bool {
155- * self == OverlapMode :: Strict || * self == OverlapMode :: WithNegative
156- }
157-
158- fn use_implicit_negative ( & self ) -> bool {
159- * self == OverlapMode :: Stable || * self == OverlapMode :: WithNegative
160- }
161- }
162-
163- fn overlap_mode < ' tcx > ( tcx : TyCtxt < ' tcx > , impl1_def_id : DefId , impl2_def_id : DefId ) -> OverlapMode {
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- }
188- }
189- }
190-
191144/// Can both impl `a` and impl `b` be satisfied by a common type (including
192145/// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls.
193146fn overlap < ' cx , ' tcx > (
194147 selcx : & mut SelectionContext < ' cx , ' tcx > ,
195148 skip_leak_check : SkipLeakCheck ,
196149 impl1_def_id : DefId ,
197150 impl2_def_id : DefId ,
151+ overlap_mode : OverlapMode ,
198152) -> Option < OverlapResult < ' tcx > > {
199153 debug ! ( "overlap(impl1_def_id={:?}, impl2_def_id={:?})" , impl1_def_id, impl2_def_id) ;
200154
201155 selcx. infcx ( ) . probe_maybe_skip_leak_check ( skip_leak_check. is_yes ( ) , |snapshot| {
202- overlap_within_probe ( selcx, skip_leak_check, impl1_def_id, impl2_def_id, snapshot)
156+ overlap_within_probe (
157+ selcx,
158+ skip_leak_check,
159+ impl1_def_id,
160+ impl2_def_id,
161+ overlap_mode,
162+ snapshot,
163+ )
203164 } )
204165}
205166
@@ -208,12 +169,10 @@ fn overlap_within_probe<'cx, 'tcx>(
208169 skip_leak_check : SkipLeakCheck ,
209170 impl1_def_id : DefId ,
210171 impl2_def_id : DefId ,
172+ overlap_mode : OverlapMode ,
211173 snapshot : & CombinedSnapshot < ' _ , ' tcx > ,
212174) -> Option < OverlapResult < ' tcx > > {
213175 let infcx = selcx. infcx ( ) ;
214- let tcx = infcx. tcx ;
215-
216- let overlap_mode = overlap_mode ( tcx, impl1_def_id, impl2_def_id) ;
217176
218177 if overlap_mode. use_negative_impl ( ) {
219178 if negative_impl ( selcx, impl1_def_id, impl2_def_id)
0 commit comments