44//! [trait-resolution]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
55//! [trait-specialization]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
66
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 } ;
99use crate :: traits:: select:: IntercrateAmbiguityCause ;
1010use crate :: traits:: util:: impl_trait_ref_and_oblig;
1111use crate :: traits:: SkipLeakCheck ;
1212use crate :: traits:: {
1313 self , FulfillmentContext , Normalized , Obligation , ObligationCause , PredicateObligation ,
1414 PredicateObligations , SelectionContext ,
1515} ;
16+ //use rustc_data_structures::fx::FxHashMap;
1617use 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 ;
1721use rustc_middle:: traits:: specialization_graph:: OverlapMode ;
1822use rustc_middle:: ty:: fast_reject:: { self , SimplifyParams } ;
1923use rustc_middle:: ty:: fold:: TypeFoldable ;
@@ -150,7 +154,10 @@ fn overlap<'cx, 'tcx>(
150154 impl2_def_id : DefId ,
151155 overlap_mode : OverlapMode ,
152156) -> 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+ ) ;
154161
155162 selcx. infcx ( ) . probe_maybe_skip_leak_check ( skip_leak_check. is_yes ( ) , |snapshot| {
156163 overlap_within_probe (
@@ -191,9 +198,6 @@ fn overlap_within_probe<'cx, 'tcx>(
191198 let impl1_header = with_fresh_ty_vars ( selcx, param_env, impl1_def_id) ;
192199 let impl2_header = with_fresh_ty_vars ( selcx, param_env, impl2_def_id) ;
193200
194- debug ! ( "overlap: impl1_header={:?}" , impl1_header) ;
195- debug ! ( "overlap: impl2_header={:?}" , impl2_header) ;
196-
197201 let obligations = equate_impl_headers ( selcx, & impl1_header, & impl2_header) ?;
198202 debug ! ( "overlap: unification check succeeded" ) ;
199203
@@ -226,6 +230,7 @@ fn equate_impl_headers<'cx, 'tcx>(
226230 impl2_header : & ty:: ImplHeader < ' tcx > ,
227231) -> Option < PredicateObligations < ' tcx > > {
228232 // Do `a` and `b` unify? If not, no overlap.
233+ debug ! ( "equate_impl_headers(impl1_header={:?}, impl2_header={:?}" , impl1_header, impl2_header) ;
229234 selcx
230235 . infcx ( )
231236 . at ( & ObligationCause :: dummy ( ) , ty:: ParamEnv :: empty ( ) )
@@ -264,8 +269,11 @@ fn implicit_negative<'cx, 'tcx>(
264269 // If the obligation `&'?a str: Error` holds, it means that there's overlap. If that doesn't
265270 // hold we need to check if `&'?a str: !Error` holds, if doesn't hold there's overlap because
266271 // 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+ ) ;
267276 let infcx = selcx. infcx ( ) ;
268- let tcx = infcx. tcx ;
269277 let opt_failing_obligation = impl1_header
270278 . predicates
271279 . iter ( )
@@ -279,12 +287,7 @@ fn implicit_negative<'cx, 'tcx>(
279287 predicate : p,
280288 } )
281289 . 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) ) ;
288291
289292 if let Some ( failing_obligation) = opt_failing_obligation {
290293 debug ! ( "overlap: obligation unsatisfiable {:?}" , failing_obligation) ;
@@ -301,6 +304,7 @@ fn negative_impl<'cx, 'tcx>(
301304 impl1_def_id : DefId ,
302305 impl2_def_id : DefId ,
303306) -> bool {
307+ debug ! ( "negative_impl(impl1_def_id={:?}, impl2_def_id={:?})" , impl1_def_id, impl2_def_id) ;
304308 let tcx = selcx. infcx ( ) . tcx ;
305309
306310 // create a parameter environment corresponding to a (placeholder) instantiation of impl1
@@ -348,7 +352,7 @@ fn negative_impl<'cx, 'tcx>(
348352 let opt_failing_obligation = obligations
349353 . into_iter ( )
350354 . chain ( more_obligations)
351- . find ( |o| negative_impl_exists ( selcx, o) ) ;
355+ . find ( |o| negative_impl_exists ( selcx, impl1_env , impl1_def_id , o) ) ;
352356
353357 if let Some ( failing_obligation) = opt_failing_obligation {
354358 debug ! ( "overlap: obligation unsatisfiable {:?}" , failing_obligation) ;
@@ -359,24 +363,47 @@ fn negative_impl<'cx, 'tcx>(
359363 } )
360364}
361365
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-
369366fn negative_impl_exists < ' cx , ' tcx > (
370367 selcx : & SelectionContext < ' cx , ' tcx > ,
368+ param_env : ty:: ParamEnv < ' tcx > ,
369+ region_context : DefId ,
371370 o : & PredicateObligation < ' tcx > ,
372371) -> bool {
373- let infcx = selcx. infcx ( ) ;
372+ let infcx = & selcx. infcx ( ) . fork ( ) ;
374373 let tcx = infcx. tcx ;
375374 o. flip_polarity ( tcx)
376- . as_ref ( )
377375 . 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
380407 } )
381408 . unwrap_or ( false )
382409}
0 commit comments