diff options
| author | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2021-10-21 14:56:00 +0000 |
|---|---|---|
| committer | Deadbeef <ent3rm4n@gmail.com> | 2021-11-29 21:19:46 +0800 |
| commit | 721ffd14c35a7cb0202b84492196fa134ca65f3d (patch) | |
| tree | 001fe0b57a9fa8ff271a67b3085830d7fb1e45d7 | |
| parent | 22eeff700e4d2b4c4160c63d8d3e14931268b5f8 (diff) | |
| download | rust-721ffd14c35a7cb0202b84492196fa134ca65f3d.tar.gz rust-721ffd14c35a7cb0202b84492196fa134ca65f3d.zip | |
Add constness to ParamEnv
This now causes a lot of queries to be executed twice, as reveal_all forces NotConst
| -rw-r--r-- | compiler/rustc_middle/src/hir/map/mod.rs | 25 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 56 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/structural_impls.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/auto_trait.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/mod.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/object_safety.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/ty.rs | 37 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/compare_method.rs | 20 |
8 files changed, 127 insertions, 46 deletions
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index d9d0781b37a..bde566d4c31 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -454,18 +454,30 @@ impl<'hir> Map<'hir> { /// /// Panics if `LocalDefId` does not have an associated body. pub fn body_owner_kind(&self, id: HirId) -> BodyOwnerKind { + match self.opt_body_owner_kind(id) { + Ok(kind) => kind, + Err(node) => bug!("{:#?} is not a body node", node), + } + } + + /// Returns the `BodyOwnerKind` of this `LocalDefId`. + /// + /// Returns the `Node` if `LocalDefId` does not have an associated body. + pub fn opt_body_owner_kind(&self, id: HirId) -> Result<BodyOwnerKind, Node<'_>> { match self.get(id) { Node::Item(&Item { kind: ItemKind::Const(..), .. }) | Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. }) | Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. }) - | Node::AnonConst(_) => BodyOwnerKind::Const, + | Node::AnonConst(_) => Ok(BodyOwnerKind::Const), Node::Ctor(..) | Node::Item(&Item { kind: ItemKind::Fn(..), .. }) | Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. }) - | Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(..), .. }) => BodyOwnerKind::Fn, - Node::Item(&Item { kind: ItemKind::Static(_, m, _), .. }) => BodyOwnerKind::Static(m), - Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => BodyOwnerKind::Closure, - node => bug!("{:#?} is not a body node", node), + | Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(..), .. }) => Ok(BodyOwnerKind::Fn), + Node::Item(&Item { kind: ItemKind::Static(_, m, _), .. }) => { + Ok(BodyOwnerKind::Static(m)) + } + Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => Ok(BodyOwnerKind::Closure), + node => Err(node), } } @@ -474,7 +486,8 @@ impl<'hir> Map<'hir> { /// Panics if `LocalDefId` does not have an associated body. /// /// This should only be used for determining the context of a body, a return - /// value of `Some` does not always suggest that the owner of the body is `const`. + /// value of `Some` does not always suggest that the owner of the body is `const`, + /// just that it has to be checked as if it were. pub fn body_const_context(&self, did: LocalDefId) -> Option<ConstContext> { let hir_id = self.local_def_id_to_hir_id(did); let ccx = match self.body_owner_kind(hir_id) { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 4720c895a1e..8e7eb46f260 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1227,22 +1227,27 @@ pub struct ParamEnv<'tcx> { #[derive(Copy, Clone)] struct ParamTag { reveal: traits::Reveal, + constness: hir::Constness, } unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag { - const BITS: usize = 1; + const BITS: usize = 2; #[inline] fn into_usize(self) -> usize { match self { - Self { reveal: traits::Reveal::UserFacing } => 0, - Self { reveal: traits::Reveal::All } => 1, + Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } => 0, + Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } => 1, + Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } => 2, + Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 3, } } #[inline] unsafe fn from_usize(ptr: usize) -> Self { match ptr { - 0 => Self { reveal: traits::Reveal::UserFacing }, - 1 => Self { reveal: traits::Reveal::All }, + 0 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst }, + 1 => Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst }, + 2 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const }, + 3 => Self { reveal: traits::Reveal::All, constness: hir::Constness::Const }, _ => std::hint::unreachable_unchecked(), } } @@ -1253,6 +1258,7 @@ impl<'tcx> fmt::Debug for ParamEnv<'tcx> { f.debug_struct("ParamEnv") .field("caller_bounds", &self.caller_bounds()) .field("reveal", &self.reveal()) + .field("constness", &self.constness()) .finish() } } @@ -1261,20 +1267,23 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ParamEnv<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { self.caller_bounds().hash_stable(hcx, hasher); self.reveal().hash_stable(hcx, hasher); + self.constness().hash_stable(hcx, hasher); } } impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> { - fn super_fold_with<F: ty::fold::TypeFolder<'tcx>>( - self, - folder: &mut F, - ) -> Result<Self, F::Error> { - Ok(ParamEnv::new(self.caller_bounds().fold_with(folder)?, self.reveal().fold_with(folder)?)) + fn super_fold_with<F: ty::fold::TypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + ParamEnv::new( + self.caller_bounds().fold_with(folder)?, + self.reveal().fold_with(folder)?, + self.constness().fold_with(folder)?, + ) } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.caller_bounds().visit_with(visitor)?; - self.reveal().visit_with(visitor) + self.reveal().visit_with(visitor)?; + self.constness().visit_with(visitor) } } @@ -1285,7 +1294,7 @@ impl<'tcx> ParamEnv<'tcx> { /// type-checking. #[inline] pub fn empty() -> Self { - Self::new(List::empty(), Reveal::UserFacing) + Self::new(List::empty(), Reveal::UserFacing, hir::Constness::NotConst) } #[inline] @@ -1298,6 +1307,11 @@ impl<'tcx> ParamEnv<'tcx> { self.packed.tag().reveal } + #[inline] + pub fn constness(self) -> hir::Constness { + self.packed.tag().constness + } + /// Construct a trait environment with no where-clauses in scope /// where the values of all `impl Trait` and other hidden types /// are revealed. This is suitable for monomorphized, post-typeck @@ -1307,13 +1321,17 @@ impl<'tcx> ParamEnv<'tcx> { /// or invoke `param_env.with_reveal_all()`. #[inline] pub fn reveal_all() -> Self { - Self::new(List::empty(), Reveal::All) + Self::new(List::empty(), Reveal::All, hir::Constness::NotConst) } /// Construct a trait environment with the given set of predicates. #[inline] - pub fn new(caller_bounds: &'tcx List<Predicate<'tcx>>, reveal: Reveal) -> Self { - ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal }) } + pub fn new( + caller_bounds: &'tcx List<Predicate<'tcx>>, + reveal: Reveal, + constness: hir::Constness, + ) -> Self { + ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal, constness }) } } pub fn with_user_facing(mut self) -> Self { @@ -1335,13 +1353,17 @@ impl<'tcx> ParamEnv<'tcx> { return self; } - ParamEnv::new(tcx.normalize_opaque_types(self.caller_bounds()), Reveal::All) + ParamEnv::new( + tcx.normalize_opaque_types(self.caller_bounds()), + Reveal::All, + self.constness(), + ) } /// Returns this same environment but with no caller bounds. #[inline] pub fn without_caller_bounds(self) -> Self { - Self::new(List::empty(), self.reveal()) + Self::new(List::empty(), self.reveal(), self.constness()) } /// Creates a suitable environment in which to perform trait diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index ee6eed0f39b..f637412a117 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -480,7 +480,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> { type Lifted = ty::ParamEnv<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { tcx.lift(self.caller_bounds()) - .map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal())) + .map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal(), self.constness())) } } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 7af32b2f3b1..74de49e8fa4 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -370,12 +370,17 @@ impl AutoTraitFinder<'tcx> { computed_preds.clone().chain(user_computed_preds.iter().cloned()), ) .map(|o| o.predicate); - new_env = ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal()); + new_env = ty::ParamEnv::new( + tcx.mk_predicates(normalized_preds), + param_env.reveal(), + param_env.constness(), + ); } let final_user_env = ty::ParamEnv::new( tcx.mk_predicates(user_computed_preds.into_iter()), user_env.reveal(), + user_env.constness(), ); debug!( "evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \ diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 4bc22d5d735..36305429877 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -307,8 +307,11 @@ pub fn normalize_param_env_or_error<'tcx>( debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates); - let elaborated_env = - ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal()); + let elaborated_env = ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + unnormalized_env.reveal(), + unnormalized_env.constness(), + ); // HACK: we are trying to normalize the param-env inside *itself*. The problem is that // normalization expects its param-env to be already normalized, which means we have @@ -360,8 +363,11 @@ pub fn normalize_param_env_or_error<'tcx>( // predicates here anyway. Keeping them here anyway because it seems safer. let outlives_env: Vec<_> = non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect(); - let outlives_env = - ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal()); + let outlives_env = ty::ParamEnv::new( + tcx.intern_predicates(&outlives_env), + unnormalized_env.reveal(), + unnormalized_env.constness(), + ); let outlives_predicates = match do_normalize_predicates( tcx, region_context, @@ -381,7 +387,11 @@ pub fn normalize_param_env_or_error<'tcx>( let mut predicates = non_outlives_predicates; predicates.extend(outlives_predicates); debug!("normalize_param_env_or_error: final predicates={:?}", predicates); - ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal()) + ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + unnormalized_env.reveal(), + unnormalized_env.constness(), + ) } pub fn fully_normalize<'a, 'tcx, T>( diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index afc546540d2..616efffd999 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -698,7 +698,11 @@ fn receiver_is_dispatchable<'tcx>( .chain(array::IntoIter::new([unsize_predicate, trait_predicate])) .collect(); - ty::ParamEnv::new(tcx.intern_predicates(&caller_bounds), param_env.reveal()) + ty::ParamEnv::new( + tcx.intern_predicates(&caller_bounds), + param_env.reveal(), + param_env.constness(), + ) }; // Receiver: DispatchFromDyn<Receiver[Self => U]> diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index af3706f886e..dccb74c03f7 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -285,16 +285,33 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // issue #89334 predicates = tcx.expose_default_const_substs(predicates); - let unnormalized_env = - ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing); - - debug!("unnormalized_env caller bounds: {:?}", unnormalized_env.caller_bounds()); - let body_id = def_id - .as_local() - .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) - .map_or(hir::CRATE_HIR_ID, |id| { - tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id) - }); + let local_did = def_id.as_local(); + let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)); + + let constness = match hir_id { + Some(hir_id) => match tcx.hir().opt_body_owner_kind(hir_id) { + Err(hir::Node::Item(&hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + })) => constness, + Err(_) => hir::Constness::NotConst, + Ok(_) => match tcx.hir().body_const_context(local_did.unwrap()) { + Some(_) => hir::Constness::Const, + None => hir::Constness::NotConst, + }, + }, + None => hir::Constness::NotConst, + }; + + let unnormalized_env = ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + traits::Reveal::UserFacing, + constness, + ); + + let body_id = hir_id.map_or(hir::CRATE_HIR_ID, |id| { + tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id) + }); let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id); traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause) } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 4d4662f73a9..51dd0f98eb5 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -208,8 +208,11 @@ fn compare_predicate_entailment<'tcx>( // The key step here is to update the caller_bounds's predicates to be // the new hybrid bounds we computed. let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_hir_id); - let param_env = - ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing); + let param_env = ty::ParamEnv::new( + tcx.intern_predicates(&hybrid_preds.predicates), + Reveal::UserFacing, + hir::Constness::NotConst, + ); let param_env = traits::normalize_param_env_or_error(tcx, impl_m.def_id, param_env, normalize_cause); @@ -1183,8 +1186,11 @@ fn compare_type_predicate_entailment<'tcx>( debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds); let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id); - let param_env = - ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing); + let param_env = ty::ParamEnv::new( + tcx.intern_predicates(&hybrid_preds.predicates), + Reveal::UserFacing, + hir::Constness::NotConst, + ); let param_env = traits::normalize_param_env_or_error( tcx, impl_ty.def_id, @@ -1369,7 +1375,11 @@ pub fn check_type_bounds<'tcx>( .to_predicate(tcx), ), }; - ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing) + ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + Reveal::UserFacing, + param_env.constness(), + ) }; debug!(?normalize_param_env); |
