diff options
| author | bors <bors@rust-lang.org> | 2021-09-21 10:33:15 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-09-21 10:33:15 +0000 |
| commit | dda2a0eca4a70acbdd2b65f5fc5e4cd38c39351b (patch) | |
| tree | d27b21c4eda7a9a8b3e6a144493d95cedcc3d833 /compiler/rustc_trait_selection/src | |
| parent | 49c0861ed0fa1d95186d88df0cd4310103e70957 (diff) | |
| parent | afb7472bcca54bffcab6841345cbf58e9f5dfa33 (diff) | |
Auto merge of #89045 - oli-obk:lazy_normalization_in_opaque_types, r=nikomatsakis
Register normalization obligations instead of immediately normalizing in opaque type instantiation For lazy TAIT we will need to instantiate opaque types from within `rustc_infer`, which cannot invoke normalization methods (they are in `rustc_trait_resolution`). So before we move the logic over to `rustc_infer`, we need make sure no normalization happens anymore. This PR resolves that by just registering normalization obligations and continuing. This PR is best reviewed commit by commit I also included f7ad36e which is just an independent cleanup that touches the same code and reduces diagnostics noise a bit r? `@nikomatsakis` cc `@spastorino`
Diffstat (limited to 'compiler/rustc_trait_selection/src')
| -rw-r--r-- | compiler/rustc_trait_selection/src/opaque_types.rs | 71 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/project.rs | 12 |
2 files changed, 32 insertions, 51 deletions
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 8abcdb5e89b..c01faae5d6a 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -1,4 +1,3 @@ -use crate::infer::InferCtxtExt as _; use crate::traits::{self, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -863,7 +862,6 @@ struct Instantiator<'a, 'tcx> { } impl<'a, 'tcx> Instantiator<'a, 'tcx> { - #[instrument(level = "debug", skip(self))] fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T { let tcx = self.infcx.tcx; value.fold_with(&mut BottomUpFolder { @@ -954,6 +952,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { }) } + #[instrument(skip(self), level = "debug")] fn fold_opaque_ty( &mut self, ty: Ty<'tcx>, @@ -964,25 +963,18 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { let tcx = infcx.tcx; let OpaqueTypeKey { def_id, substs } = opaque_type_key; - debug!("instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})", def_id, substs); - // Use the same type variable if the exact same opaque type appears more // than once in the return type (e.g., if it's passed to a type alias). if let Some(opaque_defn) = infcx.inner.borrow().opaque_types.get(&opaque_type_key) { - debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty); + debug!("re-using cached concrete type {:?}", opaque_defn.concrete_ty.kind()); return opaque_defn.concrete_ty; } + let ty_var = infcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span: self.value_span, }); - // Make sure that we are in fact defining the *entire* type - // (e.g., `type Foo<T: Bound> = impl Bar;` needs to be - // defined by a function like `fn foo<T: Bound>() -> Foo<T>`). - debug!("instantiate_opaque_types: param_env={:#?}", self.param_env,); - debug!("instantiate_opaque_types: generics={:#?}", tcx.generics_of(def_id),); - // Ideally, we'd get the span where *this specific `ty` came // from*, but right now we just use the span from the overall // value being folded. In simple cases like `-> impl Foo`, @@ -999,43 +991,40 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { infcx.opaque_types_vars.insert(ty_var, ty); } - debug!("instantiate_opaque_types: ty_var={:?}", ty_var); - self.compute_opaque_type_obligations(opaque_type_key); - - ty_var - } - - fn compute_opaque_type_obligations(&mut self, opaque_type_key: OpaqueTypeKey<'tcx>) { - let infcx = self.infcx; - let tcx = infcx.tcx; - let OpaqueTypeKey { def_id, substs } = opaque_type_key; + debug!("generated new type inference var {:?}", ty_var.kind()); let item_bounds = tcx.explicit_item_bounds(def_id); - debug!("instantiate_opaque_types: bounds={:#?}", item_bounds); - let bounds: Vec<_> = - item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect(); - - let param_env = tcx.param_env(def_id); - let InferOk { value: bounds, obligations } = infcx.partially_normalize_associated_types_in( - ObligationCause::misc(self.value_span, self.body_id), - param_env, - bounds, - ); - self.obligations.extend(obligations); - debug!("instantiate_opaque_types: bounds={:?}", bounds); + self.obligations.reserve(item_bounds.len()); + for (predicate, _) in item_bounds { + debug!(?predicate); + let predicate = predicate.subst(tcx, substs); + debug!(?predicate); + + // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them. + let predicate = predicate.fold_with(&mut BottomUpFolder { + tcx, + ty_op: |ty| match ty.kind() { + ty::Projection(projection_ty) => infcx.infer_projection( + self.param_env, + *projection_ty, + ObligationCause::misc(self.value_span, self.body_id), + 0, + &mut self.obligations, + ), + _ => ty, + }, + lt_op: |lt| lt, + ct_op: |ct| ct, + }); + debug!(?predicate); - for predicate in &bounds { if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() { if projection.ty.references_error() { // No point on adding these obligations since there's a type error involved. - return; + return tcx.ty_error(); } } - } - - self.obligations.reserve(bounds.len()); - for predicate in bounds { // Change the predicate to refer to the type variable, // which will be the concrete type instead of the opaque type. // This also instantiates nested instances of `impl Trait`. @@ -1045,9 +1034,11 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType); // Require that the predicate holds for the concrete type. - debug!("instantiate_opaque_types: predicate={:?}", predicate); + debug!(?predicate); self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate)); } + + ty_var } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 4f22543950c..873c058c55c 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -810,17 +810,7 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>( // and a deferred predicate to resolve this when more type // information is available. - let tcx = selcx.infcx().tcx; - let def_id = projection_ty.item_def_id; - let ty_var = selcx.infcx().next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::NormalizeProjectionType, - span: tcx.def_span(def_id), - }); - let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var }); - let obligation = - Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate(tcx)); - obligations.push(obligation); - ty_var + selcx.infcx().infer_projection(param_env, projection_ty, cause, depth + 1, obligations) }) } |
