|
| 1 | +use rustc_data_structures::fx::FxHashSet; |
1 | 2 | use rustc_hir::def_id::LocalDefId; |
2 | 3 | use rustc_infer::infer::outlives::env::OutlivesEnvironment; |
3 | | -use rustc_infer::infer::{InferCtxt, RegionResolutionError}; |
| 4 | +use rustc_infer::infer::{ |
| 5 | + InferCtxt, RegionResolutionError, SubregionOrigin, TypeOutlivesConstraint, |
| 6 | +}; |
4 | 7 | use rustc_macros::extension; |
5 | 8 | use rustc_middle::traits::ObligationCause; |
6 | | -use rustc_middle::traits::query::NoSolution; |
7 | 9 | use rustc_middle::ty::{self, Ty, elaborate}; |
8 | 10 |
|
9 | 11 | use crate::traits::ScrubbedTraitError; |
10 | 12 | use crate::traits::outlives_bounds::InferCtxtExt; |
11 | 13 |
|
| 14 | +fn normalize_higher_ranked_assumptions<'tcx>( |
| 15 | + infcx: &InferCtxt<'tcx>, |
| 16 | + param_env: ty::ParamEnv<'tcx>, |
| 17 | +) -> FxHashSet<ty::ArgOutlivesPredicate<'tcx>> { |
| 18 | + let assumptions = infcx.take_registered_region_assumptions(); |
| 19 | + if !infcx.next_trait_solver() { |
| 20 | + return elaborate::elaborate_outlives_assumptions(infcx.tcx, assumptions); |
| 21 | + } |
| 22 | + |
| 23 | + let mut normalized_assumptions = vec![]; |
| 24 | + let mut seen_assumptions = FxHashSet::default(); |
| 25 | + |
| 26 | + for assumption in assumptions { |
| 27 | + if !seen_assumptions.insert(assumption) { |
| 28 | + continue; |
| 29 | + } |
| 30 | + |
| 31 | + let assumption = infcx.resolve_vars_if_possible(assumption); |
| 32 | + let outlives = ty::Binder::dummy(assumption); |
| 33 | + let ty::OutlivesPredicate(kind, region) = |
| 34 | + match crate::solve::deeply_normalize::<_, ScrubbedTraitError<'tcx>>( |
| 35 | + infcx.at(&ObligationCause::dummy(), param_env), |
| 36 | + outlives, |
| 37 | + ) { |
| 38 | + Ok(assumption) => assumption, |
| 39 | + Err(_) => { |
| 40 | + infcx.dcx().delayed_bug(format!( |
| 41 | + "could not normalize higher-ranked assumption `{assumption}`" |
| 42 | + )); |
| 43 | + outlives |
| 44 | + } |
| 45 | + } |
| 46 | + .no_bound_vars() |
| 47 | + .expect("started with no bound vars, should end with no bound vars"); |
| 48 | + |
| 49 | + normalized_assumptions.push(ty::OutlivesPredicate(kind, region)); |
| 50 | + } |
| 51 | + |
| 52 | + for assumption in infcx.take_registered_region_assumptions() { |
| 53 | + if seen_assumptions.insert(assumption) { |
| 54 | + normalized_assumptions.push(assumption); |
| 55 | + } |
| 56 | + } |
| 57 | + |
| 58 | + elaborate::elaborate_outlives_assumptions(infcx.tcx, normalized_assumptions) |
| 59 | +} |
| 60 | + |
| 61 | +fn normalize_registered_region_obligations<'tcx>( |
| 62 | + infcx: &InferCtxt<'tcx>, |
| 63 | + param_env: ty::ParamEnv<'tcx>, |
| 64 | +) -> Result<(), (ty::PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>)> { |
| 65 | + if !infcx.next_trait_solver() { |
| 66 | + return Ok(()); |
| 67 | + } |
| 68 | + |
| 69 | + let obligations = infcx.take_registered_region_obligations(); |
| 70 | + let mut seen_outputs = FxHashSet::default(); |
| 71 | + let mut normalized_obligations = vec![]; |
| 72 | + |
| 73 | + for TypeOutlivesConstraint { sup_type, sub_region, origin } in obligations { |
| 74 | + let outlives = infcx.resolve_vars_if_possible(ty::Binder::dummy(ty::OutlivesPredicate( |
| 75 | + sup_type, sub_region, |
| 76 | + ))); |
| 77 | + let ty::OutlivesPredicate(sup_type, sub_region) = crate::solve::deeply_normalize( |
| 78 | + infcx.at(&ObligationCause::dummy_with_span(origin.span()), param_env), |
| 79 | + outlives, |
| 80 | + ) |
| 81 | + .map_err(|_: Vec<ScrubbedTraitError<'tcx>>| (outlives, origin.clone()))? |
| 82 | + .no_bound_vars() |
| 83 | + .expect("started with no bound vars, should end with no bound vars"); |
| 84 | + |
| 85 | + if seen_outputs.insert((sup_type, sub_region)) { |
| 86 | + normalized_obligations.push(TypeOutlivesConstraint { sup_type, sub_region, origin }); |
| 87 | + } |
| 88 | + } |
| 89 | + |
| 90 | + for obligation in infcx.take_registered_region_obligations() { |
| 91 | + if seen_outputs.insert((obligation.sup_type, obligation.sub_region)) { |
| 92 | + normalized_obligations.push(obligation); |
| 93 | + } |
| 94 | + } |
| 95 | + |
| 96 | + for obligation in normalized_obligations { |
| 97 | + infcx.register_type_outlives_constraint_inner(obligation); |
| 98 | + } |
| 99 | + |
| 100 | + Ok(()) |
| 101 | +} |
| 102 | + |
12 | 103 | #[extension(pub trait OutlivesEnvironmentBuildExt<'tcx>)] |
13 | 104 | impl<'tcx> OutlivesEnvironment<'tcx> { |
14 | 105 | fn new( |
@@ -46,10 +137,7 @@ impl<'tcx> OutlivesEnvironment<'tcx> { |
46 | 137 | } |
47 | 138 | } |
48 | 139 |
|
49 | | - // FIXME(-Znext-trait-solver): Normalize these. |
50 | | - let higher_ranked_assumptions = infcx.take_registered_region_assumptions(); |
51 | | - let higher_ranked_assumptions = |
52 | | - elaborate::elaborate_outlives_assumptions(infcx.tcx, higher_ranked_assumptions); |
| 140 | + let higher_ranked_assumptions = normalize_higher_ranked_assumptions(infcx, param_env); |
53 | 141 |
|
54 | 142 | // FIXME: This needs to be modified so that we normalize the known type |
55 | 143 | // outlives obligations then elaborate them into their region/type components. |
@@ -98,21 +186,14 @@ impl<'tcx> InferCtxt<'tcx> { |
98 | 186 | &self, |
99 | 187 | outlives_env: &OutlivesEnvironment<'tcx>, |
100 | 188 | ) -> Vec<RegionResolutionError<'tcx>> { |
101 | | - self.resolve_regions_with_normalize(&outlives_env, |ty, origin| { |
102 | | - let ty = self.resolve_vars_if_possible(ty); |
103 | | - |
104 | | - if self.next_trait_solver() { |
105 | | - crate::solve::deeply_normalize( |
106 | | - self.at( |
107 | | - &ObligationCause::dummy_with_span(origin.span()), |
108 | | - outlives_env.param_env, |
109 | | - ), |
110 | | - ty, |
111 | | - ) |
112 | | - .map_err(|_: Vec<ScrubbedTraitError<'tcx>>| NoSolution) |
113 | | - } else { |
114 | | - Ok(ty) |
115 | | - } |
| 189 | + if let Err((outlives, origin)) = |
| 190 | + normalize_registered_region_obligations(self, outlives_env.param_env) |
| 191 | + { |
| 192 | + return vec![RegionResolutionError::CannotNormalize(outlives, origin)]; |
| 193 | + } |
| 194 | + |
| 195 | + self.resolve_regions_with_normalize(outlives_env, |outlives, _| { |
| 196 | + Ok(self.resolve_vars_if_possible(outlives)) |
116 | 197 | }) |
117 | 198 | } |
118 | 199 | } |
0 commit comments