make unevaluated const substs optional

This commit is contained in:
lcnr 2021-03-16 00:05:45 +01:00
parent f4b606fd17
commit bfaf13af4e
46 changed files with 234 additions and 188 deletions

View file

@ -129,13 +129,13 @@ pub(crate) fn codegen_constant<'tcx>(
};
let const_val = match const_.val {
ConstKind::Value(const_val) => const_val,
ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
if fx.tcx.is_static(def.did) =>
ConstKind::Unevaluated(uv)
if fx.tcx.is_static(uv.def.did) =>
{
assert!(substs.is_empty());
assert!(promoted.is_none());
assert!(uv.substs(fx.tcx).is_empty());
assert!(uv.promoted.is_none());
return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx);
return codegen_static_ref(fx, uv.def.did, fx.layout_of(const_.ty)).to_cvalue(fx);
}
ConstKind::Unevaluated(unevaluated) => {
match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {

View file

@ -742,10 +742,9 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
}
}
}
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
if self.tcx().lazy_normalization() =>
{
assert_eq!(promoted, None);
ty::ConstKind::Unevaluated(uv) if self.tcx().lazy_normalization() => {
assert_eq!(uv.promoted, None);
let substs = uv.substs(self.tcx());
let substs = self.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
@ -754,7 +753,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
)?;
Ok(self.tcx().mk_const(ty::Const {
ty: c.ty,
val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(uv.def, substs)),
}))
}
_ => relate::super_relate_consts(self, c, c),
@ -976,10 +975,9 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
}
}
}
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
if self.tcx().lazy_normalization() =>
{
assert_eq!(promoted, None);
ty::ConstKind::Unevaluated(uv) if self.tcx().lazy_normalization() => {
assert_eq!(uv.promoted, None);
let substs = uv.substs(self.tcx());
let substs = self.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
@ -988,7 +986,7 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
)?;
Ok(self.tcx().mk_const(ty::Const {
ty: c.ty,
val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(uv.def, substs)),
}))
}
_ => relate::super_relate_consts(self, c, c),

View file

@ -1537,8 +1537,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> {
self.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {

View file

@ -479,8 +479,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
pub(super) struct TraitObjectVisitor(pub(super) FxHashSet<DefId>);
impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> {
bug!("tcx_for_anon_const_substs called for TraitObjectVisitor");
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
// The default anon const substs cannot include
// trait objects, so we don't have to bother looking.
None
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {

View file

@ -679,7 +679,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
b: ty::Unevaluated<'tcx>,
) -> bool {
let canonical = self.canonicalize_query(
((a.def, a.substs), (b.def, b.substs)),
((a.def, a.substs(self.tcx)), (b.def, b.substs(self.tcx))),
&mut OriginalQueryValues::default(),
);
debug!("canonical consts: {:?}", &canonical.value);
@ -1592,16 +1592,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn const_eval_resolve(
&self,
param_env: ty::ParamEnv<'tcx>,
ty::Unevaluated { def, substs, promoted }: ty::Unevaluated<'tcx>,
unevaluated: ty::Unevaluated<'tcx>,
span: Option<Span>,
) -> EvalToConstValueResult<'tcx> {
let mut original_values = OriginalQueryValues::default();
let canonical = self.canonicalize_query((param_env, substs), &mut original_values);
let canonical = self.canonicalize_query((param_env, unevaluated), &mut original_values);
let (param_env, substs) = canonical.value;
let (param_env, unevaluated) = 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, ty::Unevaluated { def, substs, promoted }, span)
self.tcx.const_eval_resolve(param_env, unevaluated, span)
}
/// If `typ` is a type variable of some kind, resolve it one level

View file

@ -766,8 +766,8 @@ struct ScopeInstantiator<'me, 'tcx> {
}
impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> {
self.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
fn visit_binder<T: TypeFoldable<'tcx>>(

View file

@ -127,8 +127,8 @@ impl<'a, 'tcx> UnresolvedTypeFinder<'a, 'tcx> {
impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
type BreakTy = (Ty<'tcx>, Option<Span>);
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.infcx.tcx)
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {

View file

@ -1160,8 +1160,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
type BreakTy = Ty<'tcx>;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.cx.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.cx.tcx)
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {

View file

@ -38,7 +38,7 @@ impl<'tcx> TyCtxt<'tcx> {
ct: ty::Unevaluated<'tcx>,
span: Option<Span>,
) -> EvalToConstValueResult<'tcx> {
match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs(self)) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: ct.promoted };
self.const_eval_global_id(param_env, cid, span)

View file

@ -114,6 +114,10 @@ rustc_queries! {
desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param) }
}
query default_anon_const_substs(key: DefId) -> SubstsRef<'tcx> {
desc { |tcx| "computing the default generic arguments for `{}`", tcx.def_path_str(key) }
}
/// Records the type of every item.
query type_of(key: DefId) -> Ty<'tcx> {
desc { |tcx| "computing type of `{}`", tcx.def_path_str(key) }

View file

@ -1,6 +1,5 @@
use crate::mir::interpret::ConstValue;
use crate::mir::interpret::{LitToConstInput, Scalar};
use crate::ty::subst::InternalSubsts;
use crate::ty::{self, Ty, TyCtxt};
use crate::ty::{ParamEnv, ParamEnvAnd};
use rustc_errors::ErrorReported;
@ -100,7 +99,7 @@ impl<'tcx> Const<'tcx> {
}
_ => ty::ConstKind::Unevaluated(ty::Unevaluated {
def: def.to_global(),
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
substs_: None,
promoted: None,
}),
};

View file

@ -16,10 +16,23 @@ use super::ScalarInt;
#[derive(Hash, HashStable)]
pub struct Unevaluated<'tcx> {
pub def: ty::WithOptConstParam<DefId>,
pub substs: SubstsRef<'tcx>,
pub substs_: Option<SubstsRef<'tcx>>,
pub promoted: Option<Promoted>,
}
impl<'tcx> Unevaluated<'tcx> {
pub fn new(def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx> {
Unevaluated { def, substs_: Some(substs), promoted: None }
}
pub fn substs(self, tcx: TyCtxt<'tcx>) -> SubstsRef<'tcx> {
self.substs_.unwrap_or_else(|| {
debug_assert_eq!(self.promoted, None);
tcx.default_anon_const_substs(self.def.did)
})
}
}
/// Represents a constant in Rust.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
#[derive(Hash, HashStable)]
@ -109,7 +122,7 @@ impl<'tcx> ConstKind<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
) -> 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;
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
@ -118,29 +131,32 @@ impl<'tcx> ConstKind<'tcx> {
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
// so that we don't try to invoke this query with
// any region variables.
let param_env_and_substs = tcx
let param_env_and = tcx
.erase_regions(param_env)
.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,
// attempt using identity substs and `ParamEnv` instead, that will succeed
// when the expression doesn't depend on any parameters.
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
// we can call `infcx.const_eval_resolve` which handles inference variables.
let param_env_and_substs = if param_env_and_substs.needs_infer() {
tcx.param_env(def.did).and(InternalSubsts::identity_for_item(tcx, def.did))
let param_env_and = if param_env_and.needs_infer() {
tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
def: unevaluated.def,
substs_: Some(InternalSubsts::identity_for_item(tcx, unevaluated.def.did)),
promoted: unevaluated.promoted,
})
} else {
param_env_and_substs
param_env_and
};
// FIXME(eddyb) maybe the `const_eval_*` methods should take
// `ty::ParamEnvAnd<SubstsRef>` instead of having them separate.
let (param_env, substs) = param_env_and_substs.into_parts();
// `ty::ParamEnvAnd` instead of having them separate.
let (param_env, unevaluated) = param_env_and.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, ty::Unevaluated { def, substs, promoted }, None)
{
match tcx.const_eval_resolve(param_env, unevaluated, 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),

View file

@ -305,7 +305,8 @@ impl FlagComputation {
}
fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) {
self.add_substs(ct.substs);
// TODO
self.add_substs(ct.substs_.unwrap());
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
}

View file

@ -192,9 +192,11 @@ pub trait TypeVisitor<'tcx>: Sized {
/// Supplies the `tcx` for an unevaluated anonymous constant in case its default substs
/// are not yet supplied.
///
/// Visitors which do not look into these substs may leave this unimplemented, so be
/// careful when calling this method elsewhere.
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx>;
/// Visitors which do not look into these substs may return `None` here, in which case
/// `super_visit_with` completely skips the default substs. Incorrectly returning
/// `None` can very quickly lead to ICE or other critical bugs, so be careful and
/// try to return an actual `tcx` if at all possible.
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>>;
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
@ -336,8 +338,8 @@ impl<'tcx> TyCtxt<'tcx> {
{
type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
fn visit_binder<T: TypeFoldable<'tcx>>(
@ -788,8 +790,9 @@ impl<'tcx> ValidateBoundVars<'tcx> {
impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
bug!("default anon const substs can't contain bound vars");
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
// Anonymous constants do not contain bound vars in their substs by default.
None
}
fn visit_binder<T: TypeFoldable<'tcx>>(
@ -1006,8 +1009,9 @@ struct HasEscapingVarsVisitor {
impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
type BreakTy = FoundEscapingVars;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
bug!("tcx_for_anon_const_substs called for HasEscpaingVarsVisitor");
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
// Anonymous constants do not contain bound vars in their substs by default.
None
}
fn visit_binder<T: TypeFoldable<'tcx>>(
@ -1080,8 +1084,13 @@ struct HasTypeFlagsVisitor {
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
type BreakTy = FoundFlags;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
bug!("tcx_for_anon_const_substs called for HasTypeFlagsVisitor");
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
// TypeFlagsVisitor must not look into the default anon const substs
// as that would cause cycle errors, but we do care about them for
// some flags.
//
// We therefore have to be very careful here.
None
}
#[inline]
@ -1164,8 +1173,8 @@ impl LateBoundRegionsCollector<'tcx> {
}
impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector<'tcx> {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
fn visit_binder<T: TypeFoldable<'tcx>>(

View file

@ -927,29 +927,28 @@ pub trait PrettyPrinter<'tcx>:
}
match ct.val {
ty::ConstKind::Unevaluated(ty::Unevaluated {
def,
substs,
promoted: Some(promoted),
}) => {
p!(print_value_path(def.did, substs));
p!(write("::{:?}", promoted));
}
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None }) => {
match self.tcx().def_kind(def.did) {
DefKind::Static | DefKind::Const | DefKind::AssocConst => {
p!(print_value_path(def.did, substs))
}
_ => {
if def.is_local() {
let span = self.tcx().def_span(def.did);
if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
p!(write("{}", snip))
ty::ConstKind::Unevaluated(uv) => {
if let Some(promoted) = uv.promoted {
let substs = uv.substs_.unwrap();
p!(print_value_path(uv.def.did, substs));
p!(write("::{:?}", promoted));
} else {
let tcx = self.tcx();
match tcx.def_kind(uv.def.did) {
DefKind::Static | DefKind::Const | DefKind::AssocConst => {
p!(print_value_path(uv.def.did, uv.substs(tcx)))
}
_ => {
if uv.def.is_local() {
let span = tcx.def_span(uv.def.did);
if let Ok(snip) = tcx.sess.source_map().span_to_snippet(span) {
p!(write("{}", snip))
} else {
print_underscore!()
}
} else {
print_underscore!()
}
} else {
print_underscore!()
}
}
}
@ -2025,8 +2024,8 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {

View file

@ -579,7 +579,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
if tcx.features().const_evaluatable_checked =>
{
tcx.try_unify_abstract_consts(((au.def, au.substs), (bu.def, bu.substs)))
tcx.try_unify_abstract_consts(((au.def, au.substs(tcx)), (bu.def, bu.substs(tcx))))
}
// While this is slightly incorrect, it shouldn't matter for `min_const_generics`
@ -591,13 +591,13 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
let substs = relation.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
au.substs,
bu.substs,
au.substs(tcx),
bu.substs(tcx),
)?;
return Ok(tcx.mk_const(ty::Const {
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
def: au.def,
substs,
substs_: Some(substs),
promoted: au.promoted,
}),
ty: a.ty,

View file

@ -1046,13 +1046,7 @@ 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(ty::Unevaluated { def, substs, promoted }) => {
ty::ConstKind::Unevaluated(ty::Unevaluated {
def,
substs: substs.fold_with(folder),
promoted,
})
}
ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.fold_with(folder)),
ty::ConstKind::Value(_)
| ty::ConstKind::Bound(..)
| ty::ConstKind::Placeholder(..)
@ -1064,7 +1058,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(ct) => ct.substs.visit_with(visitor),
ty::ConstKind::Unevaluated(uv) => uv.visit_with(visitor),
ty::ConstKind::Value(_)
| ty::ConstKind::Bound(..)
| ty::ConstKind::Placeholder(_)
@ -1082,3 +1076,24 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
ControlFlow::CONTINUE
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
ty::Unevaluated {
def: self.def,
substs_: Some(self.substs(folder.tcx()).fold_with(folder)),
promoted: self.promoted,
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
if let Some(tcx) = visitor.tcx_for_anon_const_substs() {
self.substs(tcx).visit_with(visitor)
} else if let Some(substs) = self.substs_ {
substs.visit_with(visitor)
} else {
debug!("ignoring default substs of `{:?}`", self.def);
ControlFlow::CONTINUE
}
}
}

View file

@ -196,7 +196,8 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
| ty::ConstKind::Error(_) => {}
ty::ConstKind::Unevaluated(ct) => {
stack.extend(ct.substs.iter().rev());
// TODO
stack.extend(ct.substs_.unwrap().iter().rev());
}
}
}

View file

@ -377,8 +377,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
},
_ => None,
};
if let Some(ty::Unevaluated { def, substs, promoted }) = maybe_uneval {
if let Some(promoted) = promoted {
if let Some(uv) = maybe_uneval {
if let Some(promoted) = uv.promoted {
let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
promoted: &Body<'tcx>,
ty,
@ -413,8 +413,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
ConstraintCategory::Boring,
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
constant.literal.ty(),
def.did,
UserSubsts { substs, user_self_ty: None },
uv.def.did,
UserSubsts { substs: uv.substs(self.tcx()), user_self_ty: None },
)),
) {
span_mirbug!(

View file

@ -555,9 +555,9 @@ 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(ty::Unevaluated { def, substs, promoted }) => {
let instance = self.resolve(def, substs)?;
Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into())
ty::ConstKind::Unevaluated(uv) => {
let instance = self.resolve(uv.def, uv.substs(*self.tcx))?;
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
}
ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => {
span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", val)

View file

@ -21,8 +21,8 @@ where
impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> {
type BreakTy = FoundParam;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {

View file

@ -283,8 +283,8 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
}
impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
#[instrument(skip(self))]
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
@ -298,7 +298,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
self.unused_parameters.clear(param.index);
ControlFlow::CONTINUE
}
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: 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 =>
@ -309,10 +309,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
self.visit_body(&promoted[p]);
ControlFlow::CONTINUE
}
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None })
if self.tcx.def_kind(def.did) == DefKind::AnonConst =>
ty::ConstKind::Unevaluated(uv)
if self.tcx.def_kind(uv.def.did) == DefKind::AnonConst =>
{
self.visit_child_body(def.did, substs);
self.visit_child_body(uv.def.did, uv.substs(self.tcx));
ControlFlow::CONTINUE
}
_ => c.super_visit_with(self),
@ -357,8 +357,8 @@ struct HasUsedGenericParams<'a, 'tcx> {
impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> {
type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
#[instrument(skip(self))]

View file

@ -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(ty::Unevaluated { def, substs: _, 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() {

View file

@ -483,7 +483,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
// Promoteds must lint and not error as the user didn't ask for them
ConstKind::Unevaluated(ty::Unevaluated {
def: _,
substs: _,
substs_: _,
promoted: Some(_),
}) => true,
// Out of backwards compatibility we cannot report hard errors in unused

View file

@ -859,13 +859,17 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
ty,
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
def,
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)
}
}),
substs_: Some(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)
}
},
)),
promoted: Some(promoted_id),
}),
})

View file

@ -475,7 +475,7 @@ impl Visitor<'tcx> for ExtraComments<'tcx> {
ty::ConstKind::Unevaluated(uv) => format!(
"Unevaluated({}, {:?}, {:?})",
self.tcx.def_path_str(uv.def.did),
uv.substs,
uv.substs(self.tcx),
uv.promoted
),
ty::ConstKind::Value(val) => format!("Value({:?})", val),
@ -682,8 +682,10 @@ pub fn write_allocations<'tcx>(
}
struct CollectAllocIds(BTreeSet<AllocId>);
impl<'tcx> TypeVisitor<'tcx> for CollectAllocIds {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
bug!("tcx_for_anon_const_substs called for CollectAllocIds")
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
// `AllocId`s are only inside of `ConstKind::Value` which
// can't be part of the anon const default substs.
None
}
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {

View file

@ -693,11 +693,10 @@ impl<'tcx> Cx<'tcx> {
// and not the beginning of discriminants (which is always `0`)
let substs = InternalSubsts::identity_for_item(self.tcx(), did);
let lhs = ty::Const {
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
def: ty::WithOptConstParam::unknown(did),
val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(
ty::WithOptConstParam::unknown(did),
substs,
promoted: None,
}),
)),
ty: var_ty,
};
let lhs = self.thir.exprs.push(mk_const(self.tcx().mk_const(lhs)));
@ -889,11 +888,10 @@ impl<'tcx> Cx<'tcx> {
debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
ExprKind::Literal {
literal: self.tcx.mk_const(ty::Const {
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
def: ty::WithOptConstParam::unknown(def_id),
val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(
ty::WithOptConstParam::unknown(def_id),
substs,
promoted: None,
}),
)),
ty: self.typeck_results().node_type(expr.hir_id),
}),
user_ty,

View file

@ -179,8 +179,8 @@ where
{
type BreakTy = V::BreakTy;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.def_id_visitor.tcx()
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.def_id_visitor.tcx())
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> {

View file

@ -558,8 +558,8 @@ impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
where
OP: FnMut(ty::Region<'tcx>),
{
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> {
self.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
fn visit_binder<T: TypeFoldable<'tcx>>(

View file

@ -155,11 +155,8 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
// and hopefully soon change this to an error.
//
// See #74595 for more details about this.
let concrete = infcx.const_eval_resolve(
param_env,
ty::Unevaluated { def, substs, promoted: None },
Some(span),
);
let concrete =
infcx.const_eval_resolve(param_env, ty::Unevaluated::new(def, substs), Some(span));
if concrete.is_ok() && substs.has_param_types_or_consts() {
match infcx.tcx.def_kind(def.did) {
@ -217,9 +214,7 @@ impl AbstractConst<'tcx> {
ct: &ty::Const<'tcx>,
) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
match ct.val {
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: _ }) => {
AbstractConst::new(tcx, def, substs)
}
ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.def, uv.substs(tcx)),
ty::ConstKind::Error(_) => Err(ErrorReported),
_ => Ok(None),
}

View file

@ -570,7 +570,8 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
ty::PredicateKind::ConstEquate(c1, c2) => {
debug!(?c1, ?c2, "equating consts");
if self.selcx.tcx().features().const_evaluatable_checked {
let tcx = self.selcx.tcx();
if tcx.features().const_evaluatable_checked {
// FIXME: we probably should only try to unify abstract constants
// if the constants depend on generic parameters.
//
@ -597,7 +598,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
Err(ErrorHandled::TooGeneric) => {
stalled_on.extend(
unevaluated
.substs
.substs(tcx)
.iter()
.filter_map(TyOrConstInferVar::maybe_from_generic_arg),
);

View file

@ -771,8 +771,8 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> {
type BreakTy = ();
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> {
self.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {

View file

@ -130,8 +130,8 @@ impl Search<'a, 'tcx> {
impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
type BreakTy = NonStructuralMatchTy<'tcx>;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx()
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx())
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {

View file

@ -435,13 +435,14 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
GenericArgKind::Const(constant) => {
match constant.val {
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
assert!(promoted.is_none());
ty::ConstKind::Unevaluated(uv) => {
assert!(uv.promoted.is_none());
let substs = uv.substs(self.tcx());
let obligations = self.nominal_obligations(def.did, substs);
let obligations = self.nominal_obligations(uv.def.did, substs);
self.out.extend(obligations);
let predicate = ty::PredicateKind::ConstEvaluatable(def, substs)
let predicate = ty::PredicateKind::ConstEvaluatable(uv.def, substs)
.to_predicate(self.tcx());
let cause = self.cause(traits::MiscObligation);
self.out.push(traits::Obligation::with_depth(

View file

@ -854,8 +854,8 @@ impl<'tcx> BoundVarsCollector<'tcx> {
}
impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
fn visit_binder<T: TypeFoldable<'tcx>>(
@ -1076,8 +1076,9 @@ impl PlaceholdersCollector {
}
impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
bug!("tcx_for_anon_const_substs called for PlaceholdersCollector");
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
// Anon const substs do not contain placeholders by default.
None
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {

View file

@ -54,8 +54,9 @@ impl<'tcx> BoundVarsCollector<'tcx> {
impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
bug!("default anon const substs can't be bound vars");
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
// Anon const substs do not contain bound vars by default.
None
}
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,

View file

@ -473,8 +473,8 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
struct FindParentLifetimeVisitor<'tcx>(TyCtxt<'tcx>, &'tcx ty::Generics);
impl<'tcx> ty::fold::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> {
type BreakTy = FoundParentLifetime;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.0
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.0)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
@ -510,8 +510,8 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
type BreakTy = Ty<'tcx>;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@ -1584,10 +1584,11 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
.filter_map(|e| typeck_results.node_type_opt(e.hir_id).map(|t| (e.span, t)))
.filter(|(_, ty)| !matches!(ty.kind(), ty::Never))
{
struct VisitTypes(Vec<DefId>);
impl<'tcx> ty::fold::TypeVisitor<'tcx> for VisitTypes {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
bug!("tcx_for_anon_const_substs called for VisitTypes");
struct OpaqueTypeCollector(Vec<DefId>);
impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypeCollector {
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
// Default anon const substs cannot contain opaque types.
None
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match *t.kind() {
@ -1599,7 +1600,7 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
}
}
}
let mut visitor = VisitTypes(vec![]);
let mut visitor = OpaqueTypeCollector(vec![]);
ty.visit_with(&mut visitor);
for def_id in visitor.0 {
let ty_span = tcx.def_span(def_id);

View file

@ -1006,8 +1006,8 @@ fn suggest_constraining_param(
struct TypeParamVisitor<'tcx>(TyCtxt<'tcx>, Vec<Ty<'tcx>>);
impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.0
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.0)
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::Param(_) = ty.kind() {

View file

@ -831,8 +831,8 @@ fn check_where_clauses<'tcx, 'fcx>(
}
impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams<'tcx> {
type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {

View file

@ -68,6 +68,7 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
pub fn provide(providers: &mut Providers) {
*providers = Providers {
opt_const_param_of: type_of::opt_const_param_of,
default_anon_const_substs: type_of::default_anon_const_substs,
type_of: type_of::type_of,
item_bounds: item_bounds::item_bounds,
explicit_item_bounds: item_bounds::explicit_item_bounds,
@ -2355,7 +2356,8 @@ fn const_evaluatable_predicates_of<'tcx>(
assert_eq!(uv.promoted, None);
let span = self.tcx.hir().span(c.hir_id);
self.preds.insert((
ty::PredicateKind::ConstEvaluatable(uv.def, uv.substs).to_predicate(self.tcx),
ty::PredicateKind::ConstEvaluatable(uv.def, uv.substs(self.tcx))
.to_predicate(self.tcx),
span,
));
}

View file

@ -7,7 +7,7 @@ use rustc_hir::intravisit;
use rustc_hir::intravisit::Visitor;
use rustc_hir::{HirId, Node};
use rustc_middle::hir::map::Map;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, SubstsRef};
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder};
use rustc_span::symbol::Ident;
@ -274,6 +274,10 @@ fn get_path_containing_arg_in_pat<'hir>(
arg_path
}
pub(super) fn default_anon_const_substs(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> {
InternalSubsts::identity_for_item(tcx, def_id)
}
pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
let def_id = def_id.expect_local();
use rustc_hir::*;

View file

@ -60,8 +60,8 @@ struct ParameterCollector<'tcx> {
}
impl<'tcx> TypeVisitor<'tcx> for ParameterCollector<'tcx> {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.tcx
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {

View file

@ -287,7 +287,7 @@ crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
match n.val {
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => {
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs_: _, promoted }) => {
let mut s = if let Some(def) = def.as_local() {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def.did);
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(hir_id))

View file

@ -187,11 +187,7 @@ fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: D
let result = cx.tcx.const_eval_resolve(
cx.param_env,
ty::Unevaluated {
def: ty::WithOptConstParam::unknown(def_id),
substs,
promoted: None,
},
ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
None,
);
is_value_unfrozen_raw(cx, result, ty)

View file

@ -705,8 +705,8 @@ struct ContainsRegion<'tcx>(TyCtxt<'tcx>);
impl<'tcx> TypeVisitor<'tcx> for ContainsRegion<'tcx> {
type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> {
self.0
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.0)
}
fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {

View file

@ -346,11 +346,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
.tcx
.const_eval_resolve(
self.param_env,
ty::Unevaluated {
def: ty::WithOptConstParam::unknown(def_id),
substs,
promoted: None,
},
ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
None,
)
.ok()