4
4
//! [trait-resolution]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
5
5
//! [trait-specialization]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
6
6
7
- use crate :: infer:: { CombinedSnapshot , InferOk , TyCtxtInferExt } ;
8
- use crate :: traits :: query :: evaluate_obligation :: InferCtxtExt ;
7
+ use crate :: infer:: outlives :: env :: OutlivesEnvironment ;
8
+ use crate :: infer :: { CombinedSnapshot , InferOk , RegionckMode } ;
9
9
use crate :: traits:: select:: IntercrateAmbiguityCause ;
10
10
use crate :: traits:: util:: impl_trait_ref_and_oblig;
11
11
use crate :: traits:: SkipLeakCheck ;
12
12
use crate :: traits:: {
13
13
self , FulfillmentContext , Normalized , Obligation , ObligationCause , PredicateObligation ,
14
14
PredicateObligations , SelectionContext ,
15
15
} ;
16
+ //use rustc_data_structures::fx::FxHashMap;
16
17
use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
18
+ use rustc_hir:: CRATE_HIR_ID ;
19
+ use rustc_infer:: infer:: TyCtxtInferExt ;
20
+ use rustc_infer:: traits:: TraitEngine ;
17
21
use rustc_middle:: traits:: specialization_graph:: OverlapMode ;
18
22
use rustc_middle:: ty:: fast_reject:: { self , SimplifyParams } ;
19
23
use rustc_middle:: ty:: fold:: TypeFoldable ;
@@ -150,7 +154,10 @@ fn overlap<'cx, 'tcx>(
150
154
impl2_def_id : DefId ,
151
155
overlap_mode : OverlapMode ,
152
156
) -> Option < OverlapResult < ' tcx > > {
153
- debug ! ( "overlap(impl1_def_id={:?}, impl2_def_id={:?})" , impl1_def_id, impl2_def_id) ;
157
+ debug ! (
158
+ "overlap(impl1_def_id={:?}, impl2_def_id={:?}, overlap_mode={:?})" ,
159
+ impl1_def_id, impl2_def_id, overlap_mode
160
+ ) ;
154
161
155
162
selcx. infcx ( ) . probe_maybe_skip_leak_check ( skip_leak_check. is_yes ( ) , |snapshot| {
156
163
overlap_within_probe (
@@ -191,9 +198,6 @@ fn overlap_within_probe<'cx, 'tcx>(
191
198
let impl1_header = with_fresh_ty_vars ( selcx, param_env, impl1_def_id) ;
192
199
let impl2_header = with_fresh_ty_vars ( selcx, param_env, impl2_def_id) ;
193
200
194
- debug ! ( "overlap: impl1_header={:?}" , impl1_header) ;
195
- debug ! ( "overlap: impl2_header={:?}" , impl2_header) ;
196
-
197
201
let obligations = equate_impl_headers ( selcx, & impl1_header, & impl2_header) ?;
198
202
debug ! ( "overlap: unification check succeeded" ) ;
199
203
@@ -226,6 +230,7 @@ fn equate_impl_headers<'cx, 'tcx>(
226
230
impl2_header : & ty:: ImplHeader < ' tcx > ,
227
231
) -> Option < PredicateObligations < ' tcx > > {
228
232
// Do `a` and `b` unify? If not, no overlap.
233
+ debug ! ( "equate_impl_headers(impl1_header={:?}, impl2_header={:?}" , impl1_header, impl2_header) ;
229
234
selcx
230
235
. infcx ( )
231
236
. at ( & ObligationCause :: dummy ( ) , ty:: ParamEnv :: empty ( ) )
@@ -264,8 +269,11 @@ fn implicit_negative<'cx, 'tcx>(
264
269
// If the obligation `&'?a str: Error` holds, it means that there's overlap. If that doesn't
265
270
// hold we need to check if `&'?a str: !Error` holds, if doesn't hold there's overlap because
266
271
// at some point an impl for `&'?a str: Error` could be added.
272
+ debug ! (
273
+ "implicit_negative(impl1_header={:?}, impl2_header={:?}, obligations={:?})" ,
274
+ impl1_header, impl2_header, obligations
275
+ ) ;
267
276
let infcx = selcx. infcx ( ) ;
268
- let tcx = infcx. tcx ;
269
277
let opt_failing_obligation = impl1_header
270
278
. predicates
271
279
. iter ( )
@@ -279,12 +287,7 @@ fn implicit_negative<'cx, 'tcx>(
279
287
predicate : p,
280
288
} )
281
289
. chain ( obligations)
282
- . find ( |o| {
283
- loose_check ( selcx, o) || tcx. features ( ) . negative_impls && negative_impl_exists ( selcx, o)
284
- } ) ;
285
- // FIXME: the call to `selcx.predicate_may_hold_fatal` above should be ported
286
- // to the canonical trait query form, `infcx.predicate_may_hold`, once
287
- // the new system supports intercrate mode (which coherence needs).
290
+ . find ( |o| !selcx. predicate_may_hold_fatal ( o) ) ;
288
291
289
292
if let Some ( failing_obligation) = opt_failing_obligation {
290
293
debug ! ( "overlap: obligation unsatisfiable {:?}" , failing_obligation) ;
@@ -301,6 +304,7 @@ fn negative_impl<'cx, 'tcx>(
301
304
impl1_def_id : DefId ,
302
305
impl2_def_id : DefId ,
303
306
) -> bool {
307
+ debug ! ( "negative_impl(impl1_def_id={:?}, impl2_def_id={:?})" , impl1_def_id, impl2_def_id) ;
304
308
let tcx = selcx. infcx ( ) . tcx ;
305
309
306
310
// create a parameter environment corresponding to a (placeholder) instantiation of impl1
@@ -348,7 +352,7 @@ fn negative_impl<'cx, 'tcx>(
348
352
let opt_failing_obligation = obligations
349
353
. into_iter ( )
350
354
. chain ( more_obligations)
351
- . find ( |o| negative_impl_exists ( selcx, o) ) ;
355
+ . find ( |o| negative_impl_exists ( selcx, impl1_env , impl1_def_id , o) ) ;
352
356
353
357
if let Some ( failing_obligation) = opt_failing_obligation {
354
358
debug ! ( "overlap: obligation unsatisfiable {:?}" , failing_obligation) ;
@@ -359,24 +363,47 @@ fn negative_impl<'cx, 'tcx>(
359
363
} )
360
364
}
361
365
362
- fn loose_check < ' cx , ' tcx > (
363
- selcx : & mut SelectionContext < ' cx , ' tcx > ,
364
- o : & PredicateObligation < ' tcx > ,
365
- ) -> bool {
366
- !selcx. predicate_may_hold_fatal ( o)
367
- }
368
-
369
366
fn negative_impl_exists < ' cx , ' tcx > (
370
367
selcx : & SelectionContext < ' cx , ' tcx > ,
368
+ param_env : ty:: ParamEnv < ' tcx > ,
369
+ region_context : DefId ,
371
370
o : & PredicateObligation < ' tcx > ,
372
371
) -> bool {
373
- let infcx = selcx. infcx ( ) ;
372
+ let infcx = & selcx. infcx ( ) . fork ( ) ;
374
373
let tcx = infcx. tcx ;
375
374
o. flip_polarity ( tcx)
376
- . as_ref ( )
377
375
. map ( |o| {
378
- // FIXME This isn't quite correct, regions should be included
379
- selcx. infcx ( ) . predicate_must_hold_modulo_regions ( o)
376
+ let mut fulfillment_cx = FulfillmentContext :: new ( ) ;
377
+ fulfillment_cx. register_predicate_obligation ( infcx, o) ;
378
+
379
+ let errors = fulfillment_cx. select_all_or_error ( infcx) ;
380
+ if !errors. is_empty ( ) {
381
+ return false ;
382
+ }
383
+
384
+ let mut outlives_env = OutlivesEnvironment :: new ( param_env) ;
385
+ // FIXME -- add "assumed to be well formed" types into the `outlives_env`
386
+
387
+ // "Save" the accumulated implied bounds into the outlives environment
388
+ // (due to the FIXME above, there aren't any, but this step is still needed).
389
+ // The "body id" is given as `CRATE_HIR_ID`, which is the same body-id used
390
+ // by the "dummy" causes elsewhere (body-id is only relevant when checking
391
+ // function bodies with closures).
392
+ outlives_env. save_implied_bounds ( CRATE_HIR_ID ) ;
393
+
394
+ infcx. process_registered_region_obligations (
395
+ outlives_env. region_bound_pairs_map ( ) ,
396
+ Some ( tcx. lifetimes . re_root_empty ) ,
397
+ param_env,
398
+ ) ;
399
+
400
+ let errors =
401
+ infcx. resolve_regions ( region_context, & outlives_env, RegionckMode :: default ( ) ) ;
402
+ if !errors. is_empty ( ) {
403
+ return false ;
404
+ }
405
+
406
+ true
380
407
} )
381
408
. unwrap_or ( false )
382
409
}
0 commit comments