/// An unevaluated (potentially generic) constant used in the type-system.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
-#[derive(Hash, HashStable)]
+#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
pub struct UnevaluatedConst<'tcx> {
pub def: ty::WithOptConstParam<DefId>,
pub substs: SubstsRef<'tcx>,
result.flags
}
- pub fn for_unevaluated_const(uv: ty::UnevaluatedConst<'_>) -> TypeFlags {
- let mut result = FlagComputation::new();
- result.add_unevaluated_const(uv);
- result.flags
- }
-
fn add_flags(&mut self, flags: TypeFlags) {
self.flags = self.flags | flags;
}
fn add_const(&mut self, c: ty::Const<'_>) {
self.add_ty(c.ty());
match c.kind() {
- ty::ConstKind::Unevaluated(unevaluated) => self.add_unevaluated_const(unevaluated),
+ ty::ConstKind::Unevaluated(uv) => {
+ self.add_substs(uv.substs);
+ self.add_flags(TypeFlags::HAS_CT_PROJECTION);
+ }
ty::ConstKind::Infer(infer) => {
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
match infer {
}
}
- fn add_unevaluated_const(&mut self, ct: ty::UnevaluatedConst<'_>) {
- self.add_substs(ct.substs);
- self.add_flags(TypeFlags::HAS_CT_PROJECTION);
- }
-
fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
self.add_substs(projection.substs);
match projection.term.unpack() {
c.super_fold_with(self)
}
- fn fold_ty_unevaluated(
- &mut self,
- uv: ty::UnevaluatedConst<'tcx>,
- ) -> ty::UnevaluatedConst<'tcx> {
- uv.super_fold_with(self)
- }
-
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
p.super_fold_with(self)
}
c.try_super_fold_with(self)
}
- fn try_fold_ty_unevaluated(
- &mut self,
- c: ty::UnevaluatedConst<'tcx>,
- ) -> Result<ty::UnevaluatedConst<'tcx>, Self::Error> {
- c.try_super_fold_with(self)
- }
-
fn try_fold_predicate(
&mut self,
p: ty::Predicate<'tcx>,
Ok(self.fold_const(c))
}
- fn try_fold_ty_unevaluated(
- &mut self,
- c: ty::UnevaluatedConst<'tcx>,
- ) -> Result<ty::UnevaluatedConst<'tcx>, !> {
- Ok(self.fold_ty_unevaluated(c))
- }
-
fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result<ty::Predicate<'tcx>, !> {
Ok(self.fold_predicate(p))
}
}
}
-impl<'tcx> TypeFoldable<'tcx> for ty::UnevaluatedConst<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- folder.try_fold_ty_unevaluated(self)
- }
-}
-
-impl<'tcx> TypeVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- visitor.visit_ty_unevaluated(*self)
- }
-}
-
-impl<'tcx> TypeSuperFoldable<'tcx> for ty::UnevaluatedConst<'tcx> {
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
- self,
- folder: &mut F,
- ) -> Result<Self, F::Error> {
- Ok(ty::UnevaluatedConst { def: self.def, substs: self.substs.try_fold_with(folder)? })
- }
-}
-
impl<'tcx> TypeSuperVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.substs.visit_with(visitor)
c.super_visit_with(self)
}
- fn visit_ty_unevaluated(
- &mut self,
- uv: ty::UnevaluatedConst<'tcx>,
- ) -> ControlFlow<Self::BreakTy> {
- uv.super_visit_with(self)
- }
-
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
p.super_visit_with(self)
}
}
}
- #[inline]
- #[instrument(level = "trace", ret)]
- fn visit_ty_unevaluated(
- &mut self,
- uv: ty::UnevaluatedConst<'tcx>,
- ) -> ControlFlow<Self::BreakTy> {
- let flags = FlagComputation::for_unevaluated_const(uv);
- trace!(r.flags=?flags);
- if flags.intersects(self.flags) {
- ControlFlow::Break(FoundFlags)
- } else {
- ControlFlow::CONTINUE
- }
- }
-
#[inline]
#[instrument(level = "trace", ret)]
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
}
}
- fn visit_ty_unevaluated(
- &mut self,
- uv: ty::UnevaluatedConst<'tcx>,
- ) -> ControlFlow<Self::BreakTy> {
+ fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
// Constants can only influence object safety if they reference `Self`.
// This is only possible for unevaluated constants, so we walk these here.
//
- // If `AbstractConst::new` returned an error we already failed compilation
+ // If `AbstractConst::from_const` returned an error we already failed compilation
// so we don't have to emit an additional error here.
- //
- // We currently recurse into abstract consts here but do not recurse in
- // `is_const_evaluatable`. This means that the object safety check is more
- // liberal than the const eval check.
- //
- // This shouldn't really matter though as we can't really use any
- // constants which are not considered const evaluatable.
use rustc_middle::ty::abstract_const::Node;
- if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv) {
+ if let Ok(Some(ct)) = AbstractConst::from_const(self.tcx, ct) {
walk_abstract_const(self.tcx, ct, |node| match node.root(self.tcx) {
Node::Leaf(leaf) => self.visit_const(leaf),
Node::Cast(_, _, ty) => self.visit_ty(ty),
}
})
} else {
- ControlFlow::CONTINUE
+ ct.super_visit_with(self)
}
}
}