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 { let const_val = match const_.val {
ConstKind::Value(const_val) => const_val, ConstKind::Value(const_val) => const_val,
ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) ConstKind::Unevaluated(uv)
if fx.tcx.is_static(def.did) => if fx.tcx.is_static(uv.def.did) =>
{ {
assert!(substs.is_empty()); assert!(uv.substs(fx.tcx).is_empty());
assert!(promoted.is_none()); 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) => { ConstKind::Unevaluated(unevaluated) => {
match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) { 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 }) ty::ConstKind::Unevaluated(uv) if self.tcx().lazy_normalization() => {
if self.tcx().lazy_normalization() => assert_eq!(uv.promoted, None);
{ let substs = uv.substs(self.tcx());
assert_eq!(promoted, None);
let substs = self.relate_with_variance( let substs = self.relate_with_variance(
ty::Variance::Invariant, ty::Variance::Invariant,
ty::VarianceDiagInfo::default(), ty::VarianceDiagInfo::default(),
@ -754,7 +753,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
)?; )?;
Ok(self.tcx().mk_const(ty::Const { Ok(self.tcx().mk_const(ty::Const {
ty: c.ty, 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), _ => 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 }) ty::ConstKind::Unevaluated(uv) if self.tcx().lazy_normalization() => {
if self.tcx().lazy_normalization() => assert_eq!(uv.promoted, None);
{ let substs = uv.substs(self.tcx());
assert_eq!(promoted, None);
let substs = self.relate_with_variance( let substs = self.relate_with_variance(
ty::Variance::Invariant, ty::Variance::Invariant,
ty::VarianceDiagInfo::default(), ty::VarianceDiagInfo::default(),
@ -988,7 +986,7 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
)?; )?;
Ok(self.tcx().mk_const(ty::Const { Ok(self.tcx().mk_const(ty::Const {
ty: c.ty, 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), _ => 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> { impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.tcx Some(self.tcx)
} }
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { 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>); pub(super) struct TraitObjectVisitor(pub(super) FxHashSet<DefId>);
impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor { impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
bug!("tcx_for_anon_const_substs called for TraitObjectVisitor"); // 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> { 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>, b: ty::Unevaluated<'tcx>,
) -> bool { ) -> bool {
let canonical = self.canonicalize_query( 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(), &mut OriginalQueryValues::default(),
); );
debug!("canonical consts: {:?}", &canonical.value); debug!("canonical consts: {:?}", &canonical.value);
@ -1592,16 +1592,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn const_eval_resolve( pub fn const_eval_resolve(
&self, &self,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
ty::Unevaluated { def, substs, promoted }: ty::Unevaluated<'tcx>, unevaluated: ty::Unevaluated<'tcx>,
span: Option<Span>, span: Option<Span>,
) -> EvalToConstValueResult<'tcx> { ) -> EvalToConstValueResult<'tcx> {
let mut original_values = OriginalQueryValues::default(); 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 // 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. // 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 /// 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> { impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.tcx Some(self.tcx)
} }
fn visit_binder<T: TypeFoldable<'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> { impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
type BreakTy = (Ty<'tcx>, Option<Span>); type BreakTy = (Ty<'tcx>, Option<Span>);
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.infcx.tcx Some(self.infcx.tcx)
} }
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { 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> { impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
type BreakTy = Ty<'tcx>; type BreakTy = Ty<'tcx>;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.cx.tcx Some(self.cx.tcx)
} }
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { 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>, ct: ty::Unevaluated<'tcx>,
span: Option<Span>, span: Option<Span>,
) -> EvalToConstValueResult<'tcx> { ) -> 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)) => { Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: ct.promoted }; let cid = GlobalId { instance, promoted: ct.promoted };
self.const_eval_global_id(param_env, cid, span) 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) } 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. /// Records the type of every item.
query type_of(key: DefId) -> Ty<'tcx> { query type_of(key: DefId) -> Ty<'tcx> {
desc { |tcx| "computing type of `{}`", tcx.def_path_str(key) } 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::ConstValue;
use crate::mir::interpret::{LitToConstInput, Scalar}; use crate::mir::interpret::{LitToConstInput, Scalar};
use crate::ty::subst::InternalSubsts;
use crate::ty::{self, Ty, TyCtxt}; use crate::ty::{self, Ty, TyCtxt};
use crate::ty::{ParamEnv, ParamEnvAnd}; use crate::ty::{ParamEnv, ParamEnvAnd};
use rustc_errors::ErrorReported; use rustc_errors::ErrorReported;
@ -100,7 +99,7 @@ impl<'tcx> Const<'tcx> {
} }
_ => ty::ConstKind::Unevaluated(ty::Unevaluated { _ => ty::ConstKind::Unevaluated(ty::Unevaluated {
def: def.to_global(), def: def.to_global(),
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), substs_: None,
promoted: None, promoted: None,
}), }),
}; };

View File

@ -16,10 +16,23 @@ use super::ScalarInt;
#[derive(Hash, HashStable)] #[derive(Hash, HashStable)]
pub struct Unevaluated<'tcx> { pub struct Unevaluated<'tcx> {
pub def: ty::WithOptConstParam<DefId>, pub def: ty::WithOptConstParam<DefId>,
pub substs: SubstsRef<'tcx>, pub substs_: Option<SubstsRef<'tcx>>,
pub promoted: Option<Promoted>, 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. /// Represents a constant in Rust.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
#[derive(Hash, HashStable)] #[derive(Hash, HashStable)]
@ -109,7 +122,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 +131,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_: Some(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),

View File

@ -305,7 +305,8 @@ impl FlagComputation {
} }
fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) { 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); 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 /// Supplies the `tcx` for an unevaluated anonymous constant in case its default substs
/// are not yet supplied. /// are not yet supplied.
/// ///
/// Visitors which do not look into these substs may leave this unimplemented, so be /// Visitors which do not look into these substs may return `None` here, in which case
/// careful when calling this method elsewhere. /// `super_visit_with` completely skips the default substs. Incorrectly returning
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx>; /// `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>>( fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self, &mut self,
@ -336,8 +338,8 @@ impl<'tcx> TyCtxt<'tcx> {
{ {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.tcx Some(self.tcx)
} }
fn visit_binder<T: TypeFoldable<'tcx>>( fn visit_binder<T: TypeFoldable<'tcx>>(
@ -788,8 +790,9 @@ impl<'tcx> ValidateBoundVars<'tcx> {
impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> { impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
bug!("default anon const substs can't contain bound vars"); // Anonymous constants do not contain bound vars in their substs by default.
None
} }
fn visit_binder<T: TypeFoldable<'tcx>>( fn visit_binder<T: TypeFoldable<'tcx>>(
@ -1006,8 +1009,9 @@ struct HasEscapingVarsVisitor {
impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
type BreakTy = FoundEscapingVars; type BreakTy = FoundEscapingVars;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
bug!("tcx_for_anon_const_substs called for HasEscpaingVarsVisitor"); // Anonymous constants do not contain bound vars in their substs by default.
None
} }
fn visit_binder<T: TypeFoldable<'tcx>>( fn visit_binder<T: TypeFoldable<'tcx>>(
@ -1080,8 +1084,13 @@ struct HasTypeFlagsVisitor {
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
type BreakTy = FoundFlags; type BreakTy = FoundFlags;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
bug!("tcx_for_anon_const_substs called for HasTypeFlagsVisitor"); // 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] #[inline]
@ -1164,8 +1173,8 @@ impl LateBoundRegionsCollector<'tcx> {
} }
impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector<'tcx> { impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector<'tcx> {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.tcx Some(self.tcx)
} }
fn visit_binder<T: TypeFoldable<'tcx>>( fn visit_binder<T: TypeFoldable<'tcx>>(

View File

@ -927,29 +927,28 @@ pub trait PrettyPrinter<'tcx>:
} }
match ct.val { match ct.val {
ty::ConstKind::Unevaluated(ty::Unevaluated { ty::ConstKind::Unevaluated(uv) => {
def, if let Some(promoted) = uv.promoted {
substs, let substs = uv.substs_.unwrap();
promoted: Some(promoted), p!(print_value_path(uv.def.did, substs));
}) => { p!(write("::{:?}", promoted));
p!(print_value_path(def.did, substs)); } else {
p!(write("::{:?}", promoted)); let tcx = self.tcx();
} match tcx.def_kind(uv.def.did) {
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None }) => { DefKind::Static | DefKind::Const | DefKind::AssocConst => {
match self.tcx().def_kind(def.did) { p!(print_value_path(uv.def.did, uv.substs(tcx)))
DefKind::Static | DefKind::Const | DefKind::AssocConst => { }
p!(print_value_path(def.did, substs)) _ => {
} if uv.def.is_local() {
_ => { let span = tcx.def_span(uv.def.did);
if def.is_local() { if let Ok(snip) = tcx.sess.source_map().span_to_snippet(span) {
let span = self.tcx().def_span(def.did); p!(write("{}", snip))
if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) { } else {
p!(write("{}", snip)) print_underscore!()
}
} else { } else {
print_underscore!() 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> { impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.tcx Some(self.tcx)
} }
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { 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)) (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
if tcx.features().const_evaluatable_checked => 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` // 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( let substs = relation.relate_with_variance(
ty::Variance::Invariant, ty::Variance::Invariant,
ty::VarianceDiagInfo::default(), ty::VarianceDiagInfo::default(),
au.substs, au.substs(tcx),
bu.substs, bu.substs(tcx),
)?; )?;
return Ok(tcx.mk_const(ty::Const { return Ok(tcx.mk_const(ty::Const {
val: ty::ConstKind::Unevaluated(ty::Unevaluated { val: ty::ConstKind::Unevaluated(ty::Unevaluated {
def: au.def, def: au.def,
substs, substs_: Some(substs),
promoted: au.promoted, promoted: au.promoted,
}), }),
ty: a.ty, ty: a.ty,

View File

@ -1046,13 +1046,7 @@ 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(ty::Unevaluated { def, substs, promoted }) => { ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.fold_with(folder)),
ty::ConstKind::Unevaluated(ty::Unevaluated {
def,
substs: substs.fold_with(folder),
promoted,
})
}
ty::ConstKind::Value(_) ty::ConstKind::Value(_)
| ty::ConstKind::Bound(..) | ty::ConstKind::Bound(..)
| ty::ConstKind::Placeholder(..) | ty::ConstKind::Placeholder(..)
@ -1064,7 +1058,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(_)
@ -1082,3 +1076,24 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
ControlFlow::CONTINUE 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::Error(_) => {}
ty::ConstKind::Unevaluated(ct) => { 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, _ => None,
}; };
if let Some(ty::Unevaluated { def, substs, promoted }) = maybe_uneval { if let Some(uv) = maybe_uneval {
if let Some(promoted) = promoted { if let Some(promoted) = uv.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>,
ty, ty,
@ -413,8 +413,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
ConstraintCategory::Boring, ConstraintCategory::Boring,
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new( self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
constant.literal.ty(), constant.literal.ty(),
def.did, uv.def.did,
UserSubsts { substs, user_self_ty: None }, UserSubsts { substs: uv.substs(self.tcx()), user_self_ty: None },
)), )),
) { ) {
span_mirbug!( span_mirbug!(

View File

@ -555,9 +555,9 @@ 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(ty::Unevaluated { def, substs, promoted }) => { ty::ConstKind::Unevaluated(uv) => {
let instance = self.resolve(def, substs)?; let instance = self.resolve(uv.def, uv.substs(*self.tcx))?;
Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into()) Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
} }
ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => { ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => {
span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", val) 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> { impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> {
type BreakTy = FoundParam; type BreakTy = FoundParam;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.tcx Some(self.tcx)
} }
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { 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> { impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.tcx Some(self.tcx)
} }
#[instrument(skip(self))] #[instrument(skip(self))]
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> { 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); self.unused_parameters.clear(param.index);
ControlFlow::CONTINUE 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: // 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 =>
@ -309,10 +309,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(ty::Unevaluated { def, substs, promoted: None }) ty::ConstKind::Unevaluated(uv)
if self.tcx.def_kind(def.did) == DefKind::AnonConst => 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 ControlFlow::CONTINUE
} }
_ => c.super_visit_with(self), _ => c.super_visit_with(self),
@ -357,8 +357,8 @@ struct HasUsedGenericParams<'a, 'tcx> {
impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.tcx Some(self.tcx)
} }
#[instrument(skip(self))] #[instrument(skip(self))]

View File

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

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

View File

@ -859,13 +859,17 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
ty, ty,
val: ty::ConstKind::Unevaluated(ty::Unevaluated { val: ty::ConstKind::Unevaluated(ty::Unevaluated {
def, def,
substs: InternalSubsts::for_item(tcx, def.did, |param, _| { substs_: Some(InternalSubsts::for_item(
if let ty::GenericParamDefKind::Lifetime = param.kind { tcx,
tcx.lifetimes.re_erased.into() def.did,
} else { |param, _| {
tcx.mk_param_from_def(param) if let ty::GenericParamDefKind::Lifetime = param.kind {
} tcx.lifetimes.re_erased.into()
}), } else {
tcx.mk_param_from_def(param)
}
},
)),
promoted: Some(promoted_id), promoted: Some(promoted_id),
}), }),
}) })

View File

@ -475,7 +475,7 @@ impl Visitor<'tcx> for ExtraComments<'tcx> {
ty::ConstKind::Unevaluated(uv) => format!( ty::ConstKind::Unevaluated(uv) => format!(
"Unevaluated({}, {:?}, {:?})", "Unevaluated({}, {:?}, {:?})",
self.tcx.def_path_str(uv.def.did), self.tcx.def_path_str(uv.def.did),
uv.substs, uv.substs(self.tcx),
uv.promoted uv.promoted
), ),
ty::ConstKind::Value(val) => format!("Value({:?})", val), ty::ConstKind::Value(val) => format!("Value({:?})", val),
@ -682,8 +682,10 @@ pub fn write_allocations<'tcx>(
} }
struct CollectAllocIds(BTreeSet<AllocId>); struct CollectAllocIds(BTreeSet<AllocId>);
impl<'tcx> TypeVisitor<'tcx> for CollectAllocIds { impl<'tcx> TypeVisitor<'tcx> for CollectAllocIds {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
bug!("tcx_for_anon_const_substs called for CollectAllocIds") // `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> { 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`) // 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)));
@ -889,11 +888,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,

View File

@ -179,8 +179,8 @@ where
{ {
type BreakTy = V::BreakTy; type BreakTy = V::BreakTy;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.def_id_visitor.tcx() Some(self.def_id_visitor.tcx())
} }
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> { 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 where
OP: FnMut(ty::Region<'tcx>), OP: FnMut(ty::Region<'tcx>),
{ {
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.tcx Some(self.tcx)
} }
fn visit_binder<T: TypeFoldable<'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. // 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 =
param_env, infcx.const_eval_resolve(param_env, ty::Unevaluated::new(def, substs), Some(span));
ty::Unevaluated { def, substs, promoted: None },
Some(span),
);
if concrete.is_ok() && substs.has_param_types_or_consts() { if concrete.is_ok() && substs.has_param_types_or_consts() {
match infcx.tcx.def_kind(def.did) { match infcx.tcx.def_kind(def.did) {
@ -217,9 +214,7 @@ 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(ty::Unevaluated { def, substs, promoted: _ }) => { ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.def, uv.substs(tcx)),
AbstractConst::new(tcx, def, substs)
}
ty::ConstKind::Error(_) => Err(ErrorReported), ty::ConstKind::Error(_) => Err(ErrorReported),
_ => Ok(None), _ => Ok(None),
} }

View File

@ -570,7 +570,8 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
ty::PredicateKind::ConstEquate(c1, c2) => { ty::PredicateKind::ConstEquate(c1, c2) => {
debug!(?c1, ?c2, "equating consts"); 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 // FIXME: we probably should only try to unify abstract constants
// if the constants depend on generic parameters. // if the constants depend on generic parameters.
// //
@ -597,7 +598,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
Err(ErrorHandled::TooGeneric) => { Err(ErrorHandled::TooGeneric) => {
stalled_on.extend( stalled_on.extend(
unevaluated unevaluated
.substs .substs(tcx)
.iter() .iter()
.filter_map(TyOrConstInferVar::maybe_from_generic_arg), .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> { impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs<'a>(&'a self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.tcx Some(self.tcx)
} }
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { 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> { impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
type BreakTy = NonStructuralMatchTy<'tcx>; type BreakTy = NonStructuralMatchTy<'tcx>;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.tcx() Some(self.tcx())
} }
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { 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) => { 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 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); self.out.extend(obligations);
let predicate = ty::PredicateKind::ConstEvaluatable(def, substs) let predicate = ty::PredicateKind::ConstEvaluatable(uv.def, substs)
.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(

View File

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

View File

@ -473,8 +473,8 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
struct FindParentLifetimeVisitor<'tcx>(TyCtxt<'tcx>, &'tcx ty::Generics); struct FindParentLifetimeVisitor<'tcx>(TyCtxt<'tcx>, &'tcx ty::Generics);
impl<'tcx> ty::fold::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> { impl<'tcx> ty::fold::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> {
type BreakTy = FoundParentLifetime; type BreakTy = FoundParentLifetime;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.0 Some(self.0)
} }
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { 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> { impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
type BreakTy = Ty<'tcx>; type BreakTy = Ty<'tcx>;
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.tcx Some(self.tcx)
} }
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { 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_map(|e| typeck_results.node_type_opt(e.hir_id).map(|t| (e.span, t)))
.filter(|(_, ty)| !matches!(ty.kind(), ty::Never)) .filter(|(_, ty)| !matches!(ty.kind(), ty::Never))
{ {
struct VisitTypes(Vec<DefId>); struct OpaqueTypeCollector(Vec<DefId>);
impl<'tcx> ty::fold::TypeVisitor<'tcx> for VisitTypes { impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypeCollector {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
bug!("tcx_for_anon_const_substs called for VisitTypes"); // Default anon const substs cannot contain opaque types.
None
} }
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match *t.kind() { 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); ty.visit_with(&mut visitor);
for def_id in visitor.0 { for def_id in visitor.0 {
let ty_span = tcx.def_span(def_id); 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>>); struct TypeParamVisitor<'tcx>(TyCtxt<'tcx>, Vec<Ty<'tcx>>);
impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> { impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.0 Some(self.0)
} }
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::Param(_) = ty.kind() { 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> { impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams<'tcx> {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.tcx Some(self.tcx)
} }
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { 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) { pub fn provide(providers: &mut Providers) {
*providers = Providers { *providers = Providers {
opt_const_param_of: type_of::opt_const_param_of, 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, type_of: type_of::type_of,
item_bounds: item_bounds::item_bounds, item_bounds: item_bounds::item_bounds,
explicit_item_bounds: item_bounds::explicit_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); 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(uv.def, uv.substs).to_predicate(self.tcx), ty::PredicateKind::ConstEvaluatable(uv.def, uv.substs(self.tcx))
.to_predicate(self.tcx),
span, span,
)); ));
} }

View File

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

View File

@ -60,8 +60,8 @@ struct ParameterCollector<'tcx> {
} }
impl<'tcx> TypeVisitor<'tcx> for ParameterCollector<'tcx> { impl<'tcx> TypeVisitor<'tcx> for ParameterCollector<'tcx> {
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.tcx Some(self.tcx)
} }
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { 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 { crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
match n.val { 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 mut s = if let Some(def) = def.as_local() {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def.did); 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)) 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( let result = cx.tcx.const_eval_resolve(
cx.param_env, cx.param_env,
ty::Unevaluated { ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
def: ty::WithOptConstParam::unknown(def_id),
substs,
promoted: None,
},
None, None,
); );
is_value_unfrozen_raw(cx, result, ty) 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> { impl<'tcx> TypeVisitor<'tcx> for ContainsRegion<'tcx> {
type BreakTy = (); type BreakTy = ();
fn tcx_for_anon_const_substs(&self) -> TyCtxt<'tcx> { fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
self.0 Some(self.0)
} }
fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {

View File

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