@@ -452,22 +452,23 @@ fn prove_negated_obligation<'tcx>(
452452/// This both checks whether any downstream or sibling crates could
453453/// implement it and whether an upstream crate can add this impl
454454/// without breaking backwards compatibility.
455- #[ instrument( level = "debug" , skip( tcx) , ret) ]
456- pub fn trait_ref_is_knowable < ' tcx > (
455+ #[ instrument( level = "debug" , skip( tcx, lazily_normalize_ty ) , ret) ]
456+ pub fn trait_ref_is_knowable < ' tcx , E : Debug > (
457457 tcx : TyCtxt < ' tcx > ,
458458 trait_ref : ty:: TraitRef < ' tcx > ,
459- ) -> Result < ( ) , Conflict > {
459+ mut lazily_normalize_ty : impl FnMut ( Ty < ' tcx > ) -> Result < Ty < ' tcx > , E > ,
460+ ) -> Result < Result < ( ) , Conflict > , E > {
460461 if Some ( trait_ref. def_id ) == tcx. lang_items ( ) . fn_ptr_trait ( ) {
461462 // The only types implementing `FnPtr` are function pointers,
462463 // so if there's no impl of `FnPtr` in the current crate,
463464 // then such an impl will never be added in the future.
464- return Ok ( ( ) ) ;
465+ return Ok ( Ok ( ( ) ) ) ;
465466 }
466467
467- if orphan_check_trait_ref ( trait_ref, InCrate :: Remote ) . is_ok ( ) {
468+ if orphan_check_trait_ref ( trait_ref, InCrate :: Remote , & mut lazily_normalize_ty ) ? . is_ok ( ) {
468469 // A downstream or cousin crate is allowed to implement some
469470 // substitution of this trait-ref.
470- return Err ( Conflict :: Downstream ) ;
471+ return Ok ( Err ( Conflict :: Downstream ) ) ;
471472 }
472473
473474 if trait_ref_is_local_or_fundamental ( tcx, trait_ref) {
@@ -476,7 +477,7 @@ pub fn trait_ref_is_knowable<'tcx>(
476477 // allowed to implement a substitution of this trait ref, which
477478 // means impls could only come from dependencies of this crate,
478479 // which we already know about.
479- return Ok ( ( ) ) ;
480+ return Ok ( Ok ( ( ) ) ) ;
480481 }
481482
482483 // This is a remote non-fundamental trait, so if another crate
@@ -487,10 +488,10 @@ pub fn trait_ref_is_knowable<'tcx>(
487488 // and if we are an intermediate owner, then we don't care
488489 // about future-compatibility, which means that we're OK if
489490 // we are an owner.
490- if orphan_check_trait_ref ( trait_ref, InCrate :: Local ) . is_ok ( ) {
491- Ok ( ( ) )
491+ if orphan_check_trait_ref ( trait_ref, InCrate :: Local , & mut lazily_normalize_ty ) ? . is_ok ( ) {
492+ Ok ( Ok ( ( ) ) )
492493 } else {
493- Err ( Conflict :: Upstream )
494+ Ok ( Err ( Conflict :: Upstream ) )
494495 }
495496}
496497
@@ -526,7 +527,7 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
526527 return Ok ( ( ) ) ;
527528 }
528529
529- orphan_check_trait_ref ( trait_ref, InCrate :: Local )
530+ orphan_check_trait_ref :: < ! > ( trait_ref, InCrate :: Local , |ty| Ok ( ty ) ) . unwrap ( )
530531}
531532
532533/// Checks whether a trait-ref is potentially implementable by a crate.
@@ -615,21 +616,23 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
615616///
616617/// Note that this function is never called for types that have both type
617618/// parameters and inference variables.
618- #[ instrument( level = "trace" , ret) ]
619- fn orphan_check_trait_ref < ' tcx > (
619+ #[ instrument( level = "trace" , skip ( lazily_normalize_ty ) , ret) ]
620+ fn orphan_check_trait_ref < ' tcx , E : Debug > (
620621 trait_ref : ty:: TraitRef < ' tcx > ,
621622 in_crate : InCrate ,
622- ) -> Result < ( ) , OrphanCheckErr < ' tcx > > {
623+ lazily_normalize_ty : impl FnMut ( Ty < ' tcx > ) -> Result < Ty < ' tcx > , E > ,
624+ ) -> Result < Result < ( ) , OrphanCheckErr < ' tcx > > , E > {
623625 if trait_ref. has_infer ( ) && trait_ref. has_param ( ) {
624626 bug ! (
625627 "can't orphan check a trait ref with both params and inference variables {:?}" ,
626628 trait_ref
627629 ) ;
628630 }
629631
630- let mut checker = OrphanChecker :: new ( in_crate) ;
631- match trait_ref. visit_with ( & mut checker) {
632+ let mut checker = OrphanChecker :: new ( in_crate, lazily_normalize_ty ) ;
633+ Ok ( match trait_ref. visit_with ( & mut checker) {
632634 ControlFlow :: Continue ( ( ) ) => Err ( OrphanCheckErr :: NonLocalInputType ( checker. non_local_tys ) ) ,
635+ ControlFlow :: Break ( OrphanCheckEarlyExit :: NormalizationFailure ( err) ) => return Err ( err) ,
633636 ControlFlow :: Break ( OrphanCheckEarlyExit :: ParamTy ( ty) ) => {
634637 // Does there exist some local type after the `ParamTy`.
635638 checker. search_first_local_ty = true ;
@@ -642,34 +645,39 @@ fn orphan_check_trait_ref<'tcx>(
642645 }
643646 }
644647 ControlFlow :: Break ( OrphanCheckEarlyExit :: LocalTy ( _) ) => Ok ( ( ) ) ,
645- }
648+ } )
646649}
647650
648- struct OrphanChecker < ' tcx > {
651+ struct OrphanChecker < ' tcx , F > {
649652 in_crate : InCrate ,
650653 in_self_ty : bool ,
654+ lazily_normalize_ty : F ,
651655 /// Ignore orphan check failures and exclusively search for the first
652656 /// local type.
653657 search_first_local_ty : bool ,
654658 non_local_tys : Vec < ( Ty < ' tcx > , bool ) > ,
655659}
656660
657- impl < ' tcx > OrphanChecker < ' tcx > {
658- fn new ( in_crate : InCrate ) -> Self {
661+ impl < ' tcx , F , E > OrphanChecker < ' tcx , F >
662+ where
663+ F : FnOnce ( Ty < ' tcx > ) -> Result < Ty < ' tcx > , E > ,
664+ {
665+ fn new ( in_crate : InCrate , lazily_normalize_ty : F ) -> Self {
659666 OrphanChecker {
660667 in_crate,
661668 in_self_ty : true ,
669+ lazily_normalize_ty,
662670 search_first_local_ty : false ,
663671 non_local_tys : Vec :: new ( ) ,
664672 }
665673 }
666674
667- fn found_non_local_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < OrphanCheckEarlyExit < ' tcx > > {
675+ fn found_non_local_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < OrphanCheckEarlyExit < ' tcx , E > > {
668676 self . non_local_tys . push ( ( t, self . in_self_ty ) ) ;
669677 ControlFlow :: Continue ( ( ) )
670678 }
671679
672- fn found_param_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < OrphanCheckEarlyExit < ' tcx > > {
680+ fn found_param_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < OrphanCheckEarlyExit < ' tcx , E > > {
673681 if self . search_first_local_ty {
674682 ControlFlow :: Continue ( ( ) )
675683 } else {
@@ -685,18 +693,28 @@ impl<'tcx> OrphanChecker<'tcx> {
685693 }
686694}
687695
688- enum OrphanCheckEarlyExit < ' tcx > {
696+ enum OrphanCheckEarlyExit < ' tcx , E > {
697+ NormalizationFailure ( E ) ,
689698 ParamTy ( Ty < ' tcx > ) ,
690699 LocalTy ( Ty < ' tcx > ) ,
691700}
692701
693- impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for OrphanChecker < ' tcx > {
694- type BreakTy = OrphanCheckEarlyExit < ' tcx > ;
702+ impl < ' tcx , F , E > TypeVisitor < TyCtxt < ' tcx > > for OrphanChecker < ' tcx , F >
703+ where
704+ F : FnMut ( Ty < ' tcx > ) -> Result < Ty < ' tcx > , E > ,
705+ {
706+ type BreakTy = OrphanCheckEarlyExit < ' tcx , E > ;
695707 fn visit_region ( & mut self , _r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
696708 ControlFlow :: Continue ( ( ) )
697709 }
698710
699711 fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
712+ // Need to lazily normalize here in with `-Ztrait-solver=next-coherence`.
713+ let ty = match ( self . lazily_normalize_ty ) ( ty) {
714+ Ok ( ty) => ty,
715+ Err ( err) => return ControlFlow :: Break ( OrphanCheckEarlyExit :: NormalizationFailure ( err) ) ,
716+ } ;
717+
700718 let result = match * ty. kind ( ) {
701719 ty:: Bool
702720 | ty:: Char
0 commit comments