@@ -8,12 +8,16 @@ use rustc_errors::{ErrorGuaranteed, StashKey};
88use rustc_hir as hir;
99use rustc_hir:: intravisit:: { self , Visitor } ;
1010use rustc_infer:: infer:: error_reporting:: TypeAnnotationNeeded :: E0282 ;
11+ use rustc_middle:: traits:: ObligationCause ;
1112use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , PointerCoercion } ;
1213use rustc_middle:: ty:: fold:: { TypeFoldable , TypeFolder } ;
1314use rustc_middle:: ty:: visit:: TypeVisitableExt ;
15+ use rustc_middle:: ty:: TypeSuperFoldable ;
1416use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
1517use rustc_span:: symbol:: sym;
1618use rustc_span:: Span ;
19+ use rustc_trait_selection:: solve;
20+ use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt ;
1721
1822use std:: mem;
1923
@@ -695,24 +699,22 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
695699 }
696700 }
697701
698- fn resolve < T > ( & mut self , x : T , span : & dyn Locatable ) -> T
702+ fn resolve < T > ( & mut self , value : T , span : & dyn Locatable ) -> T
699703 where
700704 T : TypeFoldable < TyCtxt < ' tcx > > ,
701705 {
702- let mut resolver = Resolver :: new ( self . fcx , span, self . body ) ;
703- let x = x. fold_with ( & mut resolver) ;
704- if cfg ! ( debug_assertions) && x. has_infer ( ) {
705- span_bug ! ( span. to_span( self . fcx. tcx) , "writeback: `{:?}` has inference variables" , x) ;
706- }
706+ let value = self . fcx . resolve_vars_if_possible ( value) ;
707+ let value = value. fold_with ( & mut Resolver :: new ( self . fcx , span, self . body ) ) ;
708+ assert ! ( !value. has_infer( ) ) ;
707709
708710 // We may have introduced e.g. `ty::Error`, if inference failed, make sure
709711 // to mark the `TypeckResults` as tainted in that case, so that downstream
710712 // users of the typeck results don't produce extra errors, or worse, ICEs.
711- if let Some ( e ) = resolver . replaced_with_error {
712- self . typeck_results . tainted_by_errors = Some ( e ) ;
713+ if let Err ( guar ) = value . error_reported ( ) {
714+ self . typeck_results . tainted_by_errors = Some ( guar ) ;
713715 }
714716
715- x
717+ value
716718 }
717719}
718720
@@ -732,15 +734,13 @@ impl Locatable for hir::HirId {
732734 }
733735}
734736
735- /// The Resolver. This is the type folding engine that detects
736- /// unresolved types and so forth.
737737struct Resolver < ' cx , ' tcx > {
738738 fcx : & ' cx FnCtxt < ' cx , ' tcx > ,
739739 span : & ' cx dyn Locatable ,
740740 body : & ' tcx hir:: Body < ' tcx > ,
741-
742- /// Set to `Some` if any `Ty` or `ty::Const` had to be replaced with an `Error` .
743- replaced_with_error : Option < ErrorGuaranteed > ,
741+ /// Whether we should normalize using the new solver, disabled
742+ /// both when using the old solver and when resolving predicates .
743+ should_normalize : bool ,
744744}
745745
746746impl < ' cx , ' tcx > Resolver < ' cx , ' tcx > {
@@ -749,7 +749,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
749749 span : & ' cx dyn Locatable ,
750750 body : & ' tcx hir:: Body < ' tcx > ,
751751 ) -> Resolver < ' cx , ' tcx > {
752- Resolver { fcx, span, body, replaced_with_error : None }
752+ Resolver { fcx, span, body, should_normalize : fcx . next_trait_solver ( ) }
753753 }
754754
755755 fn report_error ( & self , p : impl Into < ty:: GenericArg < ' tcx > > ) -> ErrorGuaranteed {
@@ -768,64 +768,73 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
768768 . emit ( ) ,
769769 }
770770 }
771+
772+ fn handle_term < T > (
773+ & mut self ,
774+ value : T ,
775+ outer_exclusive_binder : impl FnOnce ( T ) -> ty:: DebruijnIndex ,
776+ new_err : impl Fn ( TyCtxt < ' tcx > , ErrorGuaranteed ) -> T ,
777+ ) -> T
778+ where
779+ T : Into < ty:: GenericArg < ' tcx > > + Copy ,
780+ T : TypeFoldable < TyCtxt < ' tcx > > ,
781+ T : TypeSuperFoldable < TyCtxt < ' tcx > > ,
782+ {
783+ let tcx = self . fcx . tcx ;
784+ // We must deeply normalize in the new solver, since later lints
785+ // expect that types that show up in the typeck are fully
786+ // normalized.
787+ let value = if self . should_normalize {
788+ let body_id = tcx. hir ( ) . body_owner_def_id ( self . body . id ( ) ) ;
789+ let cause = ObligationCause :: misc ( self . span . to_span ( tcx) , body_id) ;
790+ let at = self . fcx . at ( & cause, self . fcx . param_env ) ;
791+ let universes = vec ! [ None ; outer_exclusive_binder( value) . as_usize( ) ] ;
792+ solve:: deeply_normalize_with_skipped_universes ( at, value, universes) . unwrap_or_else (
793+ |errors| {
794+ let guar = self . fcx . err_ctxt ( ) . report_fulfillment_errors ( errors) ;
795+ new_err ( tcx, guar)
796+ } ,
797+ )
798+ } else {
799+ value
800+ } ;
801+
802+ if value. has_non_region_infer ( ) {
803+ let guar = self . report_error ( value) ;
804+ new_err ( tcx, guar)
805+ } else {
806+ tcx. fold_regions ( value, |_, _| tcx. lifetimes . re_erased )
807+ }
808+ }
771809}
772810
773811impl < ' cx , ' tcx > TypeFolder < TyCtxt < ' tcx > > for Resolver < ' cx , ' tcx > {
774812 fn interner ( & self ) -> TyCtxt < ' tcx > {
775813 self . fcx . tcx
776814 }
777815
778- fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
779- let tcx = self . fcx . tcx ;
780- match self . fcx . fully_resolve ( t) {
781- Ok ( t) if self . fcx . next_trait_solver ( ) => {
782- // We must normalize erasing regions here, since later lints
783- // expect that types that show up in the typeck are fully
784- // normalized.
785- if let Ok ( t) = tcx. try_normalize_erasing_regions ( self . fcx . param_env , t) {
786- t
787- } else {
788- tcx. fold_regions ( t, |_, _| tcx. lifetimes . re_erased )
789- }
790- }
791- Ok ( t) => {
792- // Do not anonymize late-bound regions
793- // (e.g. keep `for<'a>` named `for<'a>`).
794- // This allows NLL to generate error messages that
795- // refer to the higher-ranked lifetime names written by the user.
796- tcx. fold_regions ( t, |_, _| tcx. lifetimes . re_erased )
797- }
798- Err ( _) => {
799- debug ! ( "Resolver::fold_ty: input type `{:?}` not fully resolvable" , t) ;
800- let e = self . report_error ( t) ;
801- self . replaced_with_error = Some ( e) ;
802- Ty :: new_error ( self . fcx . tcx , e)
803- }
804- }
805- }
806-
807816 fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
808817 debug_assert ! ( !r. is_bound( ) , "Should not be resolving bound region." ) ;
809818 self . fcx . tcx . lifetimes . re_erased
810819 }
811820
821+ fn fold_ty ( & mut self , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
822+ self . handle_term ( ty, Ty :: outer_exclusive_binder, Ty :: new_error)
823+ }
824+
812825 fn fold_const ( & mut self , ct : ty:: Const < ' tcx > ) -> ty:: Const < ' tcx > {
813- match self . fcx . fully_resolve ( ct) {
814- Ok ( ct) => self . fcx . tcx . erase_regions ( ct) ,
815- Err ( _) => {
816- debug ! ( "Resolver::fold_const: input const `{:?}` not fully resolvable" , ct) ;
817- let e = self . report_error ( ct) ;
818- self . replaced_with_error = Some ( e) ;
819- ty:: Const :: new_error ( self . fcx . tcx , e, ct. ty ( ) )
820- }
821- }
826+ self . handle_term ( ct, ty:: Const :: outer_exclusive_binder, |tcx, guar| {
827+ ty:: Const :: new_error ( tcx, guar, ct. ty ( ) )
828+ } )
822829 }
823- }
824830
825- ///////////////////////////////////////////////////////////////////////////
826- // During type check, we store promises with the result of trait
827- // lookup rather than the actual results (because the results are not
828- // necessarily available immediately). These routines unwind the
829- // promises. It is expected that we will have already reported any
830- // errors that may be encountered, so if the promises store an error,
831- // a dummy result is returned.
831+ fn fold_predicate ( & mut self , predicate : ty:: Predicate < ' tcx > ) -> ty:: Predicate < ' tcx > {
832+ // Do not normalize predicates in the new solver. The new solver is
833+ // supposed to handle unnormalized predicates and incorrectly normalizing
834+ // them can be unsound, e.g. for `WellFormed` predicates.
835+ let prev = mem:: replace ( & mut self . should_normalize , false ) ;
836+ let predicate = predicate. super_fold_with ( self ) ;
837+ self . should_normalize = prev;
838+ predicate
839+ }
840+ }
0 commit comments