From bc0156baceed60a4dbfd063554e66bc69b3b0bd4 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 2 Aug 2021 08:47:15 +0200 Subject: [PATCH] shrink `ty::PredicateKind` again --- compiler/rustc_infer/src/infer/mod.rs | 4 +-- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/consts/kind.rs | 29 +++++++++++++++---- compiler/rustc_middle/src/ty/flags.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 4 +-- compiler/rustc_middle/src/ty/relate.rs | 2 +- .../rustc_middle/src/ty/structural_impls.rs | 25 ++++++++++++++++ compiler/rustc_query_impl/src/keys.rs | 2 +- .../src/traits/const_evaluatable.rs | 10 +++---- .../src/traits/fulfill.rs | 2 +- .../src/traits/select/mod.rs | 2 +- compiler/rustc_typeck/src/collect.rs | 6 ++-- 12 files changed, 68 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 7f890829e68..bc98a3aa3f9 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -675,8 +675,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// canonicalizing the consts. pub fn try_unify_abstract_consts( &self, - a: ty::Unevaluated<'tcx>, - b: ty::Unevaluated<'tcx>, + a: ty::Unevaluated<'tcx, ()>, + b: ty::Unevaluated<'tcx, ()>, ) -> bool { let canonical = self.canonicalize_query((a, b), &mut OriginalQueryValues::default()); debug!("canonical consts: {:?}", &canonical.value); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 9b3de6710ec..f8e0d910a54 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -303,7 +303,7 @@ } query try_unify_abstract_consts(key: ( - ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx> + ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()> )) -> bool { desc { |tcx| "trying to unify the generic constants {} and {}", diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index b1f6a612776..e6a6b7f8556 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,4 +1,5 @@ use std::convert::TryInto; +use std::fmt; use crate::mir::interpret::{AllocId, ConstValue, Scalar}; use crate::mir::Promoted; @@ -20,20 +21,38 @@ /// so refer to that check for more info. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] #[derive(Hash, HashStable)] -pub struct Unevaluated<'tcx> { +pub struct Unevaluated<'tcx, P = Option> { pub def: ty::WithOptConstParam, pub substs_: Option>, - pub promoted: Option, + pub promoted: P, } impl<'tcx> Unevaluated<'tcx> { - pub fn new(def: ty::WithOptConstParam, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx> { - Unevaluated { def, substs_: Some(substs), promoted: None } + pub fn shrink(self) -> Unevaluated<'tcx, ()> { + debug_assert_eq!(self.promoted, None); + Unevaluated { def: self.def, substs_: self.substs_, promoted: () } } +} + +impl<'tcx> Unevaluated<'tcx, ()> { + pub fn expand(self) -> Unevaluated<'tcx> { + Unevaluated { def: self.def, substs_: self.substs_, promoted: None } + } +} + +impl<'tcx, P: Default> Unevaluated<'tcx, P> { + pub fn new(def: ty::WithOptConstParam, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> { + Unevaluated { def, substs_: Some(substs), promoted: Default::default() } + } +} +impl<'tcx, P: Default + PartialEq + fmt::Debug> Unevaluated<'tcx, P> { pub fn substs(self, tcx: TyCtxt<'tcx>) -> SubstsRef<'tcx> { self.substs_.unwrap_or_else(|| { - debug_assert_eq!(self.promoted, None); + // We must not use the parents default substs for promoted constants + // as that can result in incorrect substs and calls the `default_anon_const_substs` + // for something that might not actually be a constant. + debug_assert_eq!(self.promoted, Default::default()); tcx.default_anon_const_substs(self.def.did) }) } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 1c4f24cdf39..763da7e82c8 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -310,7 +310,7 @@ fn add_const(&mut self, c: &ty::Const<'_>) { } } - fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) { + fn add_unevaluated_const

(&mut self, ct: ty::Unevaluated<'tcx, P>) { if let Some(substs) = ct.substs_ { self.add_substs(substs); } else { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index b1ebe43c491..8f814a84b49 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -406,7 +406,7 @@ pub fn has_name(&self) -> bool { } #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(PredicateInner<'_>, 56); +static_assert_size!(PredicateInner<'_>, 48); #[derive(Clone, Copy, Lift)] pub struct Predicate<'tcx> { @@ -502,7 +502,7 @@ pub enum PredicateKind<'tcx> { Coerce(CoercePredicate<'tcx>), /// Constant initializer must evaluate successfully. - ConstEvaluatable(ty::Unevaluated<'tcx>), + ConstEvaluatable(ty::Unevaluated<'tcx, ()>), /// Constants must be equal. The first component is the const that is expected. ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>), diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index b64d507e0b8..4a2c8349fdc 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -579,7 +579,7 @@ pub fn super_relate_consts>( (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if tcx.features().const_evaluatable_checked => { - tcx.try_unify_abstract_consts((au, bu)) + tcx.try_unify_abstract_consts((au.shrink(), bu.shrink())) } // While this is slightly incorrect, it shouldn't matter for `min_const_generics` diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 31088423efa..2ab25c83970 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -1105,3 +1105,28 @@ fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow } } } + +impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> { + fn super_fold_with>(self, folder: &mut F) -> Self { + ty::Unevaluated { + def: self.def, + substs_: Some(self.substs(folder.tcx()).fold_with(folder)), + promoted: self.promoted, + } + } + + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + visitor.visit_unevaluated_const(self.expand()) + } + + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { + if let Some(tcx) = visitor.tcx_for_anon_const_substs() { + self.substs(tcx).visit_with(visitor) + } else if let Some(substs) = self.substs_ { + substs.visit_with(visitor) + } else { + debug!("ignoring default substs of `{:?}`", self.def); + ControlFlow::CONTINUE + } + } +} diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 8523737f8db..d85f1c04524 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -217,7 +217,7 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span { } } -impl<'tcx> Key for (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx>) { +impl<'tcx> Key for (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>) { #[inline(always)] fn query_crate_is_local(&self) -> bool { (self.0).def.did.krate == LOCAL_CRATE diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 80c824565d2..d75408ed820 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -29,7 +29,7 @@ /// Check if a given constant can be evaluated. pub fn is_const_evaluatable<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, - uv: ty::Unevaluated<'tcx>, + uv: ty::Unevaluated<'tcx, ()>, param_env: ty::ParamEnv<'tcx>, span: Span, ) -> Result<(), NotConstEvaluatable> { @@ -149,7 +149,7 @@ enum FailureKind { // and hopefully soon change this to an error. // // See #74595 for more details about this. - let concrete = infcx.const_eval_resolve(param_env, uv, Some(span)); + let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span)); if concrete.is_ok() && uv.substs(infcx.tcx).has_param_types_or_consts(infcx.tcx) { match infcx.tcx.def_kind(uv.def.did) { @@ -194,7 +194,7 @@ pub struct AbstractConst<'tcx> { impl<'tcx> AbstractConst<'tcx> { pub fn new( tcx: TyCtxt<'tcx>, - uv: ty::Unevaluated<'tcx>, + uv: ty::Unevaluated<'tcx, ()>, ) -> Result>, ErrorReported> { let inner = tcx.mir_abstract_const_opt_const_arg(uv.def)?; debug!("AbstractConst::new({:?}) = {:?}", uv, inner); @@ -206,7 +206,7 @@ pub fn from_const( ct: &ty::Const<'tcx>, ) -> Result>, ErrorReported> { match ct.val { - ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv), + ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()), ty::ConstKind::Error(_) => Err(ErrorReported), _ => Ok(None), } @@ -556,7 +556,7 @@ pub(super) fn mir_abstract_const<'tcx>( pub(super) fn try_unify_abstract_consts<'tcx>( tcx: TyCtxt<'tcx>, - (a, b): (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx>), + (a, b): (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>), ) -> bool { (|| { if let Some(a) = AbstractConst::new(tcx, a)? { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index a17921ace30..f214930c57f 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -580,7 +580,7 @@ fn progress_changed_obligations( if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = (c1.val, c2.val) { - if infcx.try_unify_abstract_consts(a, b) { + if infcx.try_unify_abstract_consts(a.shrink(), b.shrink()) { return ProcessResult::Changed(vec![]); } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 6ddc3aad1b5..756646c2d88 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -623,7 +623,7 @@ fn evaluate_predicate_recursively<'o>( if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = (c1.val, c2.val) { - if self.infcx.try_unify_abstract_consts(a, b) { + if self.infcx.try_unify_abstract_consts(a.shrink(), b.shrink()) { return Ok(EvaluatedToOk); } } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index df050fc9adc..75f9405e082 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2355,8 +2355,10 @@ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { if let ty::ConstKind::Unevaluated(uv) = ct.val { assert_eq!(uv.promoted, None); let span = self.tcx.hir().span(c.hir_id); - self.preds - .insert((ty::PredicateKind::ConstEvaluatable(uv).to_predicate(self.tcx), span)); + self.preds.insert(( + ty::PredicateKind::ConstEvaluatable(uv.shrink()).to_predicate(self.tcx), + span, + )); } } -- GitLab