提交 bc0156ba 编写于 作者: L lcnr

shrink `ty::PredicateKind` again

上级 283e0e67
...@@ -675,8 +675,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ...@@ -675,8 +675,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
/// canonicalizing the consts. /// canonicalizing the consts.
pub fn try_unify_abstract_consts( pub fn try_unify_abstract_consts(
&self, &self,
a: ty::Unevaluated<'tcx>, a: ty::Unevaluated<'tcx, ()>,
b: ty::Unevaluated<'tcx>, b: ty::Unevaluated<'tcx, ()>,
) -> bool { ) -> bool {
let canonical = self.canonicalize_query((a, b), &mut OriginalQueryValues::default()); let canonical = self.canonicalize_query((a, b), &mut OriginalQueryValues::default());
debug!("canonical consts: {:?}", &canonical.value); debug!("canonical consts: {:?}", &canonical.value);
......
...@@ -303,7 +303,7 @@ ...@@ -303,7 +303,7 @@
} }
query try_unify_abstract_consts(key: ( query try_unify_abstract_consts(key: (
ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx> ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>
)) -> bool { )) -> bool {
desc { desc {
|tcx| "trying to unify the generic constants {} and {}", |tcx| "trying to unify the generic constants {} and {}",
......
use std::convert::TryInto; use std::convert::TryInto;
use std::fmt;
use crate::mir::interpret::{AllocId, ConstValue, Scalar}; use crate::mir::interpret::{AllocId, ConstValue, Scalar};
use crate::mir::Promoted; use crate::mir::Promoted;
...@@ -20,20 +21,38 @@ ...@@ -20,20 +21,38 @@
/// so refer to that check for more info. /// so refer to that check for more info.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
#[derive(Hash, HashStable)] #[derive(Hash, HashStable)]
pub struct Unevaluated<'tcx> { pub struct Unevaluated<'tcx, P = Option<Promoted>> {
pub def: ty::WithOptConstParam<DefId>, pub def: ty::WithOptConstParam<DefId>,
pub substs_: Option<SubstsRef<'tcx>>, pub substs_: Option<SubstsRef<'tcx>>,
pub promoted: Option<Promoted>, pub promoted: P,
} }
impl<'tcx> Unevaluated<'tcx> { impl<'tcx> Unevaluated<'tcx> {
pub fn new(def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx> { pub fn shrink(self) -> Unevaluated<'tcx, ()> {
Unevaluated { def, substs_: Some(substs), promoted: None } 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<DefId>, 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> { pub fn substs(self, tcx: TyCtxt<'tcx>) -> SubstsRef<'tcx> {
self.substs_.unwrap_or_else(|| { 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) tcx.default_anon_const_substs(self.def.did)
}) })
} }
......
...@@ -310,7 +310,7 @@ fn add_const(&mut self, c: &ty::Const<'_>) { ...@@ -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<P>(&mut self, ct: ty::Unevaluated<'tcx, P>) {
if let Some(substs) = ct.substs_ { if let Some(substs) = ct.substs_ {
self.add_substs(substs); self.add_substs(substs);
} else { } else {
......
...@@ -406,7 +406,7 @@ pub fn has_name(&self) -> bool { ...@@ -406,7 +406,7 @@ pub fn has_name(&self) -> bool {
} }
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(PredicateInner<'_>, 56); static_assert_size!(PredicateInner<'_>, 48);
#[derive(Clone, Copy, Lift)] #[derive(Clone, Copy, Lift)]
pub struct Predicate<'tcx> { pub struct Predicate<'tcx> {
...@@ -502,7 +502,7 @@ pub enum PredicateKind<'tcx> { ...@@ -502,7 +502,7 @@ pub enum PredicateKind<'tcx> {
Coerce(CoercePredicate<'tcx>), Coerce(CoercePredicate<'tcx>),
/// Constant initializer must evaluate successfully. /// 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. /// Constants must be equal. The first component is the const that is expected.
ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>), ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>),
......
...@@ -579,7 +579,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>( ...@@ -579,7 +579,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
if tcx.features().const_evaluatable_checked => 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` // While this is slightly incorrect, it shouldn't matter for `min_const_generics`
......
...@@ -1105,3 +1105,28 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow ...@@ -1105,3 +1105,28 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
} }
} }
} }
impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> {
fn super_fold_with<F: TypeFolder<'tcx>>(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<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_unevaluated_const(self.expand())
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
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
}
}
}
...@@ -217,7 +217,7 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span { ...@@ -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)] #[inline(always)]
fn query_crate_is_local(&self) -> bool { fn query_crate_is_local(&self) -> bool {
(self.0).def.did.krate == LOCAL_CRATE (self.0).def.did.krate == LOCAL_CRATE
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
/// Check if a given constant can be evaluated. /// Check if a given constant can be evaluated.
pub fn is_const_evaluatable<'cx, 'tcx>( pub fn is_const_evaluatable<'cx, 'tcx>(
infcx: &InferCtxt<'cx, 'tcx>, infcx: &InferCtxt<'cx, 'tcx>,
uv: ty::Unevaluated<'tcx>, uv: ty::Unevaluated<'tcx, ()>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
span: Span, span: Span,
) -> Result<(), NotConstEvaluatable> { ) -> Result<(), NotConstEvaluatable> {
...@@ -149,7 +149,7 @@ enum FailureKind { ...@@ -149,7 +149,7 @@ enum FailureKind {
// and hopefully soon change this to an error. // and hopefully soon change this to an error.
// //
// See #74595 for more details about this. // 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) { if concrete.is_ok() && uv.substs(infcx.tcx).has_param_types_or_consts(infcx.tcx) {
match infcx.tcx.def_kind(uv.def.did) { match infcx.tcx.def_kind(uv.def.did) {
...@@ -194,7 +194,7 @@ pub struct AbstractConst<'tcx> { ...@@ -194,7 +194,7 @@ pub struct AbstractConst<'tcx> {
impl<'tcx> AbstractConst<'tcx> { impl<'tcx> AbstractConst<'tcx> {
pub fn new( pub fn new(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
uv: ty::Unevaluated<'tcx>, uv: ty::Unevaluated<'tcx, ()>,
) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> { ) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
let inner = tcx.mir_abstract_const_opt_const_arg(uv.def)?; let inner = tcx.mir_abstract_const_opt_const_arg(uv.def)?;
debug!("AbstractConst::new({:?}) = {:?}", uv, inner); debug!("AbstractConst::new({:?}) = {:?}", uv, inner);
...@@ -206,7 +206,7 @@ pub fn from_const( ...@@ -206,7 +206,7 @@ pub fn from_const(
ct: &ty::Const<'tcx>, ct: &ty::Const<'tcx>,
) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> { ) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
match ct.val { 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), ty::ConstKind::Error(_) => Err(ErrorReported),
_ => Ok(None), _ => Ok(None),
} }
...@@ -556,7 +556,7 @@ pub(super) fn mir_abstract_const<'tcx>( ...@@ -556,7 +556,7 @@ pub(super) fn mir_abstract_const<'tcx>(
pub(super) fn try_unify_abstract_consts<'tcx>( pub(super) fn try_unify_abstract_consts<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
(a, b): (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx>), (a, b): (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>),
) -> bool { ) -> bool {
(|| { (|| {
if let Some(a) = AbstractConst::new(tcx, a)? { if let Some(a) = AbstractConst::new(tcx, a)? {
......
...@@ -580,7 +580,7 @@ fn progress_changed_obligations( ...@@ -580,7 +580,7 @@ fn progress_changed_obligations(
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
(c1.val, c2.val) (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![]); return ProcessResult::Changed(vec![]);
} }
} }
......
...@@ -623,7 +623,7 @@ fn evaluate_predicate_recursively<'o>( ...@@ -623,7 +623,7 @@ fn evaluate_predicate_recursively<'o>(
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
(c1.val, c2.val) (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); return Ok(EvaluatedToOk);
} }
} }
......
...@@ -2355,8 +2355,10 @@ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { ...@@ -2355,8 +2355,10 @@ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
if let ty::ConstKind::Unevaluated(uv) = ct.val { if let ty::ConstKind::Unevaluated(uv) = ct.val {
assert_eq!(uv.promoted, None); assert_eq!(uv.promoted, None);
let span = self.tcx.hir().span(c.hir_id); let span = self.tcx.hir().span(c.hir_id);
self.preds self.preds.insert((
.insert((ty::PredicateKind::ConstEvaluatable(uv).to_predicate(self.tcx), span)); ty::PredicateKind::ConstEvaluatable(uv.shrink()).to_predicate(self.tcx),
span,
));
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册