@@ -29,6 +29,7 @@ use ty::{self, AdtKind, List, Ty, TyCtxt, GenericParamDefKind, ToPredicate};
29
29
use ty:: error:: { ExpectedFound , TypeError } ;
30
30
use ty:: fold:: { TypeFolder , TypeFoldable , TypeVisitor } ;
31
31
use infer:: { InferCtxt } ;
32
+ use util:: common:: ErrorReported ;
32
33
33
34
use rustc_data_structures:: sync:: Lrc ;
34
35
use std:: fmt:: Debug ;
@@ -632,44 +633,15 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx
632
633
}
633
634
}
634
635
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 >
642
642
{
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) ;
658
644
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
-
673
645
tcx. infer_ctxt ( ) . enter ( |infcx| {
674
646
// FIXME. We should really... do something with these region
675
647
// 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>,
685
657
// them here too, and we will remove this function when
686
658
// we move over to lazy normalization *anyway*.
687
659
let fulfill_cx = FulfillmentContext :: new_ignoring_regions ( ) ;
688
-
689
660
let predicates = match fully_normalize (
690
661
& infcx,
691
662
fulfill_cx,
692
663
cause,
693
664
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.
700
665
& predicates,
701
666
) {
702
667
Ok ( predicates) => predicates,
703
668
Err ( errors) => {
704
669
infcx. report_fulfillment_errors ( & errors, None , false ) ;
705
- // An unnormalized env is better than nothing.
706
- return elaborated_env;
670
+ return Err ( ErrorReported )
707
671
}
708
672
} ;
709
673
710
- debug ! ( "normalize_param_env_or_error: normalized predicates={:?}" ,
711
- predicates) ;
674
+ debug ! ( "do_normalize_predictes: normalized predicates = {:?}" , predicates) ;
712
675
713
676
let region_scope_tree = region:: ScopeTree :: default ( ) ;
714
677
@@ -734,21 +697,119 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
734
697
// unconstrained variable, and it seems better not to ICE,
735
698
// all things considered.
736
699
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 )
739
701
}
740
702
} ;
741
703
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
+ }
745
786
} ;
746
787
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) ;
749
808
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 )
752
813
}
753
814
754
815
pub fn fully_normalize < ' a , ' gcx , ' tcx , T > (
0 commit comments