diff options
| author | bors <bors@rust-lang.org> | 2022-03-08 00:53:41 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-03-08 00:53:41 +0000 |
| commit | 67b3e8183830c7af4e06a9aa91de4d1be3c860f7 (patch) | |
| tree | fb444f08e10eb080c832dbe90f81c205ae8a1b20 /compiler | |
| parent | 89adcc636f94d34a6fc90fa117e28ddf6be7b983 (diff) | |
| parent | 06067d94d8122ef079433fb40ef5e0f87ac7d55c (diff) | |
| download | rust-67b3e8183830c7af4e06a9aa91de4d1be3c860f7.tar.gz rust-67b3e8183830c7af4e06a9aa91de4d1be3c860f7.zip | |
Auto merge of #90887 - jackh726:issue-90729, r=nikomatsakis
Try to normalize associated types before processing obligations Closes #90729 r? `@nikomatsakis`
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/fulfill.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/project.rs | 90 |
2 files changed, 97 insertions, 10 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index b4b2e4cd042..62c6c845479 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -346,6 +346,8 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { let obligation = &mut pending_obligation.obligation; + debug!(?obligation, "process_obligation pre-resolve"); + if obligation.predicate.has_infer_types_or_consts() { obligation.predicate = self.selcx.infcx().resolve_vars_if_possible(obligation.predicate); @@ -355,6 +357,21 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { let infcx = self.selcx.infcx(); + if obligation.predicate.has_projections() { + let mut obligations = Vec::new(); + let predicate = crate::traits::project::try_normalize_with_depth_to( + self.selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.predicate, + &mut obligations, + ); + if predicate != obligation.predicate { + obligations.push(obligation.with(predicate)); + return ProcessResult::Changed(mk_pending(obligations)); + } + } let binder = obligation.predicate.kind(); match binder.no_bound_vars() { None => match binder.skip_binder() { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index c32c73c6384..ea48fab1ceb 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -295,6 +295,32 @@ where result } +#[instrument(level = "info", skip(selcx, param_env, cause, obligations))] +pub fn try_normalize_with_depth_to<'a, 'b, 'tcx, T>( + selcx: &'a mut SelectionContext<'b, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, + depth: usize, + value: T, + obligations: &mut Vec<PredicateObligation<'tcx>>, +) -> T +where + T: TypeFoldable<'tcx>, +{ + debug!(obligations.len = obligations.len()); + let mut normalizer = AssocTypeNormalizer::new_without_eager_inference_replacement( + selcx, + param_env, + cause, + depth, + obligations, + ); + let result = ensure_sufficient_stack(|| normalizer.fold(value)); + debug!(?result, obligations.len = normalizer.obligations.len()); + debug!(?normalizer.obligations,); + result +} + pub(crate) fn needs_normalization<'tcx, T: TypeFoldable<'tcx>>(value: &T, reveal: Reveal) -> bool { match reveal { Reveal::UserFacing => value @@ -314,6 +340,10 @@ struct AssocTypeNormalizer<'a, 'b, 'tcx> { obligations: &'a mut Vec<PredicateObligation<'tcx>>, depth: usize, universes: Vec<Option<ty::UniverseIndex>>, + /// If true, when a projection is unable to be completed, an inference + /// variable will be created and an obligation registered to project to that + /// inference variable. Also, constants will be eagerly evaluated. + eager_inference_replacement: bool, } impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { @@ -324,7 +354,33 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { depth: usize, obligations: &'a mut Vec<PredicateObligation<'tcx>>, ) -> AssocTypeNormalizer<'a, 'b, 'tcx> { - AssocTypeNormalizer { selcx, param_env, cause, obligations, depth, universes: vec![] } + AssocTypeNormalizer { + selcx, + param_env, + cause, + obligations, + depth, + universes: vec![], + eager_inference_replacement: true, + } + } + + fn new_without_eager_inference_replacement( + selcx: &'a mut SelectionContext<'b, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + cause: ObligationCause<'tcx>, + depth: usize, + obligations: &'a mut Vec<PredicateObligation<'tcx>>, + ) -> AssocTypeNormalizer<'a, 'b, 'tcx> { + AssocTypeNormalizer { + selcx, + param_env, + cause, + obligations, + depth, + universes: vec![], + eager_inference_replacement: false, + } } fn fold<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T { @@ -428,14 +484,28 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { // there won't be bound vars there. let data = data.super_fold_with(self); - let normalized_ty = normalize_projection_type( - self.selcx, - self.param_env, - data, - self.cause.clone(), - self.depth, - &mut self.obligations, - ); + let normalized_ty = if self.eager_inference_replacement { + normalize_projection_type( + self.selcx, + self.param_env, + data, + self.cause.clone(), + self.depth, + &mut self.obligations, + ) + } else { + opt_normalize_projection_type( + self.selcx, + self.param_env, + data, + self.cause.clone(), + self.depth, + &mut self.obligations, + ) + .ok() + .flatten() + .unwrap_or_else(|| ty::Term::Ty(ty.super_fold_with(self))) + }; debug!( ?self.depth, ?ty, @@ -501,7 +571,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { } fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> { - if self.selcx.tcx().lazy_normalization() { + if self.selcx.tcx().lazy_normalization() || !self.eager_inference_replacement { constant } else { let constant = constant.super_fold_with(self); |
