make unevaluated const substs optional
This commit is contained in:
parent
f4b606fd17
commit
bfaf13af4e
46 changed files with 234 additions and 188 deletions
|
@ -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) {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>>(
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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,
|
||||
}),
|
||||
};
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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>>(
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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))]
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
}),
|
||||
})
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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>>(
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
);
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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,
|
||||
));
|
||||
}
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Add table
Reference in a new issue