attempt to re-add ty::Unevaluated
visitor and friends
This commit is contained in:
parent
71bbb603f4
commit
dec8ed438c
21 changed files with 174 additions and 121 deletions
|
@ -668,13 +668,10 @@ 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(
|
let canonical = self.canonicalize_query((a, b), &mut OriginalQueryValues::default());
|
||||||
((a.def, a.substs), (b.def, b.substs)),
|
|
||||||
&mut OriginalQueryValues::default(),
|
|
||||||
);
|
|
||||||
debug!("canonical consts: {:?}", &canonical.value);
|
debug!("canonical consts: {:?}", &canonical.value);
|
||||||
|
|
||||||
self.tcx.try_unify_abstract_consts(canonical.value)
|
self.tcx.try_unify_abstract_consts(canonical.value)
|
||||||
|
|
|
@ -314,12 +314,11 @@ rustc_queries! {
|
||||||
}
|
}
|
||||||
|
|
||||||
query try_unify_abstract_consts(key: (
|
query try_unify_abstract_consts(key: (
|
||||||
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
|
ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>
|
||||||
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)
|
|
||||||
)) -> bool {
|
)) -> bool {
|
||||||
desc {
|
desc {
|
||||||
|tcx| "trying to unify the generic constants {} and {}",
|
|tcx| "trying to unify the generic constants {} and {}",
|
||||||
tcx.def_path_str(key.0.0.did), tcx.def_path_str(key.1.0.did)
|
tcx.def_path_str(key.0.def.did), tcx.def_path_str(key.1.def.did)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,12 +12,31 @@ use rustc_target::abi::Size;
|
||||||
|
|
||||||
use super::ScalarInt;
|
use super::ScalarInt;
|
||||||
/// An unevaluated, potentially generic, constant.
|
/// An unevaluated, potentially generic, constant.
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
|
#[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: SubstsRef<'tcx>,
|
pub substs: SubstsRef<'tcx>,
|
||||||
pub promoted: Option<Promoted>,
|
pub promoted: P,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Unevaluated<'tcx> {
|
||||||
|
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<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> {
|
||||||
|
Unevaluated { def, substs, promoted: Default::default() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a constant in Rust.
|
/// Represents a constant in Rust.
|
||||||
|
@ -109,7 +128,7 @@ impl<'tcx> ConstKind<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
) -> Option<Result<ConstValue<'tcx>, ErrorReported>> {
|
) -> Option<Result<ConstValue<'tcx>, ErrorReported>> {
|
||||||
if let ConstKind::Unevaluated(Unevaluated { def, substs, promoted }) = self {
|
if let ConstKind::Unevaluated(unevaluated) = self {
|
||||||
use crate::mir::interpret::ErrorHandled;
|
use crate::mir::interpret::ErrorHandled;
|
||||||
|
|
||||||
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
|
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
|
||||||
|
@ -118,29 +137,32 @@ impl<'tcx> ConstKind<'tcx> {
|
||||||
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
|
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
|
||||||
// so that we don't try to invoke this query with
|
// so that we don't try to invoke this query with
|
||||||
// any region variables.
|
// any region variables.
|
||||||
let param_env_and_substs = tcx
|
let param_env_and = tcx
|
||||||
.erase_regions(param_env)
|
.erase_regions(param_env)
|
||||||
.with_reveal_all_normalized(tcx)
|
.with_reveal_all_normalized(tcx)
|
||||||
.and(tcx.erase_regions(substs));
|
.and(tcx.erase_regions(unevaluated));
|
||||||
|
|
||||||
// HACK(eddyb) when the query key would contain inference variables,
|
// HACK(eddyb) when the query key would contain inference variables,
|
||||||
// attempt using identity substs and `ParamEnv` instead, that will succeed
|
// attempt using identity substs and `ParamEnv` instead, that will succeed
|
||||||
// when the expression doesn't depend on any parameters.
|
// when the expression doesn't depend on any parameters.
|
||||||
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
|
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
|
||||||
// we can call `infcx.const_eval_resolve` which handles inference variables.
|
// we can call `infcx.const_eval_resolve` which handles inference variables.
|
||||||
let param_env_and_substs = if param_env_and_substs.needs_infer() {
|
let param_env_and = if param_env_and.needs_infer() {
|
||||||
tcx.param_env(def.did).and(InternalSubsts::identity_for_item(tcx, def.did))
|
tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
|
||||||
|
def: unevaluated.def,
|
||||||
|
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
|
||||||
|
promoted: unevaluated.promoted,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
param_env_and_substs
|
param_env_and
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME(eddyb) maybe the `const_eval_*` methods should take
|
// FIXME(eddyb) maybe the `const_eval_*` methods should take
|
||||||
// `ty::ParamEnvAnd<SubstsRef>` instead of having them separate.
|
// `ty::ParamEnvAnd` instead of having them separate.
|
||||||
let (param_env, substs) = param_env_and_substs.into_parts();
|
let (param_env, unevaluated) = param_env_and.into_parts();
|
||||||
// try to resolve e.g. associated constants to their definition on an impl, and then
|
// try to resolve e.g. associated constants to their definition on an impl, and then
|
||||||
// evaluate the const.
|
// evaluate the const.
|
||||||
match tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, None)
|
match tcx.const_eval_resolve(param_env, unevaluated, None) {
|
||||||
{
|
|
||||||
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
|
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
|
||||||
// and we use the original type, so nothing from `substs`
|
// and we use the original type, so nothing from `substs`
|
||||||
// (which may be identity substs, see above),
|
// (which may be identity substs, see above),
|
||||||
|
|
|
@ -34,6 +34,12 @@ impl FlagComputation {
|
||||||
result.flags
|
result.flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags {
|
||||||
|
let mut result = FlagComputation::new();
|
||||||
|
result.add_unevaluated_const(uv);
|
||||||
|
result.flags
|
||||||
|
}
|
||||||
|
|
||||||
fn add_flags(&mut self, flags: TypeFlags) {
|
fn add_flags(&mut self, flags: TypeFlags) {
|
||||||
self.flags = self.flags | flags;
|
self.flags = self.flags | flags;
|
||||||
}
|
}
|
||||||
|
@ -246,8 +252,8 @@ impl FlagComputation {
|
||||||
ty::PredicateKind::ClosureKind(_def_id, substs, _kind) => {
|
ty::PredicateKind::ClosureKind(_def_id, substs, _kind) => {
|
||||||
self.add_substs(substs);
|
self.add_substs(substs);
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEvaluatable(_def_id, substs) => {
|
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||||
self.add_substs(substs);
|
self.add_unevaluated_const(uv);
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEquate(expected, found) => {
|
ty::PredicateKind::ConstEquate(expected, found) => {
|
||||||
self.add_const(expected);
|
self.add_const(expected);
|
||||||
|
@ -304,7 +310,7 @@ impl FlagComputation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'_>) {
|
fn add_unevaluated_const<P>(&mut self, ct: ty::Unevaluated<'_, P>) {
|
||||||
self.add_substs(ct.substs);
|
self.add_substs(ct.substs);
|
||||||
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
|
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
|
||||||
}
|
}
|
||||||
|
|
|
@ -350,6 +350,10 @@ pub trait TypeVisitor<'tcx>: Sized {
|
||||||
c.super_visit_with(self)
|
c.super_visit_with(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
|
uv.super_visit_with(self)
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
p.super_visit_with(self)
|
p.super_visit_with(self)
|
||||||
}
|
}
|
||||||
|
@ -1242,6 +1246,18 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[instrument(level = "trace")]
|
||||||
|
fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'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]
|
#[inline]
|
||||||
#[instrument(level = "trace")]
|
#[instrument(level = "trace")]
|
||||||
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
|
|
|
@ -598,7 +598,7 @@ pub enum PredicateKind<'tcx> {
|
||||||
Coerce(CoercePredicate<'tcx>),
|
Coerce(CoercePredicate<'tcx>),
|
||||||
|
|
||||||
/// Constant initializer must evaluate successfully.
|
/// Constant initializer must evaluate successfully.
|
||||||
ConstEvaluatable(ty::WithOptConstParam<DefId>, SubstsRef<'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>),
|
||||||
|
|
|
@ -2539,8 +2539,8 @@ define_print_and_forward_display! {
|
||||||
print_value_path(closure_def_id, &[]),
|
print_value_path(closure_def_id, &[]),
|
||||||
write("` implements the trait `{}`", kind))
|
write("` implements the trait `{}`", kind))
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEvaluatable(def, substs) => {
|
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||||
p!("the constant `", print_value_path(def.did, substs), "` can be evaluated")
|
p!("the constant `", print_value_path(uv.def.did, uv.substs), "` can be evaluated")
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEquate(c1, c2) => {
|
ty::PredicateKind::ConstEquate(c1, c2) => {
|
||||||
p!("the constant `", print(c1), "` equals `", print(c2), "`")
|
p!("the constant `", print(c1), "` equals `", print(c2), "`")
|
||||||
|
|
|
@ -587,7 +587,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
||||||
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
|
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
|
||||||
if tcx.features().generic_const_exprs =>
|
if tcx.features().generic_const_exprs =>
|
||||||
{
|
{
|
||||||
tcx.try_unify_abstract_consts(((au.def, au.substs), (bu.def, bu.substs)))
|
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`
|
||||||
|
|
|
@ -184,8 +184,8 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
|
||||||
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
|
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
|
||||||
write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
|
write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
|
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||||
write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
|
write!(f, "ConstEvaluatable({:?}, {:?})", uv.def, uv.substs)
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
|
ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
|
||||||
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
|
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
|
||||||
|
@ -445,8 +445,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> {
|
||||||
ty::PredicateKind::ObjectSafe(trait_def_id) => {
|
ty::PredicateKind::ObjectSafe(trait_def_id) => {
|
||||||
Some(ty::PredicateKind::ObjectSafe(trait_def_id))
|
Some(ty::PredicateKind::ObjectSafe(trait_def_id))
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
|
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||||
tcx.lift(substs).map(|substs| ty::PredicateKind::ConstEvaluatable(def_id, substs))
|
tcx.lift(uv).map(|uv| ty::PredicateKind::ConstEvaluatable(uv))
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEquate(c1, c2) => {
|
ty::PredicateKind::ConstEquate(c1, c2) => {
|
||||||
tcx.lift((c1, c2)).map(|(c1, c2)| ty::PredicateKind::ConstEquate(c1, c2))
|
tcx.lift((c1, c2)).map(|(c1, c2)| ty::PredicateKind::ConstEquate(c1, c2))
|
||||||
|
@ -1185,13 +1185,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.try_fold_with(folder)?),
|
ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.try_fold_with(folder)?),
|
||||||
ty::ConstKind::Param(p) => ty::ConstKind::Param(p.try_fold_with(folder)?),
|
ty::ConstKind::Param(p) => ty::ConstKind::Param(p.try_fold_with(folder)?),
|
||||||
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
|
ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.try_fold_with(folder)?),
|
||||||
ty::ConstKind::Unevaluated(ty::Unevaluated {
|
|
||||||
def,
|
|
||||||
substs: substs.try_fold_with(folder)?,
|
|
||||||
promoted,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ty::ConstKind::Value(_)
|
ty::ConstKind::Value(_)
|
||||||
| ty::ConstKind::Bound(..)
|
| ty::ConstKind::Bound(..)
|
||||||
| ty::ConstKind::Placeholder(..)
|
| ty::ConstKind::Placeholder(..)
|
||||||
|
@ -1203,7 +1197,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
|
||||||
match *self {
|
match *self {
|
||||||
ty::ConstKind::Infer(ic) => ic.visit_with(visitor),
|
ty::ConstKind::Infer(ic) => ic.visit_with(visitor),
|
||||||
ty::ConstKind::Param(p) => p.visit_with(visitor),
|
ty::ConstKind::Param(p) => p.visit_with(visitor),
|
||||||
ty::ConstKind::Unevaluated(ct) => ct.substs.visit_with(visitor),
|
ty::ConstKind::Unevaluated(uv) => uv.visit_with(visitor),
|
||||||
ty::ConstKind::Value(_)
|
ty::ConstKind::Value(_)
|
||||||
| ty::ConstKind::Bound(..)
|
| ty::ConstKind::Bound(..)
|
||||||
| ty::ConstKind::Placeholder(_)
|
| ty::ConstKind::Placeholder(_)
|
||||||
|
@ -1224,3 +1218,45 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
|
||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
|
||||||
|
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
|
||||||
|
self,
|
||||||
|
folder: &mut F,
|
||||||
|
) -> Result<Self, F::Error> {
|
||||||
|
Ok(ty::Unevaluated {
|
||||||
|
def: self.def,
|
||||||
|
substs: self.substs.try_fold_with(folder)?,
|
||||||
|
promoted: self.promoted,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||||
|
visitor.visit_unevaluated_const(*self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||||
|
self.substs.visit_with(visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> {
|
||||||
|
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
|
||||||
|
self,
|
||||||
|
folder: &mut F,
|
||||||
|
) -> Result<Self, F::Error> {
|
||||||
|
Ok(ty::Unevaluated {
|
||||||
|
def: self.def,
|
||||||
|
substs: self.substs.try_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> {
|
||||||
|
self.substs.visit_with(visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -716,11 +716,10 @@ impl<'tcx> Cx<'tcx> {
|
||||||
// and not the beginning of discriminants (which is always `0`)
|
// and not the beginning of discriminants (which is always `0`)
|
||||||
let substs = InternalSubsts::identity_for_item(self.tcx(), did);
|
let substs = InternalSubsts::identity_for_item(self.tcx(), did);
|
||||||
let lhs = ty::Const {
|
let lhs = ty::Const {
|
||||||
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(
|
||||||
def: ty::WithOptConstParam::unknown(did),
|
ty::WithOptConstParam::unknown(did),
|
||||||
substs,
|
substs,
|
||||||
promoted: None,
|
)),
|
||||||
}),
|
|
||||||
ty: var_ty,
|
ty: var_ty,
|
||||||
};
|
};
|
||||||
let lhs = self.thir.exprs.push(mk_const(self.tcx().mk_const(lhs)));
|
let lhs = self.thir.exprs.push(mk_const(self.tcx().mk_const(lhs)));
|
||||||
|
@ -912,11 +911,10 @@ impl<'tcx> Cx<'tcx> {
|
||||||
debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
|
debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
|
||||||
ExprKind::Literal {
|
ExprKind::Literal {
|
||||||
literal: self.tcx.mk_const(ty::Const {
|
literal: self.tcx.mk_const(ty::Const {
|
||||||
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(
|
||||||
def: ty::WithOptConstParam::unknown(def_id),
|
ty::WithOptConstParam::unknown(def_id),
|
||||||
substs,
|
substs,
|
||||||
promoted: None,
|
)),
|
||||||
}),
|
|
||||||
ty: self.typeck_results().node_type(expr.hir_id),
|
ty: self.typeck_results().node_type(expr.hir_id),
|
||||||
}),
|
}),
|
||||||
user_ty,
|
user_ty,
|
||||||
|
|
|
@ -135,11 +135,11 @@ where
|
||||||
ty.visit_with(self)
|
ty.visit_with(self)
|
||||||
}
|
}
|
||||||
ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE,
|
ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE,
|
||||||
ty::PredicateKind::ConstEvaluatable(defs, substs)
|
ty::PredicateKind::ConstEvaluatable(uv)
|
||||||
if self.def_id_visitor.tcx().features().generic_const_exprs =>
|
if self.def_id_visitor.tcx().features().generic_const_exprs =>
|
||||||
{
|
{
|
||||||
let tcx = self.def_id_visitor.tcx();
|
let tcx = self.def_id_visitor.tcx();
|
||||||
if let Ok(Some(ct)) = AbstractConst::new(tcx, defs, substs) {
|
if let Ok(Some(ct)) = AbstractConst::new(tcx, uv) {
|
||||||
self.visit_abstract_const_expr(tcx, ct)?;
|
self.visit_abstract_const_expr(tcx, ct)?;
|
||||||
}
|
}
|
||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
|
|
|
@ -245,18 +245,13 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Key
|
impl<'tcx> Key for (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>) {
|
||||||
for (
|
|
||||||
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
|
|
||||||
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
|
|
||||||
)
|
|
||||||
{
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn query_crate_is_local(&self) -> bool {
|
fn query_crate_is_local(&self) -> bool {
|
||||||
(self.0).0.did.krate == LOCAL_CRATE
|
(self.0).def.did.krate == LOCAL_CRATE
|
||||||
}
|
}
|
||||||
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
|
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
|
||||||
(self.0).0.did.default_span(tcx)
|
(self.0).def.did.default_span(tcx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable
|
||||||
use rustc_middle::ty::subst::{Subst, SubstsRef};
|
use rustc_middle::ty::subst::{Subst, SubstsRef};
|
||||||
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
|
||||||
use rustc_session::lint;
|
use rustc_session::lint;
|
||||||
use rustc_span::def_id::{DefId, LocalDefId};
|
use rustc_span::def_id::LocalDefId;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
@ -29,26 +29,20 @@ use std::ops::ControlFlow;
|
||||||
/// 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>,
|
||||||
def: ty::WithOptConstParam<DefId>,
|
uv: ty::Unevaluated<'tcx, ()>,
|
||||||
substs: SubstsRef<'tcx>,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<(), NotConstEvaluatable> {
|
) -> Result<(), NotConstEvaluatable> {
|
||||||
debug!("is_const_evaluatable({:?}, {:?})", def, substs);
|
debug!("is_const_evaluatable({:?})", uv);
|
||||||
if infcx.tcx.features().generic_const_exprs {
|
if infcx.tcx.features().generic_const_exprs {
|
||||||
let tcx = infcx.tcx;
|
let tcx = infcx.tcx;
|
||||||
match AbstractConst::new(tcx, def, substs)? {
|
match AbstractConst::new(tcx, uv)? {
|
||||||
// We are looking at a generic abstract constant.
|
// We are looking at a generic abstract constant.
|
||||||
Some(ct) => {
|
Some(ct) => {
|
||||||
for pred in param_env.caller_bounds() {
|
for pred in param_env.caller_bounds() {
|
||||||
match pred.kind().skip_binder() {
|
match pred.kind().skip_binder() {
|
||||||
ty::PredicateKind::ConstEvaluatable(b_def, b_substs) => {
|
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||||
if b_def == def && b_substs == substs {
|
if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
|
||||||
debug!("is_const_evaluatable: caller_bound ~~> ok");
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(b_ct) = AbstractConst::new(tcx, b_def, b_substs)? {
|
|
||||||
// Try to unify with each subtree in the AbstractConst to allow for
|
// Try to unify with each subtree in the AbstractConst to allow for
|
||||||
// `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
|
// `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
|
||||||
// predicate for `(N + 1) * 2`
|
// predicate for `(N + 1) * 2`
|
||||||
|
@ -132,7 +126,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let future_compat_lint = || {
|
let future_compat_lint = || {
|
||||||
if let Some(local_def_id) = def.did.as_local() {
|
if let Some(local_def_id) = uv.def.did.as_local() {
|
||||||
infcx.tcx.struct_span_lint_hir(
|
infcx.tcx.struct_span_lint_hir(
|
||||||
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
|
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
|
||||||
infcx.tcx.hir().local_def_id_to_hir_id(local_def_id),
|
infcx.tcx.hir().local_def_id_to_hir_id(local_def_id),
|
||||||
|
@ -153,16 +147,12 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||||
// 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(
|
let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
|
||||||
param_env,
|
|
||||||
ty::Unevaluated { def, substs, promoted: None },
|
|
||||||
Some(span),
|
|
||||||
);
|
|
||||||
|
|
||||||
if concrete.is_ok() && substs.has_param_types_or_consts() {
|
if concrete.is_ok() && uv.substs.has_param_types_or_consts() {
|
||||||
match infcx.tcx.def_kind(def.did) {
|
match infcx.tcx.def_kind(uv.def.did) {
|
||||||
DefKind::AnonConst | DefKind::InlineConst => {
|
DefKind::AnonConst | DefKind::InlineConst => {
|
||||||
let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(def);
|
let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
|
||||||
|
|
||||||
if mir_body.is_polymorphic {
|
if mir_body.is_polymorphic {
|
||||||
future_compat_lint();
|
future_compat_lint();
|
||||||
|
@ -174,7 +164,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||||
|
|
||||||
debug!(?concrete, "is_const_evaluatable");
|
debug!(?concrete, "is_const_evaluatable");
|
||||||
match concrete {
|
match concrete {
|
||||||
Err(ErrorHandled::TooGeneric) => Err(match substs.has_infer_types_or_consts() {
|
Err(ErrorHandled::TooGeneric) => Err(match uv.has_infer_types_or_consts() {
|
||||||
true => NotConstEvaluatable::MentionsInfer,
|
true => NotConstEvaluatable::MentionsInfer,
|
||||||
false => NotConstEvaluatable::MentionsParam,
|
false => NotConstEvaluatable::MentionsParam,
|
||||||
}),
|
}),
|
||||||
|
@ -202,12 +192,11 @@ pub struct AbstractConst<'tcx> {
|
||||||
impl<'tcx> AbstractConst<'tcx> {
|
impl<'tcx> AbstractConst<'tcx> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
def: ty::WithOptConstParam<DefId>,
|
uv: ty::Unevaluated<'tcx, ()>,
|
||||||
substs: SubstsRef<'tcx>,
|
|
||||||
) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
|
) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
|
||||||
let inner = tcx.thir_abstract_const_opt_const_arg(def)?;
|
let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?;
|
||||||
debug!("AbstractConst::new({:?}, {:?}) = {:?}", def, substs, inner);
|
debug!("AbstractConst::new({:?}) = {:?}", uv, inner);
|
||||||
Ok(inner.map(|inner| AbstractConst { inner, substs }))
|
Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs }))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_const(
|
pub fn from_const(
|
||||||
|
@ -215,9 +204,7 @@ impl<'tcx> AbstractConst<'tcx> {
|
||||||
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(ty::Unevaluated { def, substs, promoted: _ }) => {
|
ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()),
|
||||||
AbstractConst::new(tcx, def, substs)
|
|
||||||
}
|
|
||||||
ty::ConstKind::Error(_) => Err(ErrorReported),
|
ty::ConstKind::Error(_) => Err(ErrorReported),
|
||||||
_ => Ok(None),
|
_ => Ok(None),
|
||||||
}
|
}
|
||||||
|
@ -539,14 +526,11 @@ pub(super) fn thir_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, a_substs), (b, b_substs)): (
|
(a, b): (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>),
|
||||||
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
|
|
||||||
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
|
|
||||||
),
|
|
||||||
) -> bool {
|
) -> bool {
|
||||||
(|| {
|
(|| {
|
||||||
if let Some(a) = AbstractConst::new(tcx, a, a_substs)? {
|
if let Some(a) = AbstractConst::new(tcx, a)? {
|
||||||
if let Some(b) = AbstractConst::new(tcx, b, b_substs)? {
|
if let Some(b) = AbstractConst::new(tcx, b)? {
|
||||||
return Ok(try_unify(tcx, a, b));
|
return Ok(try_unify(tcx, a, b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -819,10 +819,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
match obligation.predicate.kind().skip_binder() {
|
match obligation.predicate.kind().skip_binder() {
|
||||||
ty::PredicateKind::ConstEvaluatable(def, _) => {
|
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||||
let mut err =
|
let mut err =
|
||||||
self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
|
self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
|
||||||
let const_span = self.tcx.def_span(def.did);
|
let const_span = self.tcx.def_span(uv.def.did);
|
||||||
match self.tcx.sess.source_map().span_to_snippet(const_span) {
|
match self.tcx.sess.source_map().span_to_snippet(const_span) {
|
||||||
Ok(snippet) => err.help(&format!(
|
Ok(snippet) => err.help(&format!(
|
||||||
"try adding a `where` bound using this expression: `where [(); {}]:`",
|
"try adding a `where` bound using this expression: `where [(); {}]:`",
|
||||||
|
|
|
@ -527,11 +527,10 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
|
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||||
match const_evaluatable::is_const_evaluatable(
|
match const_evaluatable::is_const_evaluatable(
|
||||||
self.selcx.infcx(),
|
self.selcx.infcx(),
|
||||||
def_id,
|
uv,
|
||||||
substs,
|
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
) {
|
) {
|
||||||
|
@ -539,7 +538,9 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
Err(NotConstEvaluatable::MentionsInfer) => {
|
Err(NotConstEvaluatable::MentionsInfer) => {
|
||||||
pending_obligation.stalled_on.clear();
|
pending_obligation.stalled_on.clear();
|
||||||
pending_obligation.stalled_on.extend(
|
pending_obligation.stalled_on.extend(
|
||||||
substs.iter().filter_map(TyOrConstInferVar::maybe_from_generic_arg),
|
uv.substs
|
||||||
|
.iter()
|
||||||
|
.filter_map(TyOrConstInferVar::maybe_from_generic_arg),
|
||||||
);
|
);
|
||||||
ProcessResult::Unchanged
|
ProcessResult::Unchanged
|
||||||
}
|
}
|
||||||
|
@ -563,7 +564,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
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![]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -845,12 +845,12 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
if let ty::PredicateKind::ConstEvaluatable(def, substs) = pred.kind().skip_binder() {
|
if let ty::PredicateKind::ConstEvaluatable(uv) = pred.kind().skip_binder() {
|
||||||
// FIXME(generic_const_exprs): We should probably deduplicate the logic for
|
// FIXME(generic_const_exprs): We should probably deduplicate the logic for
|
||||||
// `AbstractConst`s here, it might make sense to change `ConstEvaluatable` to
|
// `AbstractConst`s here, it might make sense to change `ConstEvaluatable` to
|
||||||
// take a `ty::Const` instead.
|
// take a `ty::Const` instead.
|
||||||
use rustc_middle::thir::abstract_const::Node;
|
use rustc_middle::thir::abstract_const::Node;
|
||||||
if let Ok(Some(ct)) = AbstractConst::new(self.tcx, def, substs) {
|
if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv) {
|
||||||
const_evaluatable::walk_abstract_const(self.tcx, ct, |node| {
|
const_evaluatable::walk_abstract_const(self.tcx, ct, |node| {
|
||||||
match node.root(self.tcx) {
|
match node.root(self.tcx) {
|
||||||
Node::Leaf(leaf) => self.visit_const(leaf),
|
Node::Leaf(leaf) => self.visit_const(leaf),
|
||||||
|
|
|
@ -619,11 +619,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
|
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||||
match const_evaluatable::is_const_evaluatable(
|
match const_evaluatable::is_const_evaluatable(
|
||||||
self.infcx,
|
self.infcx,
|
||||||
def_id,
|
uv,
|
||||||
substs,
|
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
) {
|
) {
|
||||||
|
@ -645,7 +644,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,11 +131,11 @@ pub fn predicate_obligations<'a, 'tcx>(
|
||||||
wf.compute(a.into());
|
wf.compute(a.into());
|
||||||
wf.compute(b.into());
|
wf.compute(b.into());
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEvaluatable(def, substs) => {
|
ty::PredicateKind::ConstEvaluatable(uv) => {
|
||||||
let obligations = wf.nominal_obligations(def.did, substs);
|
let obligations = wf.nominal_obligations(uv.def.did, uv.substs);
|
||||||
wf.out.extend(obligations);
|
wf.out.extend(obligations);
|
||||||
|
|
||||||
for arg in substs.iter() {
|
for arg in uv.substs.iter() {
|
||||||
wf.compute(arg);
|
wf.compute(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -441,14 +441,14 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||||
|
|
||||||
GenericArgKind::Const(constant) => {
|
GenericArgKind::Const(constant) => {
|
||||||
match constant.val {
|
match constant.val {
|
||||||
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
|
ty::ConstKind::Unevaluated(uv) => {
|
||||||
assert!(promoted.is_none());
|
assert!(uv.promoted.is_none());
|
||||||
|
|
||||||
let obligations = self.nominal_obligations(def.did, substs);
|
let obligations = self.nominal_obligations(uv.def.did, uv.substs);
|
||||||
self.out.extend(obligations);
|
self.out.extend(obligations);
|
||||||
|
|
||||||
let predicate =
|
let predicate =
|
||||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(def, substs))
|
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink()))
|
||||||
.to_predicate(self.tcx());
|
.to_predicate(self.tcx());
|
||||||
let cause = self.cause(traits::MiscObligation);
|
let cause = self.cause(traits::MiscObligation);
|
||||||
self.out.push(traits::Obligation::with_depth(
|
self.out.push(traits::Obligation::with_depth(
|
||||||
|
|
|
@ -237,9 +237,9 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||||
relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
|
relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
ty::PredicateKind::ConstEvaluatable(a_def, a_substs),
|
ty::PredicateKind::ConstEvaluatable(a),
|
||||||
ty::PredicateKind::ConstEvaluatable(b_def, b_substs),
|
ty::PredicateKind::ConstEvaluatable(b),
|
||||||
) => tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))),
|
) => tcx.try_unify_abstract_consts((a, b)),
|
||||||
(
|
(
|
||||||
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, lt_a)),
|
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, lt_a)),
|
||||||
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_b, lt_b)),
|
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_b, lt_b)),
|
||||||
|
|
|
@ -972,10 +972,10 @@ fn check_type_defn<'tcx, F>(
|
||||||
fcx.register_predicate(traits::Obligation::new(
|
fcx.register_predicate(traits::Obligation::new(
|
||||||
cause,
|
cause,
|
||||||
fcx.param_env,
|
fcx.param_env,
|
||||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
|
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ty::Unevaluated::new(
|
||||||
ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
|
ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
|
||||||
discr_substs,
|
discr_substs,
|
||||||
))
|
)))
|
||||||
.to_predicate(tcx),
|
.to_predicate(tcx),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2313,7 +2313,7 @@ fn const_evaluatable_predicates_of<'tcx>(
|
||||||
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.insert((
|
self.preds.insert((
|
||||||
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.def, uv.substs))
|
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink()))
|
||||||
.to_predicate(self.tcx),
|
.to_predicate(self.tcx),
|
||||||
span,
|
span,
|
||||||
));
|
));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue