@@ -29,6 +29,7 @@ use ty::{self, AdtKind, List, Ty, TyCtxt, GenericParamDefKind, ToPredicate};
2929use ty:: error:: { ExpectedFound , TypeError } ;
3030use ty:: fold:: { TypeFolder , TypeFoldable , TypeVisitor } ;
3131use infer:: { InferCtxt } ;
32+ use util:: common:: ErrorReported ;
3233
3334use rustc_data_structures:: sync:: Lrc ;
3435use std:: fmt:: Debug ;
@@ -632,44 +633,15 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx
632633 }
633634}
634635
635- // FIXME: this is gonna need to be removed ...
636- /// Normalizes the parameter environment, reporting errors if they occur.
637- pub fn normalize_param_env_or_error < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
638- region_context : DefId ,
639- unnormalized_env : ty:: ParamEnv < ' tcx > ,
640- cause : ObligationCause < ' tcx > )
641- -> ty:: ParamEnv < ' tcx >
636+ fn do_normalize_predicates < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
637+ region_context : DefId ,
638+ cause : ObligationCause < ' tcx > ,
639+ elaborated_env : ty:: ParamEnv < ' tcx > ,
640+ predicates : Vec < ty:: Predicate < ' tcx > > )
641+ -> Result < Vec < ty:: Predicate < ' tcx > > , ErrorReported >
642642{
643- // I'm not wild about reporting errors here; I'd prefer to
644- // have the errors get reported at a defined place (e.g.,
645- // during typeck). Instead I have all parameter
646- // environments, in effect, going through this function
647- // and hence potentially reporting errors. This ensures of
648- // course that we never forget to normalize (the
649- // alternative seemed like it would involve a lot of
650- // manual invocations of this fn -- and then we'd have to
651- // deal with the errors at each of those sites).
652- //
653- // In any case, in practice, typeck constructs all the
654- // parameter environments once for every fn as it goes,
655- // and errors will get reported then; so after typeck we
656- // can be sure that no errors should occur.
657-
643+ debug ! ( "do_normalize_predicates({:?})" , predicates) ;
658644 let span = cause. span ;
659-
660- debug ! ( "normalize_param_env_or_error(unnormalized_env={:?})" ,
661- unnormalized_env) ;
662-
663- let predicates: Vec < _ > =
664- util:: elaborate_predicates ( tcx, unnormalized_env. caller_bounds . to_vec ( ) )
665- . collect ( ) ;
666-
667- debug ! ( "normalize_param_env_or_error: elaborated-predicates={:?}" ,
668- predicates) ;
669-
670- let elaborated_env = ty:: ParamEnv :: new ( tcx. intern_predicates ( & predicates) ,
671- unnormalized_env. reveal ) ;
672-
673645 tcx. infer_ctxt ( ) . enter ( |infcx| {
674646 // FIXME. We should really... do something with these region
675647 // obligations. But this call just continues the older
@@ -685,30 +657,21 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
685657 // them here too, and we will remove this function when
686658 // we move over to lazy normalization *anyway*.
687659 let fulfill_cx = FulfillmentContext :: new_ignoring_regions ( ) ;
688-
689660 let predicates = match fully_normalize (
690661 & infcx,
691662 fulfill_cx,
692663 cause,
693664 elaborated_env,
694- // You would really want to pass infcx.param_env.caller_bounds here,
695- // but that is an interned slice, and fully_normalize takes &T and returns T, so
696- // without further refactoring, a slice can't be used. Luckily, we still have the
697- // predicate vector from which we created the ParamEnv in infcx, so we
698- // can pass that instead. It's roundabout and a bit brittle, but this code path
699- // ought to be refactored anyway, and until then it saves us from having to copy.
700665 & predicates,
701666 ) {
702667 Ok ( predicates) => predicates,
703668 Err ( errors) => {
704669 infcx. report_fulfillment_errors ( & errors, None , false ) ;
705- // An unnormalized env is better than nothing.
706- return elaborated_env;
670+ return Err ( ErrorReported )
707671 }
708672 } ;
709673
710- debug ! ( "normalize_param_env_or_error: normalized predicates={:?}" ,
711- predicates) ;
674+ debug ! ( "do_normalize_predictes: normalized predicates = {:?}" , predicates) ;
712675
713676 let region_scope_tree = region:: ScopeTree :: default ( ) ;
714677
@@ -734,21 +697,119 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
734697 // unconstrained variable, and it seems better not to ICE,
735698 // all things considered.
736699 tcx. sess . span_err ( span, & fixup_err. to_string ( ) ) ;
737- // An unnormalized env is better than nothing.
738- return elaborated_env;
700+ return Err ( ErrorReported )
739701 }
740702 } ;
741703
742- let predicates = match tcx. lift_to_global ( & predicates) {
743- Some ( predicates) => predicates,
744- None => return elaborated_env,
704+ match tcx. lift_to_global ( & predicates) {
705+ Some ( predicates) => Ok ( predicates) ,
706+ None => {
707+ // FIXME: shouldn't we, you know, actually report an error here? or an ICE?
708+ Err ( ErrorReported )
709+ }
710+ }
711+ } )
712+ }
713+
714+ // FIXME: this is gonna need to be removed ...
715+ /// Normalizes the parameter environment, reporting errors if they occur.
716+ pub fn normalize_param_env_or_error < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
717+ region_context : DefId ,
718+ unnormalized_env : ty:: ParamEnv < ' tcx > ,
719+ cause : ObligationCause < ' tcx > )
720+ -> ty:: ParamEnv < ' tcx >
721+ {
722+ // I'm not wild about reporting errors here; I'd prefer to
723+ // have the errors get reported at a defined place (e.g.,
724+ // during typeck). Instead I have all parameter
725+ // environments, in effect, going through this function
726+ // and hence potentially reporting errors. This ensures of
727+ // course that we never forget to normalize (the
728+ // alternative seemed like it would involve a lot of
729+ // manual invocations of this fn -- and then we'd have to
730+ // deal with the errors at each of those sites).
731+ //
732+ // In any case, in practice, typeck constructs all the
733+ // parameter environments once for every fn as it goes,
734+ // and errors will get reported then; so after typeck we
735+ // can be sure that no errors should occur.
736+
737+ debug ! ( "normalize_param_env_or_error(region_context={:?}, unnormalized_env={:?}, cause={:?})" ,
738+ region_context, unnormalized_env, cause) ;
739+
740+ let mut predicates: Vec < _ > =
741+ util:: elaborate_predicates ( tcx, unnormalized_env. caller_bounds . to_vec ( ) )
742+ . collect ( ) ;
743+
744+ debug ! ( "normalize_param_env_or_error: elaborated-predicates={:?}" ,
745+ predicates) ;
746+
747+ let elaborated_env = ty:: ParamEnv :: new ( tcx. intern_predicates ( & predicates) ,
748+ unnormalized_env. reveal ) ;
749+
750+ // HACK: we are trying to normalize the param-env inside *itself*. The problem is that
751+ // normalization expects its param-env to be already normalized, which means we have
752+ // a circularity.
753+ //
754+ // The way we handle this is by normalizing the param-env inside an unnormalized version
755+ // of the param-env, which means that if the param-env contains unnormalized projections,
756+ // we'll have some normalization failures. This is unfortunate.
757+ //
758+ // Lazy normalization would basically handle this by treating just the
759+ // normalizing-a-trait-ref-requires-itself cycles as evaluation failures.
760+ //
761+ // Inferred outlives bounds can create a lot of `TypeOutlives` predicates for associated
762+ // types, so to make the situation less bad, we normalize all the predicates *but*
763+ // the `TypeOutlives` predicates first inside the unnormalized parameter environment, and
764+ // then we normalize the `TypeOutlives` bounds inside the normalized parameter environment.
765+ //
766+ // This works fairly well because trait matching does not actually care about param-env
767+ // TypeOutlives predicates - these are normally used by regionck.
768+ let outlives_predicates: Vec < _ > = predicates. drain_filter ( |predicate| {
769+ match predicate {
770+ ty:: Predicate :: TypeOutlives ( ..) => true ,
771+ _ => false
772+ }
773+ } ) . collect ( ) ;
774+
775+ debug ! ( "normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})" ,
776+ predicates, outlives_predicates) ;
777+ let non_outlives_predicates =
778+ match do_normalize_predicates ( tcx, region_context, cause. clone ( ) ,
779+ elaborated_env, predicates) {
780+ Ok ( predicates) => predicates,
781+ // An unnormalized env is better than nothing.
782+ Err ( ErrorReported ) => {
783+ debug ! ( "normalize_param_env_or_error: errored resolving non-outlives predicates" ) ;
784+ return elaborated_env
785+ }
745786 } ;
746787
747- debug ! ( "normalize_param_env_or_error: resolved predicates={:?}" ,
748- predicates) ;
788+ debug ! ( "normalize_param_env_or_error: non-outlives predicates={:?}" , non_outlives_predicates) ;
789+
790+ // Not sure whether it is better to include the unnormalized TypeOutlives predicates
791+ // here. I believe they should not matter, because we are ignoring TypeOutlives param-env
792+ // predicates here anyway. Keeping them here anyway because it seems safer.
793+ let outlives_env: Vec < _ > =
794+ non_outlives_predicates. iter ( ) . chain ( & outlives_predicates) . cloned ( ) . collect ( ) ;
795+ let outlives_env = ty:: ParamEnv :: new ( tcx. intern_predicates ( & outlives_env) ,
796+ unnormalized_env. reveal ) ;
797+ let outlives_predicates =
798+ match do_normalize_predicates ( tcx, region_context, cause,
799+ outlives_env, outlives_predicates) {
800+ Ok ( predicates) => predicates,
801+ // An unnormalized env is better than nothing.
802+ Err ( ErrorReported ) => {
803+ debug ! ( "normalize_param_env_or_error: errored resolving outlives predicates" ) ;
804+ return elaborated_env
805+ }
806+ } ;
807+ debug ! ( "normalize_param_env_or_error: outlives predicates={:?}" , outlives_predicates) ;
749808
750- ty:: ParamEnv :: new ( tcx. intern_predicates ( & predicates) , unnormalized_env. reveal )
751- } )
809+ let mut predicates = non_outlives_predicates;
810+ predicates. extend ( outlives_predicates) ;
811+ debug ! ( "normalize_param_env_or_error: final predicates={:?}" , predicates) ;
812+ ty:: ParamEnv :: new ( tcx. intern_predicates ( & predicates) , unnormalized_env. reveal )
752813}
753814
754815pub fn fully_normalize < ' a , ' gcx , ' tcx , T > (
0 commit comments