From 22eeff700e4d2b4c4160c63d8d3e14931268b5f8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 21 Oct 2021 13:23:00 +0000 Subject: [PATCH 01/18] Prepare for more ParamEnv flags --- compiler/rustc_middle/src/ty/mod.rs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2d6926703726c..4720c895a1ee8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1221,23 +1221,28 @@ pub struct ParamEnv<'tcx> { /// want `Reveal::All`. /// /// Note: This is packed, use the reveal() method to access it. - packed: CopyTaggedPtr<&'tcx List>, traits::Reveal, true>, + packed: CopyTaggedPtr<&'tcx List>, ParamTag, true>, } -unsafe impl rustc_data_structures::tagged_ptr::Tag for traits::Reveal { +#[derive(Copy, Clone)] +struct ParamTag { + reveal: traits::Reveal, +} + +unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag { const BITS: usize = 1; #[inline] fn into_usize(self) -> usize { match self { - traits::Reveal::UserFacing => 0, - traits::Reveal::All => 1, + Self { reveal: traits::Reveal::UserFacing } => 0, + Self { reveal: traits::Reveal::All } => 1, } } #[inline] unsafe fn from_usize(ptr: usize) -> Self { match ptr { - 0 => traits::Reveal::UserFacing, - 1 => traits::Reveal::All, + 0 => Self { reveal: traits::Reveal::UserFacing }, + 1 => Self { reveal: traits::Reveal::All }, _ => std::hint::unreachable_unchecked(), } } @@ -1290,7 +1295,7 @@ impl<'tcx> ParamEnv<'tcx> { #[inline] pub fn reveal(self) -> traits::Reveal { - self.packed.tag() + self.packed.tag().reveal } /// Construct a trait environment with no where-clauses in scope @@ -1308,11 +1313,11 @@ impl<'tcx> ParamEnv<'tcx> { /// Construct a trait environment with the given set of predicates. #[inline] pub fn new(caller_bounds: &'tcx List>, reveal: Reveal) -> Self { - ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, reveal) } + ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal }) } } pub fn with_user_facing(mut self) -> Self { - self.packed.set_tag(Reveal::UserFacing); + self.packed.set_tag(ParamTag { reveal: Reveal::UserFacing, ..self.packed.tag() }); self } @@ -1326,7 +1331,7 @@ impl<'tcx> ParamEnv<'tcx> { /// will be normalized to their underlying types. /// See PR #65989 and issue #65918 for more details pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self { - if self.packed.tag() == traits::Reveal::All { + if self.packed.tag().reveal == traits::Reveal::All { return self; } From 721ffd14c35a7cb0202b84492196fa134ca65f3d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 21 Oct 2021 14:56:00 +0000 Subject: [PATCH 02/18] Add constness to ParamEnv This now causes a lot of queries to be executed twice, as reveal_all forces NotConst --- compiler/rustc_middle/src/hir/map/mod.rs | 25 +++++++-- compiler/rustc_middle/src/ty/mod.rs | 56 +++++++++++++------ .../rustc_middle/src/ty/structural_impls.rs | 2 +- .../src/traits/auto_trait.rs | 7 ++- .../rustc_trait_selection/src/traits/mod.rs | 20 +++++-- .../src/traits/object_safety.rs | 6 +- compiler/rustc_ty_utils/src/ty.rs | 37 ++++++++---- .../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 d9d0781b37aac..bde566d4c3136 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> { 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 { 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 4720c895a1ee8..8e7eb46f26010 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> 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>( - self, - folder: &mut F, - ) -> Result { - Ok(ParamEnv::new(self.caller_bounds().fold_with(folder)?, self.reveal().fold_with(folder)?)) + fn super_fold_with>(self, folder: &mut F) -> Result { + ParamEnv::new( + self.caller_bounds().fold_with(folder)?, + self.reveal().fold_with(folder)?, + self.constness().fold_with(folder)?, + ) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { 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>, reveal: Reveal) -> Self { - ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal }) } + pub fn new( + caller_bounds: &'tcx List>, + 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 ee6eed0f39b2d..f637412a11744 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 { 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 7af32b2f3b174..74de49e8fa4c3 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 4bc22d5d73543..36305429877a8 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 afc546540d2e2..616efffd999ec 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 U]> diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index af3706f886e9c..dccb74c03f725 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 4d4662f73a955..51dd0f98eb504 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); From 1761d88f4a39302ddc0c961811cb03ac02e01cf9 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 21 Oct 2021 15:24:29 +0000 Subject: [PATCH 03/18] Static items are also const --- compiler/rustc_hir/src/hir.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c67d3df3dedd8..2b4403b37ffc4 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3246,6 +3246,7 @@ impl<'hir> Node<'hir> { | Node::Item(Item { kind: ItemKind::Impl(Impl { constness, .. }), .. }) => *constness, Node::Item(Item { kind: ItemKind::Const(..), .. }) + | Node::Item(Item { kind: ItemKind::Static(..), .. }) | Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. }) | Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const, From e37947f0973aa9927809d102b00264c207f5e530 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 21 Oct 2021 15:28:26 +0000 Subject: [PATCH 04/18] Re-use `constness_for_typeck` instead of rolling it ourselves --- compiler/rustc_middle/src/hir/map/mod.rs | 22 +++++----------------- compiler/rustc_ty_utils/src/ty.rs | 12 +----------- 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index bde566d4c3136..c3d2fd4e15ca4 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -454,30 +454,18 @@ 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> { match self.get(id) { Node::Item(&Item { kind: ItemKind::Const(..), .. }) | Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. }) | Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. }) - | Node::AnonConst(_) => Ok(BodyOwnerKind::Const), + | Node::AnonConst(_) => BodyOwnerKind::Const, Node::Ctor(..) | Node::Item(&Item { kind: ItemKind::Fn(..), .. }) | Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. }) - | 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), + | 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), } } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index dccb74c03f725..4bcc80c83022e 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -289,17 +289,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { 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, - }, - }, + Some(hir_id) => tcx.hir().get(hir_id).constness_for_typeck(), None => hir::Constness::NotConst, }; From 19f2101272464465b7cd4758230a95d9f3486cbf Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 25 Oct 2021 12:48:58 +0000 Subject: [PATCH 05/18] Fixup add const to param env --- src/test/ui/infinite/infinite-struct.stderr | 2 +- src/test/ui/infinite/infinite-tag-type-recursion.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/infinite/infinite-struct.stderr b/src/test/ui/infinite/infinite-struct.stderr index 369645f9030fb..383e13fd4b09d 100644 --- a/src/test/ui/infinite/infinite-struct.stderr +++ b/src/test/ui/infinite/infinite-struct.stderr @@ -19,7 +19,7 @@ LL | struct Take(Take); | ^^^^^^^^^^^^^^^^^^ | = note: ...which immediately requires computing drop-check constraints for `Take` again - = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: Take } }` + = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, constness: NotConst }, value: Take } }` error: aborting due to 2 previous errors diff --git a/src/test/ui/infinite/infinite-tag-type-recursion.stderr b/src/test/ui/infinite/infinite-tag-type-recursion.stderr index 61b5e94677526..1802c7599a3b5 100644 --- a/src/test/ui/infinite/infinite-tag-type-recursion.stderr +++ b/src/test/ui/infinite/infinite-tag-type-recursion.stderr @@ -18,7 +18,7 @@ LL | enum MList { Cons(isize, MList), Nil } | ^^^^^^^^^^ | = note: ...which immediately requires computing drop-check constraints for `MList` again - = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: MList } }` + = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, constness: NotConst }, value: MList } }` error: aborting due to 2 previous errors From d51068ca28027d10b280746c7b4ed85f3900feb2 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 21 Oct 2021 16:07:37 +0000 Subject: [PATCH 06/18] Use the constness from the param env instead of having a separate dimension for it This breaks a ~const test that will be fixed in a follow up commit of this PR --- .../src/transform/check_consts/check.rs | 3 +- .../src/transform/check_consts/qualifs.rs | 3 +- compiler/rustc_infer/src/traits/engine.rs | 20 +--------- compiler/rustc_infer/src/traits/mod.rs | 10 +++++ .../src/traits/fulfill.rs | 39 +------------------ .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/mod.rs | 38 +----------------- .../rustc_typeck/src/check/compare_method.rs | 10 +---- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 4 +- compiler/rustc_typeck/src/check/inherited.rs | 14 ------- .../rfc-2632-const-trait-impl/assoc-type.rs | 4 +- .../assoc-type.stderr | 20 ---------- 12 files changed, 25 insertions(+), 142 deletions(-) delete mode 100644 src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 274665ccd9836..f9e65ea907564 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -817,8 +817,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { ); let implsrc = tcx.infer_ctxt().enter(|infcx| { - let mut selcx = - SelectionContext::with_constness(&infcx, hir::Constness::Const); + let mut selcx = SelectionContext::new(&infcx); selcx.select(&obligation) }); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index abc5a3c6a5206..43612292f5283 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -3,7 +3,6 @@ //! See the `Qualif` trait for more info. use rustc_errors::ErrorReported; -use rustc_hir as hir; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::*; use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty}; @@ -167,7 +166,7 @@ impl Qualif for NeedsNonConstDrop { ); let implsrc = cx.tcx.infer_ctxt().enter(|infcx| { - let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const); + let mut selcx = SelectionContext::new(&infcx); selcx.select(&obligation) }); !matches!( diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 152a395c871be..d9ef60d3bfc95 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -1,7 +1,6 @@ use crate::infer::InferCtxt; use crate::traits::Obligation; use rustc_data_structures::fx::FxHashMap; -use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, ToPredicate, Ty, WithConstness}; @@ -48,25 +47,10 @@ pub trait TraitEngine<'tcx>: 'tcx { fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec>; - fn select_all_with_constness_or_error( + fn select_where_possible( &mut self, infcx: &InferCtxt<'_, 'tcx>, - _constness: hir::Constness, - ) -> Vec> { - self.select_all_or_error(infcx) - } - - fn select_where_possible(&mut self, infcx: &InferCtxt<'_, 'tcx>) - -> Vec>; - - // FIXME(fee1-dead) this should not provide a default body for chalk as chalk should be updated - fn select_with_constness_where_possible( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - _constness: hir::Constness, - ) -> Vec> { - self.select_where_possible(infcx) - } + ) -> Vec>; fn pending_obligations(&self) -> Vec>; diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index e8622b3c819d2..7e30f859dae4e 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -69,6 +69,16 @@ impl PredicateObligation<'tcx> { } } +impl TraitObligation<'tcx> { + /// Returns `true` if the trait predicate is considered `const` in its ParamEnv. + pub fn is_const(&self) -> bool { + match (self.predicate.skip_binder().constness, self.param_env.constness()) { + (ty::BoundConstness::ConstIfConst, hir::Constness::Const) => true, + _ => false, + } + } +} + // `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(PredicateObligation<'_>, 32); diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index e121837c987ae..8a60f9b8602f6 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -4,7 +4,6 @@ use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_errors::ErrorReported; -use rustc_hir as hir; use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::thir::abstract_const::NotConstEvaluatable; @@ -231,21 +230,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect() } - fn select_all_with_constness_or_error( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - constness: rustc_hir::Constness, - ) -> Vec> { - { - let errors = self.select_with_constness_where_possible(infcx, constness); - if !errors.is_empty() { - return errors; - } - } - - self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect() - } - fn select_where_possible( &mut self, infcx: &InferCtxt<'_, 'tcx>, @@ -254,15 +238,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { self.select(&mut selcx) } - fn select_with_constness_where_possible( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - constness: hir::Constness, - ) -> Vec> { - let mut selcx = SelectionContext::with_constness(infcx, constness); - self.select(&mut selcx) - } - fn pending_obligations(&self) -> Vec> { self.predicates.map_pending_obligations(|o| o.obligation.clone()) } @@ -679,12 +654,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { if obligation.predicate.is_known_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. - // - // If the predicate is considered const, then we cannot use this because - // it will cause false negatives in the ui tests. - if !self.selcx.is_predicate_const(obligation.predicate) - && infcx.predicate_must_hold_considering_regions(obligation) - { + if infcx.predicate_must_hold_considering_regions(obligation) { debug!( "selecting trait at depth {} evaluated to holds", obligation.recursion_depth @@ -738,12 +708,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { if obligation.predicate.is_global(tcx) { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. - // - // If the predicate is considered const, then we cannot use this because - // it will cause false negatives in the ui tests. - if !self.selcx.is_predicate_const(obligation.predicate) - && self.selcx.infcx().predicate_must_hold_considering_regions(obligation) - { + if self.selcx.infcx().predicate_must_hold_considering_regions(obligation) { return ProcessResult::Changed(vec![]); } else { tracing::debug!("Does NOT hold: {:?}", obligation); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 6e3e3b9b14480..5a857676a20c8 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -303,7 +303,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else if lang_items.drop_trait() == Some(def_id) && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst { - if self.is_in_const_context { + if obligation.param_env.constness() == hir::Constness::Const { self.assemble_const_drop_candidates(obligation, stack, &mut candidates)?; } else { debug!("passing ~const Drop bound; in non-const context"); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 767cb1618bb67..173eb1c5894c4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -128,9 +128,6 @@ pub struct SelectionContext<'cx, 'tcx> { /// and a negative impl allow_negative_impls: bool, - /// Are we in a const context that needs `~const` bounds to be const? - is_in_const_context: bool, - /// The mode that trait queries run in, which informs our error handling /// policy. In essence, canonicalized queries need their errors propagated /// rather than immediately reported because we do not have accurate spans. @@ -222,7 +219,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls: false, - is_in_const_context: false, query_mode: TraitQueryMode::Standard, } } @@ -234,7 +230,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: true, intercrate_ambiguity_causes: None, allow_negative_impls: false, - is_in_const_context: false, query_mode: TraitQueryMode::Standard, } } @@ -250,7 +245,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls, - is_in_const_context: false, query_mode: TraitQueryMode::Standard, } } @@ -266,26 +260,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls: false, - is_in_const_context: false, query_mode, } } - pub fn with_constness( - infcx: &'cx InferCtxt<'cx, 'tcx>, - constness: hir::Constness, - ) -> SelectionContext<'cx, 'tcx> { - SelectionContext { - infcx, - freshener: infcx.freshener_keep_static(), - intercrate: false, - intercrate_ambiguity_causes: None, - allow_negative_impls: false, - is_in_const_context: matches!(constness, hir::Constness::Const), - query_mode: TraitQueryMode::Standard, - } - } - /// Enables tracking of intercrate ambiguity causes. These are /// used in coherence to give improved diagnostics. We don't do /// this until we detect a coherence error because it can lead to @@ -318,20 +296,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.intercrate } - /// Returns `true` if the trait predicate is considerd `const` to this selection context. - pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool { - matches!(pred.constness, ty::BoundConstness::ConstIfConst) && self.is_in_const_context - } - - /// Returns `true` if the predicate is considered `const` to - /// this selection context. - pub fn is_predicate_const(&self, pred: ty::Predicate<'_>) -> bool { - match pred.kind().skip_binder() { - ty::PredicateKind::Trait(pred) => self.is_trait_predicate_const(pred), - _ => false, - } - } - /////////////////////////////////////////////////////////////////////////// // Selection // @@ -1138,7 +1102,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { for candidate in candidates { // Respect const trait obligations - if self.is_trait_predicate_const(obligation.predicate.skip_binder()) { + if obligation.is_const() { match candidate { // const impl ImplCandidate(def_id) diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 51dd0f98eb504..8141950ee8ddd 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1388,13 +1388,7 @@ pub fn check_type_bounds<'tcx>( impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs); tcx.infer_ctxt().enter(move |infcx| { - let constness = impl_ty - .container - .impl_def_id() - .map(|did| tcx.impl_constness(did)) - .unwrap_or(hir::Constness::NotConst); - - let inh = Inherited::with_constness(infcx, impl_ty.def_id.expect_local(), constness); + let inh = Inherited::new(infcx, impl_ty.def_id.expect_local()); let infcx = &inh.infcx; let mut selcx = traits::SelectionContext::new(&infcx); @@ -1439,7 +1433,7 @@ pub fn check_type_bounds<'tcx>( // Check that all obligations are satisfied by the implementation's // version. let errors = - inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness); + inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); if !errors.is_empty() { infcx.report_fulfillment_errors(&errors, None, false); return Err(ErrorReported); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 142a0a8fc2501..58a2f21d22e67 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -613,7 +613,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let errors = self .fulfillment_cx .borrow_mut() - .select_all_with_constness_or_error(&self, self.inh.constness); + .select_all_or_error(&self); if !errors.is_empty() { self.report_fulfillment_errors(&errors, self.inh.body_id, false); @@ -629,7 +629,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut result = self .fulfillment_cx .borrow_mut() - .select_with_constness_where_possible(self, self.inh.constness); + .select_where_possible(self); if !result.is_empty() { mutate_fulfillment_errors(&mut result); self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred); diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index f7552c1f4eb0c..bf52e77504331 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -53,9 +53,6 @@ pub struct Inherited<'a, 'tcx> { pub(super) deferred_generator_interiors: RefCell, hir::GeneratorKind)>>, - /// Reports whether this is in a const context. - pub(super) constness: hir::Constness, - pub(super) body_id: Option, /// Whenever we introduce an adjustment from `!` into a type variable, @@ -102,16 +99,6 @@ impl<'tcx> InheritedBuilder<'tcx> { impl Inherited<'a, 'tcx> { pub(super) fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self { - let tcx = infcx.tcx; - let item_id = tcx.hir().local_def_id_to_hir_id(def_id); - Self::with_constness(infcx, def_id, tcx.hir().get(item_id).constness_for_typeck()) - } - - pub(super) fn with_constness( - infcx: InferCtxt<'a, 'tcx>, - def_id: LocalDefId, - constness: hir::Constness, - ) -> Self { let tcx = infcx.tcx; let item_id = tcx.hir().local_def_id_to_hir_id(def_id); let body_id = tcx.hir().maybe_body_owned_by(item_id); @@ -128,7 +115,6 @@ impl Inherited<'a, 'tcx> { deferred_cast_checks: RefCell::new(Vec::new()), deferred_generator_interiors: RefCell::new(Vec::new()), diverging_type_vars: RefCell::new(Default::default()), - constness, body_id, } } diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs index 228b5ed71e80a..c65adc9178479 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs @@ -1,6 +1,6 @@ // FIXME(fee1-dead): this should have a better error message #![feature(const_trait_impl)] - +// check-pass struct NonConstAdd(i32); impl std::ops::Add for NonConstAdd { @@ -29,3 +29,5 @@ impl const Baz for NonConstAdd { } fn main() {} + +// TODO: this test should not pass \ No newline at end of file diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr deleted file mode 100644 index b894092205e43..0000000000000 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0277]: cannot add `NonConstAdd` to `NonConstAdd` - --> $DIR/assoc-type.rs:19:5 - | -LL | type Bar = NonConstAdd; - | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `NonConstAdd + NonConstAdd` - | - = help: the trait `Add` is not implemented for `NonConstAdd` -note: required by a bound in `Foo::Bar` - --> $DIR/assoc-type.rs:15:15 - | -LL | type Bar: ~const std::ops::Add; - | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar` -help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement - | -LL | impl const Foo for NonConstAdd where NonConstAdd: Add { - | ++++++++++++++++++++++ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. From 40f39e6c6a97dd3d2313bcd9db42185dd39cfa58 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 25 Oct 2021 13:28:09 +0000 Subject: [PATCH 07/18] Fixup --- src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs index c65adc9178479..321cea0d4154a 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs @@ -17,7 +17,7 @@ trait Foo { impl const Foo for NonConstAdd { type Bar = NonConstAdd; - //~^ ERROR + //TODO: ~^ ERROR } trait Baz { @@ -28,6 +28,4 @@ impl const Baz for NonConstAdd { type Qux = NonConstAdd; // OK } -fn main() {} - -// TODO: this test should not pass \ No newline at end of file +fn main() {} \ No newline at end of file From b16c811f1cbaf4d2e7e61409a0bd39aef5a6b1b4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 21 Oct 2021 18:12:19 +0000 Subject: [PATCH 08/18] Prefer TraitPredicate over ConstnessAnd --- compiler/rustc_middle/src/traits/select.rs | 2 +- .../src/traits/select/mod.rs | 33 +++++-------------- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 560660517f34b..621bc0c5786c3 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -12,7 +12,7 @@ use rustc_hir::def_id::DefId; use rustc_query_system::cache::Cache; pub type SelectionCache<'tcx> = Cache< - (ty::ConstnessAnd>>, ty::ImplPolarity), + ty::ParamEnvAnd<'tcx, ty::TraitPredicate<'tcx>>, SelectionResult<'tcx, SelectionCandidate<'tcx>>, >; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 173eb1c5894c4..2690fdbea6b0c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1231,19 +1231,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return None; } let tcx = self.tcx(); - let pred = &cache_fresh_trait_pred.skip_binder(); - let trait_ref = pred.trait_ref; + let pred = cache_fresh_trait_pred.skip_binder(); if self.can_use_global_caches(param_env) { - if let Some(res) = tcx - .selection_cache - .get(&(param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), tcx) - { + if let Some(res) = tcx.selection_cache.get(¶m_env.and(pred), tcx) { return Some(res); } } - self.infcx - .selection_cache - .get(&(param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), tcx) + self.infcx.selection_cache.get(¶m_env.and(pred), tcx) } /// Determines whether can we safely cache the result @@ -1288,36 +1282,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) { let tcx = self.tcx(); let pred = cache_fresh_trait_pred.skip_binder(); - let trait_ref = pred.trait_ref; if !self.can_cache_candidate(&candidate) { - debug!(?trait_ref, ?candidate, "insert_candidate_cache - candidate is not cacheable"); + debug!(?pred, ?candidate, "insert_candidate_cache - candidate is not cacheable"); return; } if self.can_use_global_caches(param_env) { if let Err(Overflow) = candidate { // Don't cache overflow globally; we only produce this in certain modes. - } else if !trait_ref.needs_infer() { + } else if !pred.needs_infer() { if !candidate.needs_infer() { - debug!(?trait_ref, ?candidate, "insert_candidate_cache global"); + debug!(?pred, ?candidate, "insert_candidate_cache global"); // This may overwrite the cache with the same value. - tcx.selection_cache.insert( - (param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), - dep_node, - candidate, - ); + tcx.selection_cache.insert(param_env.and(pred), dep_node, candidate); return; } } } - debug!(?trait_ref, ?candidate, "insert_candidate_cache local"); - self.infcx.selection_cache.insert( - (param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), - dep_node, - candidate, - ); + debug!(?pred, ?candidate, "insert_candidate_cache local"); + self.infcx.selection_cache.insert(param_env.and(pred), dep_node, candidate); } /// Matches a predicate against the bounds of its self type. From d161cc20718138ab7846b51303c0dc0db0172a8b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 25 Oct 2021 14:04:15 +0000 Subject: [PATCH 09/18] Replace `ConstnessAnd` with `TraitPredicate` which conveys the same information --- compiler/rustc_middle/src/traits/select.rs | 6 +- .../src/traits/select/mod.rs | 109 +++++++----------- 2 files changed, 46 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 621bc0c5786c3..ff711bff86f61 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -16,10 +16,8 @@ pub type SelectionCache<'tcx> = Cache< SelectionResult<'tcx, SelectionCandidate<'tcx>>, >; -pub type EvaluationCache<'tcx> = Cache< - (ty::ParamEnvAnd<'tcx, ty::ConstnessAnd>>, ty::ImplPolarity), - EvaluationResult, ->; +pub type EvaluationCache<'tcx> = + Cache>, EvaluationResult>; /// The selection process begins by considering all impls, where /// clauses, and so forth that might resolve an obligation. Sometimes diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 2690fdbea6b0c..55fd38ac261dd 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -39,7 +39,6 @@ use rustc_middle::ty::fast_reject; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef}; -use rustc_middle::ty::WithConstness; use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable}; use rustc_span::symbol::sym; @@ -138,9 +137,9 @@ pub struct SelectionContext<'cx, 'tcx> { struct TraitObligationStack<'prev, 'tcx> { obligation: &'prev TraitObligation<'tcx>, - /// The trait ref from `obligation` but "freshened" with the + /// The trait predicate from `obligation` but "freshened" with the /// selection-context's freshener. Used to check for recursion. - fresh_trait_ref: ty::ConstnessAnd>, + fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, /// Starts out equal to `depth` -- if, during evaluation, we /// encounter a cycle, then we will set this flag to the minimum @@ -676,20 +675,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } let stack = self.push_stack(previous_stack, &obligation); - let fresh_trait_ref = stack.fresh_trait_ref; + let fresh_trait_pred = stack.fresh_trait_pred; - debug!(?fresh_trait_ref); + debug!(?fresh_trait_pred); - if let Some(result) = self.check_evaluation_cache( - obligation.param_env, - fresh_trait_ref, - obligation.polarity(), - ) { + if let Some(result) = self.check_evaluation_cache(obligation.param_env, fresh_trait_pred) { debug!(?result, "CACHE HIT"); return Ok(result); } - if let Some(result) = stack.cache().get_provisional(fresh_trait_ref) { + if let Some(result) = stack.cache().get_provisional(fresh_trait_pred) { debug!(?result, "PROVISIONAL CACHE HIT"); stack.update_reached_depth(result.reached_depth); return Ok(result.result); @@ -714,19 +709,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let reached_depth = stack.reached_depth.get(); if reached_depth >= stack.depth { debug!(?result, "CACHE MISS"); - self.insert_evaluation_cache( - obligation.param_env, - fresh_trait_ref, - obligation.polarity(), - dep_node, - result, - ); + self.insert_evaluation_cache(obligation.param_env, fresh_trait_pred, dep_node, result); - stack.cache().on_completion(stack.dfn, |fresh_trait_ref, provisional_result| { + stack.cache().on_completion(stack.dfn, |fresh_trait_pred, provisional_result| { self.insert_evaluation_cache( obligation.param_env, - fresh_trait_ref, - obligation.polarity(), + fresh_trait_pred, dep_node, provisional_result.max(result), ); @@ -736,10 +724,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!( "caching provisionally because {:?} \ is a cycle participant (at depth {}, reached depth {})", - fresh_trait_ref, stack.depth, reached_depth, + fresh_trait_pred, stack.depth, reached_depth, ); - stack.cache().insert_provisional(stack.dfn, reached_depth, fresh_trait_ref, result); + stack.cache().insert_provisional(stack.dfn, reached_depth, fresh_trait_pred, result); } Ok(result) @@ -773,7 +761,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .skip(1) // Skip top-most frame. .find(|prev| { stack.obligation.param_env == prev.obligation.param_env - && stack.fresh_trait_ref == prev.fresh_trait_ref + && stack.fresh_trait_pred == prev.fresh_trait_pred }) .map(|stack| stack.depth) { @@ -836,7 +824,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // terms of `Fn` etc, but we could probably make this more // precise still. let unbound_input_types = - stack.fresh_trait_ref.value.skip_binder().substs.types().any(|ty| ty.is_fresh()); + stack.fresh_trait_pred.skip_binder().trait_ref.substs.types().any(|ty| ty.is_fresh()); if stack.obligation.polarity() != ty::ImplPolarity::Negative { // This check was an imperfect workaround for a bug in the old @@ -874,8 +862,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { && stack.iter().skip(1).any(|prev| { stack.obligation.param_env == prev.obligation.param_env && self.match_fresh_trait_refs( - stack.fresh_trait_ref, - prev.fresh_trait_ref, + stack.fresh_trait_pred, + prev.fresh_trait_pred, prev.obligation.param_env, ) }) @@ -953,7 +941,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // not just the lifetime choice for this particular (non-erased) // predicate. // See issue #80691 - if stack.fresh_trait_ref.has_erased_regions() { + if stack.fresh_trait_pred.has_erased_regions() { result = result.max(EvaluatedToOkModuloRegions); } @@ -964,8 +952,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn check_evaluation_cache( &self, param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::ConstnessAnd>, - polarity: ty::ImplPolarity, + trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option { // Neither the global nor local cache is aware of intercrate // mode, so don't do any caching. In particular, we might @@ -977,19 +964,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); if self.can_use_global_caches(param_env) { - if let Some(res) = tcx.evaluation_cache.get(&(param_env.and(trait_ref), polarity), tcx) - { + if let Some(res) = tcx.evaluation_cache.get(¶m_env.and(trait_pred), tcx) { return Some(res); } } - self.infcx.evaluation_cache.get(&(param_env.and(trait_ref), polarity), tcx) + self.infcx.evaluation_cache.get(¶m_env.and(trait_pred), tcx) } fn insert_evaluation_cache( &mut self, param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::ConstnessAnd>, - polarity: ty::ImplPolarity, + trait_pred: ty::PolyTraitPredicate<'tcx>, dep_node: DepNodeIndex, result: EvaluationResult, ) { @@ -1008,23 +993,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if self.can_use_global_caches(param_env) { - if !trait_ref.needs_infer() { - debug!(?trait_ref, ?result, "insert_evaluation_cache global"); + if !trait_pred.needs_infer() { + debug!(?trait_pred, ?result, "insert_evaluation_cache global"); // This may overwrite the cache with the same value // FIXME: Due to #50507 this overwrites the different values // This should be changed to use HashMapExt::insert_same // when that is fixed - self.tcx().evaluation_cache.insert( - (param_env.and(trait_ref), polarity), - dep_node, - result, - ); + self.tcx().evaluation_cache.insert(param_env.and(trait_pred), dep_node, result); return; } } - debug!(?trait_ref, ?result, "insert_evaluation_cache"); - self.infcx.evaluation_cache.insert((param_env.and(trait_ref), polarity), dep_node, result); + debug!(?trait_pred, ?result, "insert_evaluation_cache"); + self.infcx.evaluation_cache.insert(param_env.and(trait_pred), dep_node, result); } /// For various reasons, it's possible for a subobligation @@ -2154,8 +2135,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn match_fresh_trait_refs( &self, - previous: ty::ConstnessAnd>, - current: ty::ConstnessAnd>, + previous: ty::PolyTraitPredicate<'tcx>, + current: ty::PolyTraitPredicate<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> bool { let mut matcher = ty::_match::Match::new(self.tcx(), param_env); @@ -2167,18 +2148,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { previous_stack: TraitObligationStackList<'o, 'tcx>, obligation: &'o TraitObligation<'tcx>, ) -> TraitObligationStack<'o, 'tcx> { - let fresh_trait_ref = obligation + let fresh_trait_pred = obligation .predicate - .to_poly_trait_ref() .fold_with(&mut self.freshener) - .into_ok() - .with_constness(obligation.predicate.skip_binder().constness); + .into_ok(); let dfn = previous_stack.cache.next_dfn(); let depth = previous_stack.depth() + 1; TraitObligationStack { obligation, - fresh_trait_ref, + fresh_trait_pred, reached_depth: Cell::new(depth), previous: previous_stack, dfn, @@ -2372,7 +2351,7 @@ impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> { debug!(reached_depth, "update_reached_depth"); let mut p = self; while reached_depth < p.depth { - debug!(?p.fresh_trait_ref, "update_reached_depth: marking as cycle participant"); + debug!(?p.fresh_trait_pred, "update_reached_depth: marking as cycle participant"); p.reached_depth.set(p.reached_depth.get().min(reached_depth)); p = p.previous.head.unwrap(); } @@ -2451,7 +2430,7 @@ struct ProvisionalEvaluationCache<'tcx> { /// - then we determine that `E` is in error -- we will then clear /// all cache values whose DFN is >= 4 -- in this case, that /// means the cached value for `F`. - map: RefCell>, ProvisionalEvaluation>>, + map: RefCell, ProvisionalEvaluation>>, } /// A cache value for the provisional cache: contains the depth-first @@ -2483,28 +2462,28 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { /// `reached_depth` (from the returned value). fn get_provisional( &self, - fresh_trait_ref: ty::ConstnessAnd>, + fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option { debug!( - ?fresh_trait_ref, + ?fresh_trait_pred, "get_provisional = {:#?}", - self.map.borrow().get(&fresh_trait_ref), + self.map.borrow().get(&fresh_trait_pred), ); - Some(*self.map.borrow().get(&fresh_trait_ref)?) + Some(*self.map.borrow().get(&fresh_trait_pred)?) } /// Insert a provisional result into the cache. The result came /// from the node with the given DFN. It accessed a minimum depth - /// of `reached_depth` to compute. It evaluated `fresh_trait_ref` + /// of `reached_depth` to compute. It evaluated `fresh_trait_pred` /// and resulted in `result`. fn insert_provisional( &self, from_dfn: usize, reached_depth: usize, - fresh_trait_ref: ty::ConstnessAnd>, + fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, result: EvaluationResult, ) { - debug!(?from_dfn, ?fresh_trait_ref, ?result, "insert_provisional"); + debug!(?from_dfn, ?fresh_trait_pred, ?result, "insert_provisional"); let mut map = self.map.borrow_mut(); @@ -2528,7 +2507,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { } } - map.insert(fresh_trait_ref, ProvisionalEvaluation { from_dfn, reached_depth, result }); + map.insert(fresh_trait_pred, ProvisionalEvaluation { from_dfn, reached_depth, result }); } /// Invoked when the node with dfn `dfn` does not get a successful @@ -2579,16 +2558,16 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { fn on_completion( &self, dfn: usize, - mut op: impl FnMut(ty::ConstnessAnd>, EvaluationResult), + mut op: impl FnMut(ty::PolyTraitPredicate<'tcx>, EvaluationResult), ) { debug!(?dfn, "on_completion"); - for (fresh_trait_ref, eval) in + for (fresh_trait_pred, eval) in self.map.borrow_mut().drain_filter(|_k, eval| eval.from_dfn >= dfn) { - debug!(?fresh_trait_ref, ?eval, "on_completion"); + debug!(?fresh_trait_pred, ?eval, "on_completion"); - op(fresh_trait_ref, eval.result); + op(fresh_trait_pred, eval.result); } } } From a848c4ba3ff69c2cb0cb66a59dc37fd53bbcb70b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 25 Oct 2021 14:29:54 +0000 Subject: [PATCH 10/18] Avoid storing the ImplPolarity and Constness next to a TraitRef and use TraitPredicate instead --- compiler/rustc_infer/src/traits/util.rs | 8 ++-- compiler/rustc_middle/src/traits/select.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 6 +-- .../rustc_trait_selection/src/traits/mod.rs | 13 +++++-- .../src/traits/select/candidate_assembly.rs | 10 +++-- .../src/traits/select/confirmation.rs | 14 ++++--- .../src/traits/select/mod.rs | 38 +++++++++---------- .../src/traits/specialize/mod.rs | 6 +-- .../rustc_trait_selection/src/traits/util.rs | 8 ++-- .../rustc_trait_selection/src/traits/wf.rs | 5 ++- compiler/rustc_typeck/src/astconv/mod.rs | 2 +- 11 files changed, 59 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 92f74af4eb3eb..7e3cfbe2eba2d 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -328,8 +328,8 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>( )); for (super_predicate, _) in super_predicates.predicates { let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref); - if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() { - stack.push(binder.value); + if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() { + stack.push(binder.map_bound(|t| t.trait_ref)); } } @@ -362,8 +362,8 @@ impl<'tcx, I: Iterator>> Iterator for FilterToT fn next(&mut self) -> Option> { while let Some(obligation) = self.base_iterator.next() { - if let Some(data) = obligation.predicate.to_opt_poly_trait_ref() { - return Some(data.value); + if let Some(data) = obligation.predicate.to_opt_poly_trait_pred() { + return Some(data.map_bound(|t| t.trait_ref)); } } None diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index ff711bff86f61..71ee00c602a3d 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -101,7 +101,7 @@ pub enum SelectionCandidate<'tcx> { /// `false` if there are no *further* obligations. has_nested: bool, }, - ParamCandidate((ty::ConstnessAnd>, ty::ImplPolarity)), + ParamCandidate(ty::PolyTraitPredicate<'tcx>), ImplCandidate(DefId), AutoImplCandidate(DefId), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8e7eb46f26010..c5bbaf60069ad 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -885,12 +885,10 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { } impl<'tcx> Predicate<'tcx> { - pub fn to_opt_poly_trait_ref(self) -> Option>> { + pub fn to_opt_poly_trait_pred(self) -> Option> { let predicate = self.kind(); match predicate.skip_binder() { - PredicateKind::Trait(t) => { - Some(ConstnessAnd { constness: t.constness, value: predicate.rebind(t.trait_ref) }) - } + PredicateKind::Trait(t) => Some(predicate.rebind(t)), PredicateKind::Projection(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 36305429877a8..ba527341acc06 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -574,14 +574,17 @@ fn prepare_vtable_segments<'tcx, T>( .predicates .into_iter() .filter_map(move |(pred, _)| { - pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_ref() + pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_pred() }); 'diving_in_skip_visited_traits: loop { if let Some(next_super_trait) = direct_super_traits_iter.next() { if visited.insert(next_super_trait.to_predicate(tcx)) { + // We're throwing away potential constness of super traits here. + // FIXME: handle ~const super traits + let next_super_trait = next_super_trait.map_bound(|t| t.trait_ref); stack.push(( - next_super_trait.value, + next_super_trait, emit_vptr_on_new_entry, Some(direct_super_traits_iter), )); @@ -613,7 +616,11 @@ fn prepare_vtable_segments<'tcx, T>( if let Some(siblings) = siblings_opt { if let Some(next_inner_most_trait_ref) = siblings.next() { if visited.insert(next_inner_most_trait_ref.to_predicate(tcx)) { - *inner_most_trait_ref = next_inner_most_trait_ref.value; + // We're throwing away potential constness of super traits here. + // FIXME: handle ~const super traits + let next_inner_most_trait_ref = + next_inner_most_trait_ref.map_bound(|t| t.trait_ref); + *inner_most_trait_ref = next_inner_most_trait_ref; *emit_vptr = emit_vptr_on_new_entry; break 'exiting_out; } else { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 5a857676a20c8..d78fa24823151 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -383,17 +383,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .param_env .caller_bounds() .iter() - .filter_map(|o| o.to_opt_poly_trait_ref()); + .filter_map(|o| o.to_opt_poly_trait_pred()); // Micro-optimization: filter out predicates relating to different traits. let matching_bounds = - all_bounds.filter(|p| p.value.def_id() == stack.obligation.predicate.def_id()); + all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id()); // Keep only those bounds which may apply, and propagate overflow if it occurs. for bound in matching_bounds { - let wc = self.evaluate_where_clause(stack, bound.value)?; + // FIXME(oli-obk): it is suspicious that we are dropping the constness and + // polarity here. + let wc = self.evaluate_where_clause(stack, bound.map_bound(|t| t.trait_ref))?; if wc.may_apply() { - candidates.vec.push(ParamCandidate((bound, stack.obligation.polarity()))); + candidates.vec.push(ParamCandidate(bound)); } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 2f1f7971a7926..ec2ea2b8c940f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -58,8 +58,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ParamCandidate(param) => { - let obligations = self.confirm_param_candidate(obligation, param.0.value); - Ok(ImplSource::Param(obligations, param.0.constness)) + let obligations = + self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref)); + Ok(ImplSource::Param(obligations, param.skip_binder().constness)) } ImplCandidate(impl_def_id) => { @@ -139,7 +140,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let trait_predicate = self.infcx.shallow_resolve(obligation.predicate); let placeholder_trait_predicate = - self.infcx().replace_bound_vars_with_placeholders(trait_predicate); + self.infcx().replace_bound_vars_with_placeholders(trait_predicate).trait_ref; let placeholder_self_ty = placeholder_trait_predicate.self_ty(); let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate); let (def_id, substs) = match *placeholder_self_ty.kind() { @@ -150,8 +151,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let candidate_predicate = tcx.item_bounds(def_id)[idx].subst(tcx, substs); let candidate = candidate_predicate - .to_opt_poly_trait_ref() - .expect("projection candidate is not a trait predicate"); + .to_opt_poly_trait_pred() + .expect("projection candidate is not a trait predicate") + .map_bound(|t| t.trait_ref); let mut obligations = Vec::new(); let candidate = normalize_with_depth_to( self, @@ -165,7 +167,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations.extend(self.infcx.commit_if_ok(|_| { self.infcx .at(&obligation.cause, obligation.param_env) - .sup(placeholder_trait_predicate.to_poly_trait_ref(), candidate.value) + .sup(placeholder_trait_predicate, candidate) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| Unimplemented) })?); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 55fd38ac261dd..e1ab9bba45982 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1089,10 +1089,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplCandidate(def_id) if tcx.impl_constness(def_id) == hir::Constness::Const => {} // const param - ParamCandidate(( - ty::ConstnessAnd { constness: ty::BoundConstness::ConstIfConst, .. }, - _, - )) => {} + ParamCandidate(trait_pred) + if trait_pred.skip_binder().constness + == ty::BoundConstness::ConstIfConst => {} // auto trait impl AutoImplCandidate(..) => {} // generator, this will raise error in other places @@ -1474,7 +1473,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Check if a bound would previously have been removed when normalizing // the param_env so that it can be given the lowest priority. See // #50825 for the motivation for this. - let is_global = |cand: &ty::PolyTraitRef<'tcx>| { + let is_global = |cand: &ty::PolyTraitPredicate<'tcx>| { cand.is_global(self.infcx.tcx) && !cand.has_late_bound_regions() }; @@ -1507,25 +1506,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ConstDropCandidate, ) => false, - ( - ParamCandidate((other, other_polarity)), - ParamCandidate((victim, victim_polarity)), - ) => { - let same_except_bound_vars = other.value.skip_binder() - == victim.value.skip_binder() - && other.constness == victim.constness - && other_polarity == victim_polarity - && !other.value.skip_binder().has_escaping_bound_vars(); + (ParamCandidate(other), ParamCandidate(victim)) => { + let same_except_bound_vars = other.skip_binder().trait_ref + == victim.skip_binder().trait_ref + && other.skip_binder().constness == victim.skip_binder().constness + && other.skip_binder().polarity == victim.skip_binder().polarity + && !other.skip_binder().trait_ref.has_escaping_bound_vars(); if same_except_bound_vars { // See issue #84398. In short, we can generate multiple ParamCandidates which are // the same except for unused bound vars. Just pick the one with the fewest bound vars // or the current one if tied (they should both evaluate to the same answer). This is // probably best characterized as a "hack", since we might prefer to just do our // best to *not* create essentially duplicate candidates in the first place. - other.value.bound_vars().len() <= victim.value.bound_vars().len() - } else if other.value == victim.value - && victim.constness == ty::BoundConstness::NotConst - && other_polarity == victim_polarity + other.bound_vars().len() <= victim.bound_vars().len() + } else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref + && victim.skip_binder().constness == ty::BoundConstness::NotConst + && other.skip_binder().polarity == victim.skip_binder().polarity { // Drop otherwise equivalent non-const candidates in favor of const candidates. true @@ -1555,11 +1551,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | TraitAliasCandidate(..) | ObjectCandidate(_) | ProjectionCandidate(_), - ) => !is_global(&cand.0.value), + ) => !is_global(cand), (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => { // Prefer these to a global where-clause bound // (see issue #50825). - is_global(&cand.0.value) + is_global(cand) } ( ImplCandidate(_) @@ -1575,7 +1571,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) => { // Prefer these to a global where-clause bound // (see issue #50825). - is_global(&cand.0.value) && other.evaluation.must_apply_modulo_regions() + is_global(cand) && other.evaluation.must_apply_modulo_regions() } (ProjectionCandidate(i), ProjectionCandidate(j)) diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index b64c55592272e..ab732f510ff92 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -508,9 +508,9 @@ crate fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option TraitAliasExpander<'tcx> { let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { pred.subst_supertrait(tcx, &trait_ref) - .to_opt_poly_trait_ref() - .map(|trait_ref| item.clone_and_push(trait_ref.value, *span)) + .to_opt_poly_trait_pred() + .map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span)) }); debug!("expand_trait_aliases: items={:?}", items.clone()); @@ -183,8 +183,8 @@ impl Iterator for SupertraitDefIds<'tcx> { predicates .predicates .iter() - .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref()) - .map(|trait_ref| trait_ref.value.def_id()) + .filter_map(|(pred, _)| pred.to_opt_poly_trait_pred()) + .map(|trait_ref| trait_ref.def_id()) .filter(|&super_def_id| visited.insert(super_def_id)), ); Some(def_id) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 2a66684e2a2a0..664dd861612b1 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -298,9 +298,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let extend = |obligation: traits::PredicateObligation<'tcx>| { let mut cause = cause.clone(); - if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() { + if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_pred() { let derived_cause = traits::DerivedObligationCause { - parent_trait_ref: parent_trait_ref.value, + // TODO: sus + parent_trait_ref: parent_trait_ref.map_bound(|t| t.trait_ref), parent_code: Lrc::new(obligation.cause.code.clone()), }; cause.make_mut().code = diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index da751f2075399..b532a6b118f06 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1588,7 +1588,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { traits::transitive_bounds_that_define_assoc_type( tcx, predicates.iter().filter_map(|(p, _)| { - p.to_opt_poly_trait_ref().map(|trait_ref| trait_ref.value) + Some(p.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref)) }), assoc_name, ) From a9a79f657c4a6b86483f3c1165e6f0ebbf77c927 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 25 Oct 2021 15:58:41 +0000 Subject: [PATCH 11/18] Completely remove ConstnessAnd --- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- compiler/rustc_infer/src/traits/engine.rs | 2 +- compiler/rustc_infer/src/traits/util.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 40 ++++--------------- compiler/rustc_middle/src/ty/relate.rs | 13 ------ compiler/rustc_middle/src/ty/sty.rs | 4 +- .../rustc_trait_selection/src/autoderef.rs | 2 +- compiler/rustc_trait_selection/src/infer.rs | 1 - .../src/traits/error_reporting/mod.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 2 +- .../rustc_trait_selection/src/traits/mod.rs | 3 +- .../src/traits/object_safety.rs | 2 +- .../src/traits/project.rs | 2 +- .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/confirmation.rs | 2 +- .../rustc_trait_selection/src/traits/util.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 2 +- compiler/rustc_ty_utils/src/ty.rs | 4 +- compiler/rustc_typeck/src/bounds.rs | 2 +- compiler/rustc_typeck/src/check/method/mod.rs | 2 +- .../rustc_typeck/src/check/method/probe.rs | 2 +- .../rustc_typeck/src/check/method/suggest.rs | 2 +- compiler/rustc_typeck/src/check/wfcheck.rs | 1 - compiler/rustc_typeck/src/collect.rs | 2 +- 24 files changed, 28 insertions(+), 72 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index da26d9c7b8779..d90154f164386 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -31,7 +31,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts}; use rustc_middle::ty::{ self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid, - ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness, + ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, }; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::{Span, DUMMY_SP}; diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index d9ef60d3bfc95..2f56158278820 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -2,7 +2,7 @@ use crate::infer::InferCtxt; use crate::traits::Obligation; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, ToPredicate, Ty, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty}; use super::FulfillmentError; use super::{ObligationCause, PredicateObligation}; diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 7e3cfbe2eba2d..61588147364a9 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -3,7 +3,7 @@ use smallvec::smallvec; use crate::infer::outlives::components::{push_outlives_components, Component}; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, TyCtxt}; use rustc_span::symbol::Ident; use rustc_span::Span; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c5bbaf60069ad..8031eb8a1ec20 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -846,20 +846,6 @@ impl ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { } } -impl<'tcx> ToPredicate<'tcx> for ConstnessAnd> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.value - .map_bound(|trait_ref| { - PredicateKind::Trait(ty::TraitPredicate { - trait_ref, - constness: self.constness, - polarity: ty::ImplPolarity::Positive, - }) - }) - .to_predicate(tcx) - } -} - impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(PredicateKind::Trait).to_predicate(tcx) @@ -1391,33 +1377,23 @@ impl<'tcx> ParamEnv<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] -pub struct ConstnessAnd { - pub constness: BoundConstness, - pub value: T, -} - // FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that // the constness of trait bounds is being propagated correctly. -pub trait WithConstness: Sized { - #[inline] - fn with_constness(self, constness: BoundConstness) -> ConstnessAnd { - ConstnessAnd { constness, value: self } - } - +impl PolyTraitRef<'tcx> { #[inline] - fn with_const_if_const(self) -> ConstnessAnd { - self.with_constness(BoundConstness::ConstIfConst) + pub fn with_constness(self, constness: BoundConstness) -> PolyTraitPredicate<'tcx> { + self.map_bound(|trait_ref| ty::TraitPredicate { + trait_ref, + constness, + polarity: ty::ImplPolarity::Positive, + }) } - #[inline] - fn without_const(self) -> ConstnessAnd { + pub fn without_const(self) -> PolyTraitPredicate<'tcx> { self.with_constness(BoundConstness::NotConst) } } -impl WithConstness for T {} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] pub struct ParamEnvAnd<'tcx, T> { pub param_env: ParamEnv<'tcx>, diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index c7d8bec506f6b..b6aadf27bb08b 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -218,19 +218,6 @@ impl<'tcx> Relate<'tcx> for ty::BoundConstness { } } -impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::ConstnessAnd { - fn relate>( - relation: &mut R, - a: ty::ConstnessAnd, - b: ty::ConstnessAnd, - ) -> RelateResult<'tcx, ty::ConstnessAnd> { - Ok(ty::ConstnessAnd { - constness: relation.relate(a.constness, b.constness)?, - value: relation.relate(a.value, b.value)?, - }) - } -} - impl<'tcx> Relate<'tcx> for ast::Unsafety { fn relate>( relation: &mut R, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index fcbf15b3bca47..29ba75e1a7dad 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -8,9 +8,7 @@ use crate::infer::canonical::Canonical; use crate::ty::fold::ValidateBoundVars; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::InferTy::{self, *}; -use crate::ty::{ - self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness, -}; +use crate::ty::{self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable}; use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS}; use polonius_engine::Atom; use rustc_data_structures::captures::Captures; diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 4c80483fc1f1e..46c74660f86a1 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -3,7 +3,7 @@ use crate::traits::{self, TraitEngine}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_infer::infer::InferCtxt; -use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, WithConstness}; +use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt}; use rustc_middle::ty::{ToPredicate, TypeFoldable}; use rustc_session::{DiagnosticMessageId, Limit}; use rustc_span::def_id::LOCAL_CRATE; diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 70816b5722b2d..f135f0c1b13d2 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -9,7 +9,6 @@ use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, Quer use rustc_middle::traits::query::Fallible; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::ToPredicate; -use rustc_middle::ty::WithConstness; use rustc_middle::ty::{self, Ty, TypeFoldable}; use rustc_span::{Span, DUMMY_SP}; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 866bcde1bfd4f..37d42e84cde88 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -24,7 +24,7 @@ use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{ self, fast_reject, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, - TypeFoldable, WithConstness, + TypeFoldable, }; use rustc_session::DiagnosticMessageId; use rustc_span::symbol::{kw, sym}; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index a90140a9b50b9..af0a39b239fc4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -21,7 +21,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node}; use rustc_middle::ty::{ self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree, - Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, + Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, }; use rustc_middle::ty::{TypeAndMut, TypeckResults}; use rustc_session::Limit; diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index ba527341acc06..d81b6949cae62 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -33,8 +33,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::{ - self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness, - COMMON_VTABLE_ENTRIES, + self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, COMMON_VTABLE_ENTRIES, }; use rustc_span::{sym, Span}; use smallvec::SmallVec; diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 616efffd999ec..412f7923fb586 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -18,7 +18,7 @@ use rustc_errors::FatalError; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, Subst}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor, WithConstness}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_middle::ty::{Predicate, ToPredicate}; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; use rustc_span::symbol::Symbol; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 0911b2c529ab2..26398bfd81000 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -27,7 +27,7 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::sym; use std::collections::BTreeMap; diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index d78fa24823151..89c01fe34400d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -11,7 +11,7 @@ use rustc_infer::traits::TraitEngine; use rustc_infer::traits::{Obligation, SelectionError, TraitObligation}; use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable}; use rustc_target::spec::abi::Abi; use crate::traits; diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index ec2ea2b8c940f..e9b368f683e5b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -13,7 +13,7 @@ use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; use rustc_middle::ty::{self, Ty}; -use rustc_middle::ty::{ToPolyTraitRef, ToPredicate, WithConstness}; +use rustc_middle::ty::{ToPolyTraitRef, ToPredicate}; use rustc_span::def_id::DefId; use crate::traits::project::{normalize_with_depth, normalize_with_depth_to}; diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index bc3da12b22e45..5577e98e89321 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -6,7 +6,7 @@ use smallvec::SmallVec; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef}; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext}; pub use rustc_infer::traits::{self, util::*}; diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 664dd861612b1..2197dcc048641 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -6,7 +6,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; use std::iter; diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 4bcc80c83022e..9a4639b088600 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -2,9 +2,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{ - self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness, -}; +use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; use rustc_trait_selection::traits; diff --git a/compiler/rustc_typeck/src/bounds.rs b/compiler/rustc_typeck/src/bounds.rs index 24474e163b9da..8bc3a48e5b506 100644 --- a/compiler/rustc_typeck/src/bounds.rs +++ b/compiler/rustc_typeck/src/bounds.rs @@ -1,7 +1,7 @@ //! Bounds are restrictions applied to some types after they've been converted into the //! `ty` form from the HIR. -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; /// Collects together a list of type bounds. These lists of bounds occur in many places diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index dbc1d4ec19377..03518dc8d127e 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -22,7 +22,7 @@ use rustc_infer::infer::{self, InferOk}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable}; use rustc_span::symbol::Ident; use rustc_span::Span; use rustc_trait_selection::traits; diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 9fd7e8c4daa20..9f9f0df97a894 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -21,7 +21,7 @@ use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_middle::middle::stability; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::lev_distance::{find_best_match_for_name, lev_distance}; diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index ca174ed5e8497..6a3ce2132f815 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -12,7 +12,7 @@ use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::ty::fast_reject::simplify_type; use rustc_middle::ty::print::with_crate_prefix; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_span::lev_distance; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{source_map, FileName, MultiSpan, Span, Symbol}; diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 78088b9bd0c38..9f6a411f24ba3 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -21,7 +21,6 @@ use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst}; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitor, - WithConstness, }; use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Ident, Symbol}; diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 39fac12e29743..19dcdbdff22a0 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -41,7 +41,7 @@ use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::Discr; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, Ty, TyCtxt}; -use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness}; +use rustc_middle::ty::{ReprOptions, ToPredicate}; use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Ident, Symbol}; From f394bb57bb800be024e95e624d96bc698e04dde3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 25 Oct 2021 16:49:39 +0000 Subject: [PATCH 12/18] Always use const param envs for const eval. Nothing else makes sense, and there is no "danger" in doing so, as it only does something if there are const bounds, which are unstable. This used to happen implicitly via the inferctxt before, which was much more fragile. --- compiler/rustc_const_eval/src/const_eval/eval_queries.rs | 3 +++ compiler/rustc_const_eval/src/interpret/eval_context.rs | 1 + compiler/rustc_hir/src/hir.rs | 1 + compiler/rustc_middle/src/mir/interpret/queries.rs | 2 ++ compiler/rustc_middle/src/ty/mod.rs | 5 +++++ 5 files changed, 12 insertions(+) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 6d3a89c0a8a5b..c5412affafe23 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -7,6 +7,7 @@ use crate::interpret::{ }; use rustc_errors::ErrorReported; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; @@ -215,6 +216,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> { + assert!(key.param_env.constness() == hir::Constness::Const); // see comment in eval_to_allocation_raw_provider for what we're doing here if key.param_env.reveal() == Reveal::All { let mut key = key; @@ -249,6 +251,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> { + assert!(key.param_env.constness() == hir::Constness::Const); // Because the constant is computed twice (once per value of `Reveal`), we are at risk of // reporting the same error twice here. To resolve this, we check whether we can evaluate the // constant in the more restrictive `Reveal::UserFacing`, which most likely already was diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index cf084faade8cc..6206deb211533 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -918,6 +918,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else { self.param_env }; + let param_env = param_env.with_const(); let val = self.tcx.eval_to_allocation_raw(param_env.and(gid))?; self.raw_const_to_mplace(val) } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2b4403b37ffc4..1446c84a39768 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3248,6 +3248,7 @@ impl<'hir> Node<'hir> { Node::Item(Item { kind: ItemKind::Const(..), .. }) | Node::Item(Item { kind: ItemKind::Static(..), .. }) | Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. }) + | Node::AnonConst(_) | Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const, _ => Constness::NotConst, diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index c63613ae3af29..f983185563315 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -64,6 +64,7 @@ impl<'tcx> TyCtxt<'tcx> { cid: GlobalId<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { + let param_env = param_env.with_const(); // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. let inputs = self.erase_regions(param_env.and(cid)); @@ -92,6 +93,7 @@ impl<'tcx> TyCtxt<'tcx> { gid: GlobalId<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Result<&'tcx mir::Allocation, ErrorHandled> { + let param_env = param_env.with_const(); trace!("eval_to_allocation: Need to compute {:?}", gid); let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?; Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory()) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8031eb8a1ec20..896e56026188f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1323,6 +1323,11 @@ impl<'tcx> ParamEnv<'tcx> { self } + pub fn with_const(mut self) -> Self { + self.packed.set_tag(ParamTag { constness: hir::Constness::Const, ..self.packed.tag() }); + self + } + /// Returns a new parameter environment with the same clauses, but /// which "reveals" the true results of projections in all cases /// (even for associated types that are specializable). This is From fdf5322169e85d9c5caaff6359d71f182afa202b Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 29 Nov 2021 20:42:16 +0800 Subject: [PATCH 13/18] Fix tools --- compiler/rustc_middle/src/traits/util.rs | 4 ++-- compiler/rustc_middle/src/ty/mod.rs | 4 ++-- src/librustdoc/clean/blanket_impl.rs | 5 +++-- src/tools/clippy/clippy_lints/src/future_not_send.rs | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs index 3490c6881704a..815f4824bc134 100644 --- a/compiler/rustc_middle/src/traits/util.rs +++ b/compiler/rustc_middle/src/traits/util.rs @@ -26,9 +26,9 @@ impl<'tcx> Elaborator<'tcx> { .predicates .into_iter() .flat_map(|(pred, _)| { - pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_ref() + pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_pred() }) - .map(|t| t.value) + .map(|t| t.map_bound(|pred| pred.trait_ref)) .filter(|supertrait_ref| self.visited.insert(*supertrait_ref)); self.stack.extend(supertrait_refs); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 896e56026188f..da4a414d7cbe1 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1257,11 +1257,11 @@ impl<'a, 'tcx> HashStable> for ParamEnv<'tcx> { impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> { fn super_fold_with>(self, folder: &mut F) -> Result { - ParamEnv::new( + Ok(ParamEnv::new( self.caller_bounds().fold_with(folder)?, self.reveal().fold_with(folder)?, self.constness().fold_with(folder)?, - ) + )) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index f44589f60675f..7ca5cb4bd4279 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -3,7 +3,7 @@ use rustc_hir as hir; use rustc_infer::infer::{InferOk, TyCtxtInferExt}; use rustc_infer::traits; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{ToPredicate, WithConstness}; +use rustc_middle::ty::ToPredicate; use rustc_span::DUMMY_SP; use super::*; @@ -66,7 +66,8 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .into_iter() .chain(Some( ty::Binder::dummy(trait_ref) - .without_const() + .to_poly_trait_predicate() + .map_bound(ty::PredicateKind::Trait) .to_predicate(infcx.tcx), )); for predicate in predicates { diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index 6b2ac985555dc..a9297adb426a2 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -67,8 +67,8 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { let mut is_future = false; for &(p, _span) in preds { let p = p.subst(cx.tcx, subst); - if let Some(trait_ref) = p.to_opt_poly_trait_ref() { - if Some(trait_ref.value.def_id()) == cx.tcx.lang_items().future_trait() { + if let Some(trait_pred) = p.to_opt_poly_trait_pred() { + if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() { is_future = true; break; } From 8710a2e169a6b008734b75f3f86f79d93319fbfd Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 29 Nov 2021 21:12:53 +0800 Subject: [PATCH 14/18] Reformat everything --- compiler/rustc_infer/src/traits/engine.rs | 6 ++---- compiler/rustc_middle/src/ty/mod.rs | 5 ++++- .../rustc_trait_selection/src/traits/select/mod.rs | 5 +---- compiler/rustc_typeck/src/check/compare_method.rs | 3 +-- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 10 ++-------- src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs | 2 +- 6 files changed, 11 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 2f56158278820..822f2365e023f 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -47,10 +47,8 @@ pub trait TraitEngine<'tcx>: 'tcx { fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec>; - fn select_where_possible( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - ) -> Vec>; + fn select_where_possible(&mut self, infcx: &InferCtxt<'_, 'tcx>) + -> Vec>; fn pending_obligations(&self) -> Vec>; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index da4a414d7cbe1..72191bce4c701 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1256,7 +1256,10 @@ impl<'a, 'tcx> HashStable> for ParamEnv<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Result { + fn super_fold_with>( + self, + folder: &mut F, + ) -> Result { Ok(ParamEnv::new( self.caller_bounds().fold_with(folder)?, self.reveal().fold_with(folder)?, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index e1ab9bba45982..dde4529a21b27 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2144,10 +2144,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { previous_stack: TraitObligationStackList<'o, 'tcx>, obligation: &'o TraitObligation<'tcx>, ) -> TraitObligationStack<'o, 'tcx> { - let fresh_trait_pred = obligation - .predicate - .fold_with(&mut self.freshener) - .into_ok(); + let fresh_trait_pred = obligation.predicate.fold_with(&mut self.freshener).into_ok(); let dfn = previous_stack.cache.next_dfn(); let depth = previous_stack.depth() + 1; diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 8141950ee8ddd..7ce4c476d3a6c 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -1432,8 +1432,7 @@ pub fn check_type_bounds<'tcx>( // Check that all obligations are satisfied by the implementation's // version. - let errors = - inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); + let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); if !errors.is_empty() { infcx.report_fulfillment_errors(&errors, None, false); return Err(ErrorReported); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 58a2f21d22e67..6dbcf3c3c6edc 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -610,10 +610,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(skip(self), level = "debug")] pub(in super::super) fn select_all_obligations_or_error(&self) { - let errors = self - .fulfillment_cx - .borrow_mut() - .select_all_or_error(&self); + let errors = self.fulfillment_cx.borrow_mut().select_all_or_error(&self); if !errors.is_empty() { self.report_fulfillment_errors(&errors, self.inh.body_id, false); @@ -626,10 +623,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fallback_has_occurred: bool, mutate_fulfillment_errors: impl Fn(&mut Vec>), ) { - let mut result = self - .fulfillment_cx - .borrow_mut() - .select_where_possible(self); + let mut result = self.fulfillment_cx.borrow_mut().select_where_possible(self); if !result.is_empty() { mutate_fulfillment_errors(&mut result); self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred); diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs index 321cea0d4154a..11334c1077548 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs @@ -28,4 +28,4 @@ impl const Baz for NonConstAdd { type Qux = NonConstAdd; // OK } -fn main() {} \ No newline at end of file +fn main() {} From 87cd1ce6c149c002e158e29cee9ff863073c5412 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 29 Nov 2021 22:21:38 +0800 Subject: [PATCH 15/18] `ParamEnv` should be const when `ImplItem` is within a const impl. --- compiler/rustc_hir/src/hir.rs | 27 ------------- compiler/rustc_ty_utils/src/ty.rs | 38 ++++++++++++++++++- .../rfc-2632-const-trait-impl/assoc-type.rs | 3 +- .../assoc-type.stderr | 20 ++++++++++ 4 files changed, 58 insertions(+), 30 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 1446c84a39768..ca60b91fae0d7 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3228,33 +3228,6 @@ impl<'hir> Node<'hir> { } } - /// Returns `Constness::Const` when this node is a const fn/impl/item. - pub fn constness_for_typeck(&self) -> Constness { - match self { - Node::Item(Item { - kind: ItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), - .. - }) - | Node::TraitItem(TraitItem { - kind: TraitItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), - .. - }) - | Node::ImplItem(ImplItem { - kind: ImplItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), - .. - }) - | Node::Item(Item { kind: ItemKind::Impl(Impl { constness, .. }), .. }) => *constness, - - Node::Item(Item { kind: ItemKind::Const(..), .. }) - | Node::Item(Item { kind: ItemKind::Static(..), .. }) - | Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. }) - | Node::AnonConst(_) - | Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const, - - _ => Constness::NotConst, - } - } - pub fn as_owner(self) -> Option> { match self { Node::Item(i) => Some(OwnerNode::Item(i)), diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 9a4639b088600..f47f8a562ddf8 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -287,7 +287,43 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { 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) => tcx.hir().get(hir_id).constness_for_typeck(), + Some(hir_id) => match tcx.hir().get(hir_id) { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. }) + | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }) + | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Const(..), .. }) + | hir::Node::AnonConst(_) + | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) + | hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness: hir::Constness::Const, .. }, .. }, ..), + .. + }) => hir::Constness::Const, + + hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::TyAlias(..) | hir::ImplItemKind::Fn(..), + .. + }) => { + let parent_hir_id = tcx.hir().get_parent_node(hir_id); + match tcx.hir().get(parent_hir_id) { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), .. }) => *constness, + _ => span_bug!( + tcx.def_span(parent_hir_id.owner), + "impl item's parent node is not an impl", + ), + } + } + + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), + .. + }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), + .. + }) + | hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), .. }) => *constness, + + _ => hir::Constness::NotConst, + }, None => hir::Constness::NotConst, }; diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs index 11334c1077548..7b012083c5a3d 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs @@ -1,6 +1,5 @@ // FIXME(fee1-dead): this should have a better error message #![feature(const_trait_impl)] -// check-pass struct NonConstAdd(i32); impl std::ops::Add for NonConstAdd { @@ -17,7 +16,7 @@ trait Foo { impl const Foo for NonConstAdd { type Bar = NonConstAdd; - //TODO: ~^ ERROR + //~^ ERROR } trait Baz { diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr new file mode 100644 index 0000000000000..d1e55e12d6f50 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr @@ -0,0 +1,20 @@ +error[E0277]: cannot add `NonConstAdd` to `NonConstAdd` + --> $DIR/assoc-type.rs:18:5 + | +LL | type Bar = NonConstAdd; + | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `NonConstAdd + NonConstAdd` + | + = help: the trait `Add` is not implemented for `NonConstAdd` +note: required by a bound in `Foo::Bar` + --> $DIR/assoc-type.rs:14:15 + | +LL | type Bar: ~const std::ops::Add; + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar` +help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement + | +LL | impl const Foo for NonConstAdd where NonConstAdd: Add { + | ++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 6b07cec05c614c34d211cff23f738f03d3026ae8 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 1 Dec 2021 23:22:42 +0800 Subject: [PATCH 16/18] Cache with consistent env and bound --- compiler/rustc_middle/src/ty/mod.rs | 18 +++++++++++++ .../src/traits/select/mod.rs | 26 +++++++++++++------ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 72191bce4c701..cd60519ac3424 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -230,6 +230,19 @@ pub enum BoundConstness { ConstIfConst, } +impl BoundConstness { + /// Reduce `self` and `constness` to two possible combined states instead of four. + pub fn and(&mut self, constness: hir::Constness) -> hir::Constness { + match (constness, self) { + (hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const, + (_, this) => { + *this = BoundConstness::NotConst; + hir::Constness::NotConst + } + } + } +} + impl fmt::Display for BoundConstness { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -1326,6 +1339,11 @@ impl<'tcx> ParamEnv<'tcx> { self } + pub fn with_constness(mut self, constness: hir::Constness) -> Self { + self.packed.set_tag(ParamTag { constness, ..self.packed.tag() }); + self + } + pub fn with_const(mut self) -> Self { self.packed.set_tag(ParamTag { constness: hir::Constness::Const, ..self.packed.tag() }); self diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index dde4529a21b27..dd62411cb8e50 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -675,11 +675,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } let stack = self.push_stack(previous_stack, &obligation); - let fresh_trait_pred = stack.fresh_trait_pred; + let mut fresh_trait_pred = stack.fresh_trait_pred; + let mut param_env = obligation.param_env; + + fresh_trait_pred = fresh_trait_pred.map_bound(|mut pred| { + param_env = param_env.with_constness(pred.constness.and(param_env.constness())); + pred + }); debug!(?fresh_trait_pred); - if let Some(result) = self.check_evaluation_cache(obligation.param_env, fresh_trait_pred) { + if let Some(result) = self.check_evaluation_cache(param_env, fresh_trait_pred) { debug!(?result, "CACHE HIT"); return Ok(result); } @@ -709,11 +715,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let reached_depth = stack.reached_depth.get(); if reached_depth >= stack.depth { debug!(?result, "CACHE MISS"); - self.insert_evaluation_cache(obligation.param_env, fresh_trait_pred, dep_node, result); + self.insert_evaluation_cache(param_env, fresh_trait_pred, dep_node, result); stack.cache().on_completion(stack.dfn, |fresh_trait_pred, provisional_result| { self.insert_evaluation_cache( - obligation.param_env, + param_env, fresh_trait_pred, dep_node, provisional_result.max(result), @@ -1200,7 +1206,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn check_candidate_cache( &mut self, - param_env: ty::ParamEnv<'tcx>, + mut param_env: ty::ParamEnv<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option>> { // Neither the global nor local cache is aware of intercrate @@ -1211,7 +1217,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return None; } let tcx = self.tcx(); - let pred = cache_fresh_trait_pred.skip_binder(); + let mut pred = cache_fresh_trait_pred.skip_binder(); + param_env = param_env.with_constness(pred.constness.and(param_env.constness())); + if self.can_use_global_caches(param_env) { if let Some(res) = tcx.selection_cache.get(¶m_env.and(pred), tcx) { return Some(res); @@ -1255,13 +1263,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn insert_candidate_cache( &mut self, - param_env: ty::ParamEnv<'tcx>, + mut param_env: ty::ParamEnv<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, dep_node: DepNodeIndex, candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>, ) { let tcx = self.tcx(); - let pred = cache_fresh_trait_pred.skip_binder(); + let mut pred = cache_fresh_trait_pred.skip_binder(); + + param_env = param_env.with_constness(pred.constness.and(param_env.constness())); if !self.can_cache_candidate(&candidate) { debug!(?pred, ?candidate, "insert_candidate_cache - candidate is not cacheable"); From b64c40bc6f4ced6e418fe89d6754c86e5841f714 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 1 Dec 2021 23:32:36 +0800 Subject: [PATCH 17/18] TODO => FIXME --- compiler/rustc_trait_selection/src/traits/wf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 2197dcc048641..5875b764e9f36 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -300,7 +300,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let mut cause = cause.clone(); if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_pred() { let derived_cause = traits::DerivedObligationCause { - // TODO: sus + // FIXME(fee1-dead): when improving error messages, change this to PolyTraitPredicate parent_trait_ref: parent_trait_ref.map_bound(|t| t.trait_ref), parent_code: Lrc::new(obligation.cause.code.clone()), }; From 5ebc99e5b29a36150dfe090b4ac17d241debfb36 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Wed, 1 Dec 2021 23:33:37 +0800 Subject: [PATCH 18/18] Format --- compiler/rustc_ty_utils/src/ty.rs | 32 +++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index f47f8a562ddf8..c20c81e41cc4d 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -290,11 +290,20 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { Some(hir_id) => match tcx.hir().get(hir_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. }) | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }) - | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Const(..), .. }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(..), .. + }) | hir::Node::AnonConst(_) | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) | hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness: hir::Constness::Const, .. }, .. }, ..), + kind: + hir::ImplItemKind::Fn( + hir::FnSig { + header: hir::FnHeader { constness: hir::Constness::Const, .. }, + .. + }, + .., + ), .. }) => hir::Constness::Const, @@ -304,7 +313,10 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { }) => { let parent_hir_id = tcx.hir().get_parent_node(hir_id); match tcx.hir().get(parent_hir_id) { - hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), .. }) => *constness, + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + }) => *constness, _ => span_bug!( tcx.def_span(parent_hir_id.owner), "impl item's parent node is not an impl", @@ -313,14 +325,22 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { } hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), + kind: + hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), .. }) | hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), + kind: + hir::TraitItemKind::Fn( + hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, + .., + ), .. }) - | hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), .. }) => *constness, + | hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + }) => *constness, _ => hir::Constness::NotConst, },