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 , StripReferences } ;
1923use rustc_middle:: ty:: fold:: TypeFoldable ;
@@ -270,7 +274,6 @@ fn implicit_negative<'cx, 'tcx>(
270274 impl1_header, impl2_header, obligations
271275 ) ;
272276 let infcx = selcx. infcx ( ) ;
273- let tcx = infcx. tcx ;
274277 let opt_failing_obligation = impl1_header
275278 . predicates
276279 . iter ( )
@@ -349,7 +352,7 @@ fn negative_impl<'cx, 'tcx>(
349352 let opt_failing_obligation = obligations
350353 . into_iter ( )
351354 . chain ( more_obligations)
352- . find ( |o| negative_impl_exists ( selcx, o) ) ;
355+ . find ( |o| negative_impl_exists ( selcx, impl1_env , impl1_def_id , o) ) ;
353356
354357 if let Some ( failing_obligation) = opt_failing_obligation {
355358 debug ! ( "overlap: obligation unsatisfiable {:?}" , failing_obligation) ;
@@ -372,15 +375,38 @@ fn loose_check<'cx, 'tcx>(
372375
373376fn negative_impl_exists < ' cx , ' tcx > (
374377 selcx : & SelectionContext < ' cx , ' tcx > ,
378+ param_env : ty:: ParamEnv < ' tcx > ,
379+ region_context : DefId ,
375380 o : & PredicateObligation < ' tcx > ,
376381) -> bool {
377- let infcx = selcx. infcx ( ) ;
382+ let infcx = selcx. infcx ( ) . clone ( ) ;
378383 let tcx = infcx. tcx ;
379384 o. flip_polarity ( tcx)
380- . as_ref ( )
381385 . map ( |o| {
382- // FIXME This isn't quite correct, regions should be included
383- selcx. infcx ( ) . predicate_must_hold_modulo_regions ( o)
386+ let mut fulfillment_cx = FulfillmentContext :: new ( ) ;
387+ fulfillment_cx. register_predicate_obligation ( infcx, o) ;
388+
389+ let errors = fulfillment_cx. select_all_or_error ( infcx) ;
390+ if !errors. is_empty ( ) {
391+ return false ;
392+ }
393+
394+ let mut outlives_env = OutlivesEnvironment :: new ( param_env) ;
395+ outlives_env. save_implied_bounds ( CRATE_HIR_ID ) ;
396+
397+ infcx. process_registered_region_obligations (
398+ outlives_env. region_bound_pairs_map ( ) ,
399+ Some ( tcx. lifetimes . re_root_empty ) ,
400+ param_env,
401+ ) ;
402+
403+ let errors =
404+ infcx. resolve_regions ( region_context, & outlives_env, RegionckMode :: default ( ) ) ;
405+ if !errors. is_empty ( ) {
406+ return false ;
407+ }
408+
409+ true
384410 } )
385411 . unwrap_or ( false )
386412}
0 commit comments