@@ -13,8 +13,8 @@ use crate::traits::{
13
13
self , FulfillmentContext , Normalized , Obligation , ObligationCause , PredicateObligation ,
14
14
PredicateObligations , SelectionContext ,
15
15
} ;
16
- use rustc_ast:: Attribute ;
17
16
use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
17
+ use rustc_middle:: traits:: specialization_graph:: OverlapMode ;
18
18
use rustc_middle:: ty:: fast_reject:: { self , SimplifyParams , StripReferences } ;
19
19
use rustc_middle:: ty:: fold:: TypeFoldable ;
20
20
use rustc_middle:: ty:: subst:: Subst ;
@@ -62,6 +62,7 @@ pub fn overlapping_impls<F1, F2, R>(
62
62
impl1_def_id : DefId ,
63
63
impl2_def_id : DefId ,
64
64
skip_leak_check : SkipLeakCheck ,
65
+ overlap_mode : OverlapMode ,
65
66
on_overlap : F1 ,
66
67
no_overlap : F2 ,
67
68
) -> R
99
100
100
101
let overlaps = tcx. infer_ctxt ( ) . enter ( |infcx| {
101
102
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 ( )
103
104
} ) ;
104
105
105
106
if !overlaps {
@@ -112,7 +113,9 @@ where
112
113
tcx. infer_ctxt ( ) . enter ( |infcx| {
113
114
let selcx = & mut SelectionContext :: intercrate ( & infcx) ;
114
115
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
+ )
116
119
} )
117
120
}
118
121
@@ -138,68 +141,26 @@ fn with_fresh_ty_vars<'cx, 'tcx>(
138
141
header
139
142
}
140
143
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
-
191
144
/// Can both impl `a` and impl `b` be satisfied by a common type (including
192
145
/// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls.
193
146
fn overlap < ' cx , ' tcx > (
194
147
selcx : & mut SelectionContext < ' cx , ' tcx > ,
195
148
skip_leak_check : SkipLeakCheck ,
196
149
impl1_def_id : DefId ,
197
150
impl2_def_id : DefId ,
151
+ overlap_mode : OverlapMode ,
198
152
) -> Option < OverlapResult < ' tcx > > {
199
153
debug ! ( "overlap(impl1_def_id={:?}, impl2_def_id={:?})" , impl1_def_id, impl2_def_id) ;
200
154
201
155
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
+ )
203
164
} )
204
165
}
205
166
@@ -208,12 +169,10 @@ fn overlap_within_probe<'cx, 'tcx>(
208
169
skip_leak_check : SkipLeakCheck ,
209
170
impl1_def_id : DefId ,
210
171
impl2_def_id : DefId ,
172
+ overlap_mode : OverlapMode ,
211
173
snapshot : & CombinedSnapshot < ' _ , ' tcx > ,
212
174
) -> Option < OverlapResult < ' tcx > > {
213
175
let infcx = selcx. infcx ( ) ;
214
- let tcx = infcx. tcx ;
215
-
216
- let overlap_mode = overlap_mode ( tcx, impl1_def_id, impl2_def_id) ;
217
176
218
177
if overlap_mode. use_negative_impl ( ) {
219
178
if negative_impl ( selcx, impl1_def_id, impl2_def_id)
0 commit comments