extract ConstKind::Unevaluated
into a struct
This commit is contained in:
parent
41b315a470
commit
43ebac119b
25 changed files with 131 additions and 88 deletions
|
@ -30,7 +30,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
mir::ConstantKind::Val(val, _) => return Ok(val),
|
mir::ConstantKind::Val(val, _) => return Ok(val),
|
||||||
};
|
};
|
||||||
match ct.val {
|
match ct.val {
|
||||||
ty::ConstKind::Unevaluated(def, substs, promoted) => self
|
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => self
|
||||||
.cx
|
.cx
|
||||||
.tcx()
|
.tcx()
|
||||||
.const_eval_resolve(ty::ParamEnv::reveal_all(), def, substs, promoted, None)
|
.const_eval_resolve(ty::ParamEnv::reveal_all(), def, substs, promoted, None)
|
||||||
|
|
|
@ -98,18 +98,18 @@ impl<'tcx> Const<'tcx> {
|
||||||
let name = tcx.hir().name(hir_id);
|
let name = tcx.hir().name(hir_id);
|
||||||
ty::ConstKind::Param(ty::ParamConst::new(index, name))
|
ty::ConstKind::Param(ty::ParamConst::new(index, name))
|
||||||
}
|
}
|
||||||
_ => ty::ConstKind::Unevaluated(
|
_ => ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||||
def.to_global(),
|
def: def.to_global(),
|
||||||
InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
|
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
|
||||||
None,
|
promoted: None,
|
||||||
),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
tcx.mk_const(ty::Const { val, ty })
|
tcx.mk_const(ty::Const { val, ty })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// Interns the given value as a constant.
|
/// Interns the given value as a constant.
|
||||||
|
#[inline]
|
||||||
pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self {
|
pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self {
|
||||||
tcx.mk_const(Self { val: ConstKind::Value(val), ty })
|
tcx.mk_const(Self { val: ConstKind::Value(val), ty })
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,18 @@ use rustc_macros::HashStable;
|
||||||
use rustc_target::abi::Size;
|
use rustc_target::abi::Size;
|
||||||
|
|
||||||
use super::ScalarInt;
|
use super::ScalarInt;
|
||||||
|
/// An unevaluated, potentially generic, constant.
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
|
||||||
|
#[derive(Hash, HashStable)]
|
||||||
|
pub struct Unevaluated<'tcx> {
|
||||||
|
pub def: ty::WithOptConstParam<DefId>,
|
||||||
|
pub substs: SubstsRef<'tcx>,
|
||||||
|
pub promoted: Option<Promoted>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents a constant in Rust.
|
/// Represents a constant in Rust.
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
|
||||||
#[derive(HashStable)]
|
#[derive(Hash, HashStable)]
|
||||||
pub enum ConstKind<'tcx> {
|
pub enum ConstKind<'tcx> {
|
||||||
/// A const generic parameter.
|
/// A const generic parameter.
|
||||||
Param(ty::ParamConst),
|
Param(ty::ParamConst),
|
||||||
|
@ -31,7 +39,7 @@ pub enum ConstKind<'tcx> {
|
||||||
|
|
||||||
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
|
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
|
||||||
/// variants when the code is monomorphic enough for that.
|
/// variants when the code is monomorphic enough for that.
|
||||||
Unevaluated(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>, Option<Promoted>),
|
Unevaluated(Unevaluated<'tcx>),
|
||||||
|
|
||||||
/// Used to hold computed value.
|
/// Used to hold computed value.
|
||||||
Value(ConstValue<'tcx>),
|
Value(ConstValue<'tcx>),
|
||||||
|
@ -102,7 +110,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(def, substs, promoted) = self {
|
if let ConstKind::Unevaluated(Unevaluated { def, substs, promoted }) = 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`
|
||||||
|
|
|
@ -270,10 +270,7 @@ impl FlagComputation {
|
||||||
fn add_const(&mut self, c: &ty::Const<'_>) {
|
fn add_const(&mut self, c: &ty::Const<'_>) {
|
||||||
self.add_ty(c.ty);
|
self.add_ty(c.ty);
|
||||||
match c.val {
|
match c.val {
|
||||||
ty::ConstKind::Unevaluated(_, substs, _) => {
|
ty::ConstKind::Unevaluated(unevaluated) => self.add_unevaluated_const(unevaluated),
|
||||||
self.add_substs(substs);
|
|
||||||
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
|
|
||||||
}
|
|
||||||
ty::ConstKind::Infer(infer) => {
|
ty::ConstKind::Infer(infer) => {
|
||||||
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||||
match infer {
|
match infer {
|
||||||
|
@ -297,6 +294,11 @@ impl FlagComputation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) {
|
||||||
|
self.add_substs(ct.substs);
|
||||||
|
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
|
||||||
|
}
|
||||||
|
|
||||||
fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
|
fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
|
||||||
self.add_substs(projection.substs);
|
self.add_substs(projection.substs);
|
||||||
self.add_ty(projection.ty);
|
self.add_ty(projection.ty);
|
||||||
|
|
|
@ -55,7 +55,7 @@ pub use rustc_type_ir::*;
|
||||||
|
|
||||||
pub use self::binding::BindingMode;
|
pub use self::binding::BindingMode;
|
||||||
pub use self::binding::BindingMode::*;
|
pub use self::binding::BindingMode::*;
|
||||||
pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, ValTree};
|
pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, Unevaluated, ValTree};
|
||||||
pub use self::context::{
|
pub use self::context::{
|
||||||
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
|
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
|
||||||
CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt,
|
CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt,
|
||||||
|
|
|
@ -915,7 +915,7 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
}
|
}
|
||||||
|
|
||||||
match ct.val {
|
match ct.val {
|
||||||
ty::ConstKind::Unevaluated(def, substs, promoted) => {
|
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
|
||||||
if let Some(promoted) = promoted {
|
if let Some(promoted) = promoted {
|
||||||
p!(print_value_path(def.did, substs));
|
p!(print_value_path(def.did, substs));
|
||||||
p!(write("::{:?}", promoted));
|
p!(write("::{:?}", promoted));
|
||||||
|
|
|
@ -531,24 +531,26 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
|
||||||
check_const_value_eq(relation, a_val, b_val, a, b)?
|
check_const_value_eq(relation, a_val, b_val, a, b)?
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
|
||||||
ty::ConstKind::Unevaluated(a_def, a_substs, None),
|
if tcx.features().const_evaluatable_checked && !relation.visit_ct_substs() =>
|
||||||
ty::ConstKind::Unevaluated(b_def, b_substs, None),
|
{
|
||||||
) if tcx.features().const_evaluatable_checked && !relation.visit_ct_substs() => {
|
tcx.try_unify_abstract_consts(((au.def, au.substs), (bu.def, bu.substs)))
|
||||||
tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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`
|
||||||
// and is the better alternative to waiting until `const_evaluatable_checked` can
|
// and is the better alternative to waiting until `const_evaluatable_checked` can
|
||||||
// be stabilized.
|
// be stabilized.
|
||||||
(
|
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
|
||||||
ty::ConstKind::Unevaluated(a_def, a_substs, a_promoted),
|
if au.def == bu.def && au.promoted == bu.promoted =>
|
||||||
ty::ConstKind::Unevaluated(b_def, b_substs, b_promoted),
|
{
|
||||||
) if a_def == b_def && a_promoted == b_promoted => {
|
|
||||||
let substs =
|
let substs =
|
||||||
relation.relate_with_variance(ty::Variance::Invariant, a_substs, b_substs)?;
|
relation.relate_with_variance(ty::Variance::Invariant, au.substs, bu.substs)?;
|
||||||
return Ok(tcx.mk_const(ty::Const {
|
return Ok(tcx.mk_const(ty::Const {
|
||||||
val: ty::ConstKind::Unevaluated(a_def, substs, a_promoted),
|
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||||
|
def: au.def,
|
||||||
|
substs,
|
||||||
|
promoted: au.promoted,
|
||||||
|
}),
|
||||||
ty: a.ty,
|
ty: a.ty,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1031,8 +1031,12 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
|
||||||
match self {
|
match self {
|
||||||
ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)),
|
ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)),
|
||||||
ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)),
|
ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)),
|
||||||
ty::ConstKind::Unevaluated(did, substs, promoted) => {
|
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
|
||||||
ty::ConstKind::Unevaluated(did, substs.fold_with(folder), promoted)
|
ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||||
|
def,
|
||||||
|
substs: substs.fold_with(folder),
|
||||||
|
promoted,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
ty::ConstKind::Value(_)
|
ty::ConstKind::Value(_)
|
||||||
| ty::ConstKind::Bound(..)
|
| ty::ConstKind::Bound(..)
|
||||||
|
@ -1045,7 +1049,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(_, substs, _) => substs.visit_with(visitor),
|
ty::ConstKind::Unevaluated(ct) => ct.substs.visit_with(visitor),
|
||||||
ty::ConstKind::Value(_)
|
ty::ConstKind::Value(_)
|
||||||
| ty::ConstKind::Bound(..)
|
| ty::ConstKind::Bound(..)
|
||||||
| ty::ConstKind::Placeholder(_)
|
| ty::ConstKind::Placeholder(_)
|
||||||
|
|
|
@ -195,8 +195,8 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
|
||||||
| ty::ConstKind::Value(_)
|
| ty::ConstKind::Value(_)
|
||||||
| ty::ConstKind::Error(_) => {}
|
| ty::ConstKind::Error(_) => {}
|
||||||
|
|
||||||
ty::ConstKind::Unevaluated(_, substs, _) => {
|
ty::ConstKind::Unevaluated(ct) => {
|
||||||
stack.extend(substs.iter().rev());
|
stack.extend(ct.substs.iter().rev());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -316,14 +316,12 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let maybe_uneval = match constant.literal {
|
let maybe_uneval = match constant.literal {
|
||||||
ConstantKind::Ty(ct) => match ct.val {
|
ConstantKind::Ty(ct) => match ct.val {
|
||||||
ty::ConstKind::Unevaluated(def, substs, promoted) => {
|
ty::ConstKind::Unevaluated(uv) => Some(uv),
|
||||||
Some((def, substs, promoted))
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
if let Some((def, substs, promoted)) = maybe_uneval {
|
if let Some(ty::Unevaluated { def, substs, promoted }) = maybe_uneval {
|
||||||
if let Some(promoted) = promoted {
|
if let Some(promoted) = promoted {
|
||||||
let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
|
let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
|
||||||
promoted: &Body<'tcx>,
|
promoted: &Body<'tcx>,
|
||||||
|
|
|
@ -560,7 +560,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
match val.val {
|
match val.val {
|
||||||
ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
|
ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
|
||||||
ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorReported)),
|
ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorReported)),
|
||||||
ty::ConstKind::Unevaluated(def, substs, promoted) => {
|
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
|
||||||
let instance = self.resolve(def, substs)?;
|
let instance = self.resolve(def, substs)?;
|
||||||
Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into())
|
Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into())
|
||||||
}
|
}
|
||||||
|
|
|
@ -646,7 +646,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||||
|
|
||||||
match substituted_constant.val {
|
match substituted_constant.val {
|
||||||
ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output),
|
ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output),
|
||||||
ty::ConstKind::Unevaluated(def, substs, promoted) => {
|
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
|
||||||
match self.tcx.const_eval_resolve(param_env, def, substs, promoted, None) {
|
match self.tcx.const_eval_resolve(param_env, def, substs, promoted, None) {
|
||||||
Ok(val) => collect_const_value(self.tcx, val, self.output),
|
Ok(val) => collect_const_value(self.tcx, val, self.output),
|
||||||
Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => {}
|
Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => {}
|
||||||
|
|
|
@ -299,7 +299,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||||
self.unused_parameters.clear(param.index);
|
self.unused_parameters.clear(param.index);
|
||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
ty::ConstKind::Unevaluated(def, _, Some(p))
|
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p)})
|
||||||
// Avoid considering `T` unused when constants are of the form:
|
// Avoid considering `T` unused when constants are of the form:
|
||||||
// `<Self as Foo<T>>::foo::promoted[p]`
|
// `<Self as Foo<T>>::foo::promoted[p]`
|
||||||
if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
|
if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
|
||||||
|
@ -310,10 +310,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||||
self.visit_body(&promoted[p]);
|
self.visit_body(&promoted[p]);
|
||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
ty::ConstKind::Unevaluated(def, unevaluated_substs, None)
|
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None })
|
||||||
if self.tcx.def_kind(def.did) == DefKind::AnonConst =>
|
if self.tcx.def_kind(def.did) == DefKind::AnonConst =>
|
||||||
{
|
{
|
||||||
self.visit_child_body(def.did, unevaluated_substs);
|
self.visit_child_body(def.did, substs);
|
||||||
ControlFlow::CONTINUE
|
ControlFlow::CONTINUE
|
||||||
}
|
}
|
||||||
_ => c.super_visit_with(self),
|
_ => c.super_visit_with(self),
|
||||||
|
|
|
@ -247,7 +247,7 @@ where
|
||||||
|
|
||||||
// Check the qualifs of the value of `const` items.
|
// Check the qualifs of the value of `const` items.
|
||||||
if let Some(ct) = constant.literal.const_for_ty() {
|
if let Some(ct) = constant.literal.const_for_ty() {
|
||||||
if let ty::ConstKind::Unevaluated(def, _, promoted) = ct.val {
|
if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) = ct.val {
|
||||||
assert!(promoted.is_none());
|
assert!(promoted.is_none());
|
||||||
// Don't peek inside trait associated constants.
|
// Don't peek inside trait associated constants.
|
||||||
if cx.tcx.trait_of_item(def.did).is_none() {
|
if cx.tcx.trait_of_item(def.did).is_none() {
|
||||||
|
|
|
@ -491,7 +491,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
let lint_only = match c.literal {
|
let lint_only = match c.literal {
|
||||||
ConstantKind::Ty(ct) => match ct.val {
|
ConstantKind::Ty(ct) => match ct.val {
|
||||||
// Promoteds must lint and not error as the user didn't ask for them
|
// Promoteds must lint and not error as the user didn't ask for them
|
||||||
ConstKind::Unevaluated(_, _, Some(_)) => true,
|
ConstKind::Unevaluated(ty::Unevaluated {
|
||||||
|
def: _,
|
||||||
|
substs: _,
|
||||||
|
promoted: Some(_),
|
||||||
|
}) => true,
|
||||||
// Out of backwards compatibility we cannot report hard errors in unused
|
// Out of backwards compatibility we cannot report hard errors in unused
|
||||||
// generic functions using associated constants of the generic parameters.
|
// generic functions using associated constants of the generic parameters.
|
||||||
_ => c.literal.needs_subst(),
|
_ => c.literal.needs_subst(),
|
||||||
|
|
|
@ -630,7 +630,7 @@ impl Inliner<'tcx> {
|
||||||
caller_body.required_consts.extend(
|
caller_body.required_consts.extend(
|
||||||
callee_body.required_consts.iter().copied().filter(|&ct| {
|
callee_body.required_consts.iter().copied().filter(|&ct| {
|
||||||
match ct.literal.const_for_ty() {
|
match ct.literal.const_for_ty() {
|
||||||
Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_, _, _)),
|
Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_)),
|
||||||
None => true,
|
None => true,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -1001,17 +1001,17 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||||
literal: tcx
|
literal: tcx
|
||||||
.mk_const(ty::Const {
|
.mk_const(ty::Const {
|
||||||
ty,
|
ty,
|
||||||
val: ty::ConstKind::Unevaluated(
|
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||||
def,
|
def,
|
||||||
InternalSubsts::for_item(tcx, def.did, |param, _| {
|
substs: InternalSubsts::for_item(tcx, def.did, |param, _| {
|
||||||
if let ty::GenericParamDefKind::Lifetime = param.kind {
|
if let ty::GenericParamDefKind::Lifetime = param.kind {
|
||||||
tcx.lifetimes.re_erased.into()
|
tcx.lifetimes.re_erased.into()
|
||||||
} else {
|
} else {
|
||||||
tcx.mk_param_from_def(param)
|
tcx.mk_param_from_def(param)
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
Some(promoted_id),
|
promoted: Some(promoted_id),
|
||||||
),
|
}),
|
||||||
})
|
})
|
||||||
.into(),
|
.into(),
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -15,7 +15,7 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, 'tcx> {
|
||||||
fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) {
|
fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) {
|
||||||
if let Some(ct) = constant.literal.const_for_ty() {
|
if let Some(ct) = constant.literal.const_for_ty() {
|
||||||
if let ConstKind::Unevaluated(_, _, _) = ct.val {
|
if let ConstKind::Unevaluated(_) = ct.val {
|
||||||
self.required_consts.push(*constant);
|
self.required_consts.push(*constant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -707,11 +707,11 @@ impl<'thir, 'tcx> Cx<'thir, '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 = mk_const(self.tcx().mk_const(ty::Const {
|
let lhs = mk_const(self.tcx().mk_const(ty::Const {
|
||||||
val: ty::ConstKind::Unevaluated(
|
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||||
ty::WithOptConstParam::unknown(did),
|
def: ty::WithOptConstParam::unknown(did),
|
||||||
substs,
|
substs,
|
||||||
None,
|
promoted: None,
|
||||||
),
|
}),
|
||||||
ty: var_ty,
|
ty: var_ty,
|
||||||
}));
|
}));
|
||||||
let bin =
|
let bin =
|
||||||
|
@ -905,11 +905,11 @@ impl<'thir, 'tcx> Cx<'thir, '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(
|
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||||
ty::WithOptConstParam::unknown(def_id),
|
def: ty::WithOptConstParam::unknown(def_id),
|
||||||
substs,
|
substs,
|
||||||
None,
|
promoted: None,
|
||||||
),
|
}),
|
||||||
ty: self.typeck_results().node_type(expr.hir_id),
|
ty: self.typeck_results().node_type(expr.hir_id),
|
||||||
}),
|
}),
|
||||||
user_ty,
|
user_ty,
|
||||||
|
|
|
@ -803,7 +803,12 @@ impl AutoTraitFinder<'tcx> {
|
||||||
}
|
}
|
||||||
ty::PredicateKind::ConstEquate(c1, c2) => {
|
ty::PredicateKind::ConstEquate(c1, c2) => {
|
||||||
let evaluate = |c: &'tcx ty::Const<'tcx>| {
|
let evaluate = |c: &'tcx ty::Const<'tcx>| {
|
||||||
if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val {
|
if let ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||||
|
def,
|
||||||
|
substs,
|
||||||
|
promoted,
|
||||||
|
}) = c.val
|
||||||
|
{
|
||||||
match select.infcx().const_eval_resolve(
|
match select.infcx().const_eval_resolve(
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
def,
|
def,
|
||||||
|
|
|
@ -239,7 +239,9 @@ impl 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(def, substs, None) => AbstractConst::new(tcx, def, substs),
|
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: _ }) => {
|
||||||
|
AbstractConst::new(tcx, def, substs)
|
||||||
|
}
|
||||||
ty::ConstKind::Error(_) => Err(ErrorReported),
|
ty::ConstKind::Error(_) => Err(ErrorReported),
|
||||||
_ => Ok(None),
|
_ => Ok(None),
|
||||||
}
|
}
|
||||||
|
@ -532,22 +534,25 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||||
if let Some(next) = self.build_terminator(block.terminator())? {
|
if let Some(next) = self.build_terminator(block.terminator())? {
|
||||||
block = &self.body.basic_blocks()[next];
|
block = &self.body.basic_blocks()[next];
|
||||||
} else {
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap());
|
assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap());
|
||||||
|
for n in self.nodes.iter() {
|
||||||
|
if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n.node {
|
||||||
// `AbstractConst`s should not contain any promoteds as they require references which
|
// `AbstractConst`s should not contain any promoteds as they require references which
|
||||||
// are not allowed.
|
// are not allowed.
|
||||||
assert!(!self.nodes.iter().any(|n| matches!(
|
assert_eq!(ct.promoted, None);
|
||||||
n.node,
|
}
|
||||||
Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(_, _, Some(_)), ty: _ })
|
}
|
||||||
)));
|
|
||||||
|
|
||||||
self.nodes[self.locals[mir::RETURN_PLACE]].used = true;
|
self.nodes[self.locals[mir::RETURN_PLACE]].used = true;
|
||||||
if let Some(&unused) = self.nodes.iter().find(|n| !n.used) {
|
if let Some(&unused) = self.nodes.iter().find(|n| !n.used) {
|
||||||
self.error(Some(unused.span), "dead code")?;
|
self.error(Some(unused.span), "dead code")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node)));
|
Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node)))
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,10 +678,16 @@ pub(super) fn try_unify<'tcx>(
|
||||||
// we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This
|
// we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This
|
||||||
// means that we only allow inference variables if they are equal.
|
// means that we only allow inference variables if they are equal.
|
||||||
(ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => a_val == b_val,
|
(ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => a_val == b_val,
|
||||||
(
|
// We expand generic anonymous constants at the start of this function, so this
|
||||||
ty::ConstKind::Unevaluated(a_def, a_substs, None),
|
// branch should only be taking when dealing with associated constants, at
|
||||||
ty::ConstKind::Unevaluated(b_def, b_substs, None),
|
// which point directly comparing them seems like the desired behavior.
|
||||||
) => a_def == b_def && a_substs == b_substs,
|
//
|
||||||
|
// FIXME(const_evaluatable_checked): This isn't actually the case.
|
||||||
|
// We also take this branch for concrete anonymous constants and
|
||||||
|
// expand generic anonymous constants with concrete substs.
|
||||||
|
(ty::ConstKind::Unevaluated(a_uv), ty::ConstKind::Unevaluated(b_uv)) => {
|
||||||
|
a_uv == b_uv
|
||||||
|
}
|
||||||
// FIXME(const_evaluatable_checked): We may want to either actually try
|
// FIXME(const_evaluatable_checked): We may want to either actually try
|
||||||
// to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like
|
// to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like
|
||||||
// this, for now we just return false here.
|
// this, for now we just return false here.
|
||||||
|
|
|
@ -516,15 +516,13 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
// if the constants depend on generic parameters.
|
// if the constants depend on generic parameters.
|
||||||
//
|
//
|
||||||
// Let's just see where this breaks :shrug:
|
// Let's just see where this breaks :shrug:
|
||||||
if let (
|
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
|
||||||
ty::ConstKind::Unevaluated(a_def, a_substs, None),
|
(c1.val, c2.val)
|
||||||
ty::ConstKind::Unevaluated(b_def, b_substs, None),
|
|
||||||
) = (c1.val, c2.val)
|
|
||||||
{
|
{
|
||||||
if self
|
if self
|
||||||
.selcx
|
.selcx
|
||||||
.tcx()
|
.tcx()
|
||||||
.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs)))
|
.try_unify_abstract_consts(((a.def, a.substs), (b.def, b.substs)))
|
||||||
{
|
{
|
||||||
return ProcessResult::Changed(vec![]);
|
return ProcessResult::Changed(vec![]);
|
||||||
}
|
}
|
||||||
|
@ -534,7 +532,12 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
let stalled_on = &mut pending_obligation.stalled_on;
|
let stalled_on = &mut pending_obligation.stalled_on;
|
||||||
|
|
||||||
let mut evaluate = |c: &'tcx Const<'tcx>| {
|
let mut evaluate = |c: &'tcx Const<'tcx>| {
|
||||||
if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val {
|
if let ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||||
|
def,
|
||||||
|
substs,
|
||||||
|
promoted,
|
||||||
|
}) = c.val
|
||||||
|
{
|
||||||
match self.selcx.infcx().const_eval_resolve(
|
match self.selcx.infcx().const_eval_resolve(
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
def,
|
def,
|
||||||
|
|
|
@ -556,7 +556,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts");
|
debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts");
|
||||||
|
|
||||||
let evaluate = |c: &'tcx ty::Const<'tcx>| {
|
let evaluate = |c: &'tcx ty::Const<'tcx>| {
|
||||||
if let ty::ConstKind::Unevaluated(def, substs, promoted) = c.val {
|
if let ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||||
|
def,
|
||||||
|
substs,
|
||||||
|
promoted,
|
||||||
|
}) = c.val
|
||||||
|
{
|
||||||
self.infcx
|
self.infcx
|
||||||
.const_eval_resolve(
|
.const_eval_resolve(
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
|
|
|
@ -430,7 +430,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||||
|
|
||||||
GenericArgKind::Const(constant) => {
|
GenericArgKind::Const(constant) => {
|
||||||
match constant.val {
|
match constant.val {
|
||||||
ty::ConstKind::Unevaluated(def, substs, promoted) => {
|
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
|
||||||
assert!(promoted.is_none());
|
assert!(promoted.is_none());
|
||||||
|
|
||||||
let obligations = self.nominal_obligations(def.did, substs);
|
let obligations = self.nominal_obligations(def.did, substs);
|
||||||
|
|
|
@ -2212,10 +2212,11 @@ fn const_evaluatable_predicates_of<'tcx>(
|
||||||
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
|
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
|
||||||
let def_id = self.tcx.hir().local_def_id(c.hir_id);
|
let def_id = self.tcx.hir().local_def_id(c.hir_id);
|
||||||
let ct = ty::Const::from_anon_const(self.tcx, def_id);
|
let ct = ty::Const::from_anon_const(self.tcx, def_id);
|
||||||
if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val {
|
if let ty::ConstKind::Unevaluated(uv) = ct.val {
|
||||||
|
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::PredicateKind::ConstEvaluatable(def, substs).to_predicate(self.tcx),
|
ty::PredicateKind::ConstEvaluatable(uv.def, uv.substs).to_predicate(self.tcx),
|
||||||
span,
|
span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue