Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extract ConstKind::Unevaluated into a struct #83040

Merged
merged 3 commits into from
Mar 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions compiler/rustc_codegen_cranelift/src/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
};
match const_.val {
ConstKind::Value(_) => {}
ConstKind::Unevaluated(def, ref substs, promoted) => {
ConstKind::Unevaluated(unevaluated) => {
if let Err(err) =
fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), def, substs, promoted, None)
fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None)
{
all_constants_ok = false;
match err {
Expand Down Expand Up @@ -122,14 +122,14 @@ pub(crate) fn codegen_constant<'tcx>(
};
let const_val = match const_.val {
ConstKind::Value(const_val) => const_val,
ConstKind::Unevaluated(def, ref substs, promoted) if fx.tcx.is_static(def.did) => {
ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) if fx.tcx.is_static(def.did) => {
assert!(substs.is_empty());
assert!(promoted.is_none());

return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx);
}
ConstKind::Unevaluated(def, ref substs, promoted) => {
match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), def, substs, promoted, None) {
ConstKind::Unevaluated(unevaluated) => {
match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
Ok(const_val) => const_val,
Err(_) => {
span_bug!(constant.span, "erroneous constant not captured by required_consts");
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/mir/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::ConstantKind::Val(val, _) => return Ok(val),
};
match ct.val {
ty::ConstKind::Unevaluated(def, substs, promoted) => self
ty::ConstKind::Unevaluated(ct) => self
.cx
.tcx()
.const_eval_resolve(ty::ParamEnv::reveal_all(), def, substs, promoted, None)
.const_eval_resolve(ty::ParamEnv::reveal_all(), ct, None)
.map_err(|err| {
self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
err
Expand Down
7 changes: 2 additions & 5 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
use rustc_middle::mir;
use rustc_middle::mir::interpret::EvalToConstValueResult;
use rustc_middle::traits::select;
use rustc_middle::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
Expand Down Expand Up @@ -1499,9 +1498,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn const_eval_resolve(
&self,
param_env: ty::ParamEnv<'tcx>,
def: ty::WithOptConstParam<DefId>,
substs: SubstsRef<'tcx>,
promoted: Option<mir::Promoted>,
ty::Unevaluated { def, substs, promoted }: ty::Unevaluated<'tcx>,
span: Option<Span>,
) -> EvalToConstValueResult<'tcx> {
let mut original_values = OriginalQueryValues::default();
Expand All @@ -1510,7 +1507,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let (param_env, substs) = canonical.value;
// The return value is the evaluated value which doesn't contain any reference to inference
// variables, thus we don't need to substitute back the original values.
self.tcx.const_eval_resolve(param_env, def, substs, promoted, span)
self.tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, span)
}

/// If `typ` is a type variable of some kind, resolve it one level
Expand Down
10 changes: 4 additions & 6 deletions compiler/rustc_middle/src/mir/interpret/queries.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::{ErrorHandled, EvalToConstValueResult, GlobalId};

use crate::mir;
use crate::ty::subst::{InternalSubsts, SubstsRef};
use crate::ty::subst::InternalSubsts;
use crate::ty::{self, TyCtxt};
use rustc_hir::def_id::DefId;
use rustc_span::Span;
Expand Down Expand Up @@ -35,14 +35,12 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn const_eval_resolve(
self,
param_env: ty::ParamEnv<'tcx>,
def: ty::WithOptConstParam<DefId>,
substs: SubstsRef<'tcx>,
promoted: Option<mir::Promoted>,
ct: ty::Unevaluated<'tcx>,
span: Option<Span>,
) -> EvalToConstValueResult<'tcx> {
match ty::Instance::resolve_opt_const_arg(self, param_env, def, substs) {
match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted };
let cid = GlobalId { instance, promoted: ct.promoted };
self.const_eval_global_id(param_env, cid, span)
}
Ok(None) => Err(ErrorHandled::TooGeneric),
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,18 @@ impl<'tcx> Const<'tcx> {
let name = tcx.hir().name(hir_id);
ty::ConstKind::Param(ty::ParamConst::new(index, name))
}
_ => ty::ConstKind::Unevaluated(
def.to_global(),
InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
None,
),
_ => ty::ConstKind::Unevaluated(ty::Unevaluated {
def: def.to_global(),
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
promoted: None,
}),
};

tcx.mk_const(ty::Const { val, ty })
}

#[inline]
/// Interns the given value as a constant.
#[inline]
pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self {
tcx.mk_const(Self { val: ConstKind::Value(val), ty })
}
Expand Down
19 changes: 14 additions & 5 deletions compiler/rustc_middle/src/ty/consts/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,18 @@ use rustc_macros::HashStable;
use rustc_target::abi::Size;

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.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
#[derive(HashStable)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
#[derive(Hash, HashStable)]
pub enum ConstKind<'tcx> {
/// A const generic parameter.
Param(ty::ParamConst),
Expand All @@ -31,7 +39,7 @@ pub enum ConstKind<'tcx> {

/// 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.
Unevaluated(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>, Option<Promoted>),
Unevaluated(Unevaluated<'tcx>),

/// Used to hold computed value.
Value(ConstValue<'tcx>),
Expand Down Expand Up @@ -102,7 +110,7 @@ impl<'tcx> ConstKind<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
) -> 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;

// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
Expand Down Expand Up @@ -132,7 +140,8 @@ impl<'tcx> ConstKind<'tcx> {
let (param_env, substs) = param_env_and_substs.into_parts();
// try to resolve e.g. associated constants to their definition on an impl, and then
// evaluate the const.
match tcx.const_eval_resolve(param_env, def, substs, promoted, None) {
match tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, None)
{
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
// and we use the original type, so nothing from `substs`
// (which may be identity substs, see above),
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_middle/src/ty/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,7 @@ impl FlagComputation {
fn add_const(&mut self, c: &ty::Const<'_>) {
self.add_ty(c.ty);
match c.val {
ty::ConstKind::Unevaluated(_, substs, _) => {
self.add_substs(substs);
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
}
ty::ConstKind::Unevaluated(unevaluated) => self.add_unevaluated_const(unevaluated),
ty::ConstKind::Infer(infer) => {
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
match infer {
Expand All @@ -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<'_>) {
self.add_substs(projection.substs);
self.add_ty(projection.ty);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub use rustc_type_ir::*;

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::{
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -915,7 +915,7 @@ pub trait PrettyPrinter<'tcx>:
}

match ct.val {
ty::ConstKind::Unevaluated(def, substs, promoted) => {
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
if let Some(promoted) = promoted {
p!(print_value_path(def.did, substs));
p!(write("::{:?}", promoted));
Expand Down
24 changes: 13 additions & 11 deletions compiler/rustc_middle/src/ty/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,24 +531,26 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
check_const_value_eq(relation, a_val, b_val, a, b)?
}

(
ty::ConstKind::Unevaluated(a_def, a_substs, None),
ty::ConstKind::Unevaluated(b_def, b_substs, None),
) if tcx.features().const_evaluatable_checked && !relation.visit_ct_substs() => {
tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs)))
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
if tcx.features().const_evaluatable_checked && !relation.visit_ct_substs() =>
Comment on lines +534 to +535
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you lost the check for !promoted, though afaict you can just assert that actually

{
tcx.try_unify_abstract_consts(((au.def, au.substs), (bu.def, bu.substs)))
}

// 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
// be stabilized.
(
ty::ConstKind::Unevaluated(a_def, a_substs, a_promoted),
ty::ConstKind::Unevaluated(b_def, b_substs, b_promoted),
) if a_def == b_def && a_promoted == b_promoted => {
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
if au.def == bu.def && au.promoted == bu.promoted =>
{
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 {
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,
}));
}
Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_middle/src/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1031,8 +1031,12 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
match self {
ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)),
ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)),
ty::ConstKind::Unevaluated(did, substs, promoted) => {
ty::ConstKind::Unevaluated(did, substs.fold_with(folder), promoted)
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
ty::ConstKind::Unevaluated(ty::Unevaluated {
def,
substs: substs.fold_with(folder),
promoted,
})
}
ty::ConstKind::Value(_)
| ty::ConstKind::Bound(..)
Expand All @@ -1045,7 +1049,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
match *self {
ty::ConstKind::Infer(ic) => ic.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::Bound(..)
| ty::ConstKind::Placeholder(_)
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,8 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
| ty::ConstKind::Value(_)
| ty::ConstKind::Error(_) => {}

ty::ConstKind::Unevaluated(_, substs, _) => {
stack.extend(substs.iter().rev());
ty::ConstKind::Unevaluated(ct) => {
stack.extend(ct.substs.iter().rev());
}
}
}
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_mir/src/borrow_check/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,14 +316,12 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
let tcx = self.tcx();
let maybe_uneval = match constant.literal {
ConstantKind::Ty(ct) => match ct.val {
ty::ConstKind::Unevaluated(def, substs, promoted) => {
Some((def, substs, promoted))
}
ty::ConstKind::Unevaluated(uv) => Some(uv),
_ => 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 {
let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
promoted: &Body<'tcx>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir/src/interpret/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
match val.val {
ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
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)?;
Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into())
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_mir/src/monomorphize/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,8 +646,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {

match substituted_constant.val {
ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output),
ty::ConstKind::Unevaluated(def, substs, promoted) => {
match self.tcx.const_eval_resolve(param_env, def, substs, promoted, None) {
ty::ConstKind::Unevaluated(unevaluated) => {
match self.tcx.const_eval_resolve(param_env, unevaluated, None) {
Ok(val) => collect_const_value(self.tcx, val, self.output),
Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => {}
Err(ErrorHandled::TooGeneric) => span_bug!(
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_mir/src/monomorphize/polymorphize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
self.unused_parameters.clear(param.index);
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:
// `<Self as Foo<T>>::foo::promoted[p]`
if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
Expand All @@ -310,10 +310,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
self.visit_body(&promoted[p]);
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 =>
{
self.visit_child_body(def.did, unevaluated_substs);
self.visit_child_body(def.did, substs);
ControlFlow::CONTINUE
}
_ => c.super_visit_with(self),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir/src/transform/check_consts/qualifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ where

// Check the qualifs of the value of `const` items.
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());
// Don't peek inside trait associated constants.
if cx.tcx.trait_of_item(def.did).is_none() {
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_mir/src/transform/const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
let lint_only = match c.literal {
ConstantKind::Ty(ct) => match ct.val {
// 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
// generic functions using associated constants of the generic parameters.
_ => c.literal.needs_subst(),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir/src/transform/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ impl Inliner<'tcx> {
caller_body.required_consts.extend(
callee_body.required_consts.iter().copied().filter(|&ct| {
match ct.literal.const_for_ty() {
Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_, _, _)),
Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_)),
None => true,
}
}),
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_mir/src/transform/promote_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1001,17 +1001,17 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
literal: tcx
.mk_const(ty::Const {
ty,
val: ty::ConstKind::Unevaluated(
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
def,
InternalSubsts::for_item(tcx, def.did, |param, _| {
substs: InternalSubsts::for_item(tcx, def.did, |param, _| {
if let ty::GenericParamDefKind::Lifetime = param.kind {
tcx.lifetimes.re_erased.into()
} else {
tcx.mk_param_from_def(param)
}
}),
Some(promoted_id),
),
promoted: Some(promoted_id),
}),
})
.into(),
}))
Expand Down
Loading