@@ -1666,22 +1666,46 @@ fn normalize<'tcx>(
1666
1666
}
1667
1667
1668
1668
use crate :: rustc_trait_selection:: infer:: TyCtxtInferExt ;
1669
- use crate :: rustc_trait_selection:: traits:: query :: normalize :: QueryNormalizeExt ;
1669
+ use crate :: rustc_trait_selection:: traits:: ObligationCtxt ;
1670
1670
use rustc_middle:: traits:: ObligationCause ;
1671
1671
1672
- // Try to normalize `<X as Y>::T` to a type
1672
+ assert ! (
1673
+ !ty. has_non_region_infer( ) ,
1674
+ "`ty`: {:?} has pre existing infer vars before `InferCtxt` creation" ,
1675
+ ty
1676
+ ) ;
1677
+
1673
1678
let infcx = cx. tcx . infer_ctxt ( ) . build ( ) ;
1674
- let normalized = infcx
1675
- . at ( & ObligationCause :: dummy ( ) , cx. param_env )
1676
- . query_normalize ( ty)
1677
- . map ( |resolved| infcx. resolve_vars_if_possible ( resolved. value ) ) ;
1678
- match normalized {
1679
- Ok ( normalized_value) => {
1680
- debug ! ( "normalized {:?} to {:?}" , ty, normalized_value) ;
1681
- Some ( normalized_value)
1682
- }
1683
- Err ( err) => {
1684
- debug ! ( "failed to normalize {:?}: {:?}" , ty, err) ;
1679
+ // use an `ObligationCtxt` as it has a nice API for dealing with returned obligations from normalization
1680
+ // and does not expect us to be inside of typeck. It also does not ICE when the projection could not be
1681
+ // normalized like some other normalization routines (`QueryNormalizer`, `normalize_erasing_regions`, etc)
1682
+ let ocx = ObligationCtxt :: new ( & infcx) ;
1683
+
1684
+ // Try to normalize `<X as Y>::T` to a type
1685
+ let normalized = ocx. normalize ( & ObligationCause :: dummy ( ) , cx. param_env , ty) ;
1686
+ // We have to ensure that we deal with nested obligations from attempting to normalize as `ty`
1687
+ // normalizing to `normalized` is only the case if the nested obligations hold.
1688
+ let errs = ocx. select_all_or_error ( ) ;
1689
+ // Evaluating nested obligations might constrain infer vars that were created during normalization
1690
+ // so we should resolve any infer vars in `normalized` to their new values.
1691
+ let normalized = infcx. resolve_vars_if_possible ( normalized) ;
1692
+
1693
+ match errs. as_slice ( ) {
1694
+ [ ] if normalized == ty => {
1695
+ debug ! ( "normalizing {:?} did not make progress" , ty) ;
1696
+ None
1697
+ }
1698
+ [ ] => {
1699
+ debug ! ( "normalized {:?} to {:?}" , ty, normalized) ;
1700
+
1701
+ assert ! (
1702
+ !normalized. has_non_region_infer( ) ,
1703
+ "`normalized` has infer vars which would escape the `InferCtxt` they were created in"
1704
+ ) ;
1705
+ Some ( normalized)
1706
+ }
1707
+ errs => {
1708
+ debug ! ( "failed to normalize {:?}: {:?}" , ty, errs) ;
1685
1709
None
1686
1710
}
1687
1711
}
0 commit comments