Auto merge of #91549 - fee1-dead:const_env, r=spastorino
Eliminate ConstnessAnd again Closes #91489. Closes #89432. Reverts #91491. Reverts #89450. r? `@spastorino`
This commit is contained in:
commit
22f8bde876
69 changed files with 622 additions and 458 deletions
|
@ -474,7 +474,8 @@ impl<'hir> Map<'hir> {
|
|||
/// Panics if `LocalDefId` does not have an associated body.
|
||||
///
|
||||
/// This should only be used for determining the context of a body, a return
|
||||
/// value of `Some` does not always suggest that the owner of the body is `const`.
|
||||
/// value of `Some` does not always suggest that the owner of the body is `const`,
|
||||
/// just that it has to be checked as if it were.
|
||||
pub fn body_const_context(&self, did: LocalDefId) -> Option<ConstContext> {
|
||||
let hir_id = self.local_def_id_to_hir_id(did);
|
||||
let ccx = match self.body_owner_kind(hir_id) {
|
||||
|
|
|
@ -246,6 +246,14 @@ impl<'tcx, R> Canonical<'tcx, QueryResponse<'tcx, R>> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, R> Canonical<'tcx, ty::ParamEnvAnd<'tcx, R>> {
|
||||
#[inline]
|
||||
pub fn without_const(mut self) -> Self {
|
||||
self.value = self.value.without_const();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, V> Canonical<'tcx, V> {
|
||||
/// Allows you to map the `value` of a canonical while keeping the
|
||||
/// same set of bound variables.
|
||||
|
|
|
@ -64,6 +64,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
cid: GlobalId<'tcx>,
|
||||
span: Option<Span>,
|
||||
) -> EvalToConstValueResult<'tcx> {
|
||||
let param_env = param_env.with_const();
|
||||
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
|
||||
// improve caching of queries.
|
||||
let inputs = self.erase_regions(param_env.and(cid));
|
||||
|
@ -92,6 +93,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
gid: GlobalId<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> Result<&'tcx mir::Allocation, ErrorHandled> {
|
||||
let param_env = param_env.with_const();
|
||||
trace!("eval_to_allocation: Need to compute {:?}", gid);
|
||||
let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?;
|
||||
Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory())
|
||||
|
|
|
@ -880,6 +880,7 @@ rustc_queries! {
|
|||
key: ty::ParamEnvAnd<'tcx, ConstAlloc<'tcx>>
|
||||
) -> Option<ty::ValTree<'tcx>> {
|
||||
desc { "destructure constant" }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Destructure a constant ADT or array into its variant index and its
|
||||
|
@ -888,6 +889,7 @@ rustc_queries! {
|
|||
key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
|
||||
) -> mir::DestructuredConst<'tcx> {
|
||||
desc { "destructure constant" }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Dereference a constant reference or raw pointer and turn the result into a constant
|
||||
|
@ -896,6 +898,7 @@ rustc_queries! {
|
|||
key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
|
||||
) -> &'tcx ty::Const<'tcx> {
|
||||
desc { "deref constant" }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
|
||||
|
@ -1100,26 +1103,32 @@ rustc_queries! {
|
|||
/// `ty.is_copy()`, etc, since that will prune the environment where possible.
|
||||
query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
desc { "computing whether `{}` is `Copy`", env.value }
|
||||
remap_env_constness
|
||||
}
|
||||
/// Query backing `TyS::is_sized`.
|
||||
query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
desc { "computing whether `{}` is `Sized`", env.value }
|
||||
remap_env_constness
|
||||
}
|
||||
/// Query backing `TyS::is_freeze`.
|
||||
query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
desc { "computing whether `{}` is freeze", env.value }
|
||||
remap_env_constness
|
||||
}
|
||||
/// Query backing `TyS::is_unpin`.
|
||||
query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
desc { "computing whether `{}` is `Unpin`", env.value }
|
||||
remap_env_constness
|
||||
}
|
||||
/// Query backing `TyS::needs_drop`.
|
||||
query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
desc { "computing whether `{}` needs drop", env.value }
|
||||
remap_env_constness
|
||||
}
|
||||
/// Query backing `TyS::has_significant_drop_raw`.
|
||||
query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
desc { "computing whether `{}` has a significant drop", env.value }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Query backing `TyS::is_structural_eq_shallow`.
|
||||
|
@ -1158,6 +1167,7 @@ rustc_queries! {
|
|||
key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
|
||||
) -> Result<ty::layout::TyAndLayout<'tcx>, ty::layout::LayoutError<'tcx>> {
|
||||
desc { "computing layout of `{}`", key.value }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
|
||||
|
@ -1168,6 +1178,7 @@ rustc_queries! {
|
|||
key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
|
||||
) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
|
||||
desc { "computing call ABI of `{}` function pointers", key.value.0 }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
|
||||
|
@ -1179,6 +1190,7 @@ rustc_queries! {
|
|||
key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
|
||||
) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
|
||||
desc { "computing call ABI of `{}`", key.value.0 }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
query dylib_dependency_formats(_: CrateNum)
|
||||
|
@ -1463,6 +1475,7 @@ rustc_queries! {
|
|||
key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
|
||||
) -> ty::inhabitedness::DefIdForest {
|
||||
desc { "computing the inhabitedness of `{:?}`", key }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
query dep_kind(_: CrateNum) -> CrateDepKind {
|
||||
|
@ -1642,6 +1655,7 @@ rustc_queries! {
|
|||
NoSolution,
|
||||
> {
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
// FIXME: Implement `normalize_generic_arg_after_erasing_regions` and
|
||||
|
@ -1654,6 +1668,7 @@ rustc_queries! {
|
|||
goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>
|
||||
) -> GenericArg<'tcx> {
|
||||
desc { "normalizing `{}`", goal.value }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Do not call this query directly: invoke `normalize_erasing_regions` instead.
|
||||
|
@ -1661,6 +1676,7 @@ rustc_queries! {
|
|||
goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
|
||||
) -> mir::ConstantKind<'tcx> {
|
||||
desc { "normalizing `{}`", goal.value }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Do not call this query directly: invoke `try_normalize_erasing_regions` instead.
|
||||
|
@ -1668,6 +1684,7 @@ rustc_queries! {
|
|||
goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>
|
||||
) -> Result<GenericArg<'tcx>, NoSolution> {
|
||||
desc { "normalizing `{}`", goal.value }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Do not call this query directly: invoke `try_normalize_erasing_regions` instead.
|
||||
|
@ -1675,6 +1692,7 @@ rustc_queries! {
|
|||
goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
|
||||
) -> Result<mir::ConstantKind<'tcx>, NoSolution> {
|
||||
desc { "normalizing `{}`", goal.value }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
query implied_outlives_bounds(
|
||||
|
@ -1684,6 +1702,7 @@ rustc_queries! {
|
|||
NoSolution,
|
||||
> {
|
||||
desc { "computing implied outlives bounds for `{:?}`", goal }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Do not call this query directly: invoke `infcx.at().dropck_outlives()` instead.
|
||||
|
@ -1694,6 +1713,7 @@ rustc_queries! {
|
|||
NoSolution,
|
||||
> {
|
||||
desc { "computing dropck types for `{:?}`", goal }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Do not call this query directly: invoke `infcx.predicate_may_hold()` or
|
||||
|
@ -1721,6 +1741,7 @@ rustc_queries! {
|
|||
NoSolution,
|
||||
> {
|
||||
desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Do not call this query directly: part of the `Eq` type-op
|
||||
|
@ -1731,6 +1752,7 @@ rustc_queries! {
|
|||
NoSolution,
|
||||
> {
|
||||
desc { "evaluating `type_op_eq` `{:?}`", goal }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Do not call this query directly: part of the `Subtype` type-op
|
||||
|
@ -1741,6 +1763,7 @@ rustc_queries! {
|
|||
NoSolution,
|
||||
> {
|
||||
desc { "evaluating `type_op_subtype` `{:?}`", goal }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Do not call this query directly: part of the `ProvePredicate` type-op
|
||||
|
@ -1761,6 +1784,7 @@ rustc_queries! {
|
|||
NoSolution,
|
||||
> {
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Do not call this query directly: part of the `Normalize` type-op
|
||||
|
@ -1771,6 +1795,7 @@ rustc_queries! {
|
|||
NoSolution,
|
||||
> {
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Do not call this query directly: part of the `Normalize` type-op
|
||||
|
@ -1781,6 +1806,7 @@ rustc_queries! {
|
|||
NoSolution,
|
||||
> {
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
/// Do not call this query directly: part of the `Normalize` type-op
|
||||
|
@ -1791,6 +1817,7 @@ rustc_queries! {
|
|||
NoSolution,
|
||||
> {
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
query subst_and_check_impossible_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool {
|
||||
|
@ -1804,6 +1831,7 @@ rustc_queries! {
|
|||
goal: CanonicalTyGoal<'tcx>
|
||||
) -> MethodAutoderefStepsResult<'tcx> {
|
||||
desc { "computing autoderef types for `{:?}`", goal }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
query supported_target_features(_: CrateNum) -> FxHashMap<String, Option<Symbol>> {
|
||||
|
@ -1836,6 +1864,7 @@ rustc_queries! {
|
|||
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>
|
||||
) -> Result<Option<ty::Instance<'tcx>>, ErrorReported> {
|
||||
desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
query resolve_instance_of_const_arg(
|
||||
|
@ -1845,6 +1874,7 @@ rustc_queries! {
|
|||
"resolving instance of the const argument `{}`",
|
||||
ty::Instance::new(key.value.0.to_def_id(), key.value.2),
|
||||
}
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
query normalize_opaque_types(key: &'tcx ty::List<ty::Predicate<'tcx>>) -> &'tcx ty::List<ty::Predicate<'tcx>> {
|
||||
|
@ -1859,6 +1889,7 @@ rustc_queries! {
|
|||
/// size, to account for partial initialisation. See #49298 for details.)
|
||||
query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
desc { "conservatively checking if {:?} is privately uninhabited", key }
|
||||
remap_env_constness
|
||||
}
|
||||
|
||||
query limits(key: ()) -> Limits {
|
||||
|
|
|
@ -12,14 +12,12 @@ use rustc_hir::def_id::DefId;
|
|||
use rustc_query_system::cache::Cache;
|
||||
|
||||
pub type SelectionCache<'tcx> = Cache<
|
||||
(ty::ConstnessAnd<ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>>, ty::ImplPolarity),
|
||||
ty::ParamEnvAnd<'tcx, ty::TraitPredicate<'tcx>>,
|
||||
SelectionResult<'tcx, SelectionCandidate<'tcx>>,
|
||||
>;
|
||||
|
||||
pub type EvaluationCache<'tcx> = Cache<
|
||||
(ty::ParamEnvAnd<'tcx, ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>>, ty::ImplPolarity),
|
||||
EvaluationResult,
|
||||
>;
|
||||
pub type EvaluationCache<'tcx> =
|
||||
Cache<ty::ParamEnvAnd<'tcx, ty::PolyTraitPredicate<'tcx>>, EvaluationResult>;
|
||||
|
||||
/// The selection process begins by considering all impls, where
|
||||
/// clauses, and so forth that might resolve an obligation. Sometimes
|
||||
|
@ -103,7 +101,7 @@ pub enum SelectionCandidate<'tcx> {
|
|||
/// `false` if there are no *further* obligations.
|
||||
has_nested: bool,
|
||||
},
|
||||
ParamCandidate((ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, ty::ImplPolarity)),
|
||||
ParamCandidate(ty::PolyTraitPredicate<'tcx>),
|
||||
ImplCandidate(DefId),
|
||||
AutoImplCandidate(DefId),
|
||||
|
||||
|
|
|
@ -26,9 +26,9 @@ impl<'tcx> Elaborator<'tcx> {
|
|||
.predicates
|
||||
.into_iter()
|
||||
.flat_map(|(pred, _)| {
|
||||
pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_ref()
|
||||
pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_pred()
|
||||
})
|
||||
.map(|t| t.value)
|
||||
.map(|t| t.map_bound(|pred| pred.trait_ref))
|
||||
.filter(|supertrait_ref| self.visited.insert(*supertrait_ref));
|
||||
|
||||
self.stack.extend(supertrait_refs);
|
||||
|
|
|
@ -230,6 +230,19 @@ pub enum BoundConstness {
|
|||
ConstIfConst,
|
||||
}
|
||||
|
||||
impl BoundConstness {
|
||||
/// Reduce `self` and `constness` to two possible combined states instead of four.
|
||||
pub fn and(&mut self, constness: hir::Constness) -> hir::Constness {
|
||||
match (constness, self) {
|
||||
(hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const,
|
||||
(_, this) => {
|
||||
*this = BoundConstness::NotConst;
|
||||
hir::Constness::NotConst
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for BoundConstness {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
|
@ -846,20 +859,6 @@ impl ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitRef<'tcx>> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
self.value
|
||||
.map_bound(|trait_ref| {
|
||||
PredicateKind::Trait(ty::TraitPredicate {
|
||||
trait_ref,
|
||||
constness: self.constness,
|
||||
polarity: ty::ImplPolarity::Positive,
|
||||
})
|
||||
})
|
||||
.to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
self.map_bound(PredicateKind::Trait).to_predicate(tcx)
|
||||
|
@ -885,12 +884,10 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> Predicate<'tcx> {
|
||||
pub fn to_opt_poly_trait_ref(self) -> Option<ConstnessAnd<PolyTraitRef<'tcx>>> {
|
||||
pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
|
||||
let predicate = self.kind();
|
||||
match predicate.skip_binder() {
|
||||
PredicateKind::Trait(t) => {
|
||||
Some(ConstnessAnd { constness: t.constness, value: predicate.rebind(t.trait_ref) })
|
||||
}
|
||||
PredicateKind::Trait(t) => Some(predicate.rebind(t)),
|
||||
PredicateKind::Projection(..)
|
||||
| PredicateKind::Subtype(..)
|
||||
| PredicateKind::Coerce(..)
|
||||
|
@ -1221,23 +1218,33 @@ pub struct ParamEnv<'tcx> {
|
|||
/// want `Reveal::All`.
|
||||
///
|
||||
/// Note: This is packed, use the reveal() method to access it.
|
||||
packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, traits::Reveal, true>,
|
||||
packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, ParamTag, true>,
|
||||
}
|
||||
|
||||
unsafe impl rustc_data_structures::tagged_ptr::Tag for traits::Reveal {
|
||||
const BITS: usize = 1;
|
||||
#[derive(Copy, Clone)]
|
||||
struct ParamTag {
|
||||
reveal: traits::Reveal,
|
||||
constness: hir::Constness,
|
||||
}
|
||||
|
||||
unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag {
|
||||
const BITS: usize = 2;
|
||||
#[inline]
|
||||
fn into_usize(self) -> usize {
|
||||
match self {
|
||||
traits::Reveal::UserFacing => 0,
|
||||
traits::Reveal::All => 1,
|
||||
Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } => 0,
|
||||
Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } => 1,
|
||||
Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } => 2,
|
||||
Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 3,
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn from_usize(ptr: usize) -> Self {
|
||||
match ptr {
|
||||
0 => traits::Reveal::UserFacing,
|
||||
1 => traits::Reveal::All,
|
||||
0 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst },
|
||||
1 => Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst },
|
||||
2 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const },
|
||||
3 => Self { reveal: traits::Reveal::All, constness: hir::Constness::Const },
|
||||
_ => std::hint::unreachable_unchecked(),
|
||||
}
|
||||
}
|
||||
|
@ -1248,6 +1255,7 @@ impl<'tcx> fmt::Debug for ParamEnv<'tcx> {
|
|||
f.debug_struct("ParamEnv")
|
||||
.field("caller_bounds", &self.caller_bounds())
|
||||
.field("reveal", &self.reveal())
|
||||
.field("constness", &self.constness())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
@ -1256,6 +1264,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ParamEnv<'tcx> {
|
|||
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
||||
self.caller_bounds().hash_stable(hcx, hasher);
|
||||
self.reveal().hash_stable(hcx, hasher);
|
||||
self.constness().hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1267,12 +1276,14 @@ impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> {
|
|||
Ok(ParamEnv::new(
|
||||
self.caller_bounds().try_fold_with(folder)?,
|
||||
self.reveal().try_fold_with(folder)?,
|
||||
self.constness().try_fold_with(folder)?,
|
||||
))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.caller_bounds().visit_with(visitor)?;
|
||||
self.reveal().visit_with(visitor)
|
||||
self.reveal().visit_with(visitor)?;
|
||||
self.constness().visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1283,7 +1294,7 @@ impl<'tcx> ParamEnv<'tcx> {
|
|||
/// type-checking.
|
||||
#[inline]
|
||||
pub fn empty() -> Self {
|
||||
Self::new(List::empty(), Reveal::UserFacing)
|
||||
Self::new(List::empty(), Reveal::UserFacing, hir::Constness::NotConst)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -1293,7 +1304,12 @@ impl<'tcx> ParamEnv<'tcx> {
|
|||
|
||||
#[inline]
|
||||
pub fn reveal(self) -> traits::Reveal {
|
||||
self.packed.tag()
|
||||
self.packed.tag().reveal
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn constness(self) -> hir::Constness {
|
||||
self.packed.tag().constness
|
||||
}
|
||||
|
||||
/// Construct a trait environment with no where-clauses in scope
|
||||
|
@ -1305,20 +1321,47 @@ impl<'tcx> ParamEnv<'tcx> {
|
|||
/// or invoke `param_env.with_reveal_all()`.
|
||||
#[inline]
|
||||
pub fn reveal_all() -> Self {
|
||||
Self::new(List::empty(), Reveal::All)
|
||||
Self::new(List::empty(), Reveal::All, hir::Constness::NotConst)
|
||||
}
|
||||
|
||||
/// Construct a trait environment with the given set of predicates.
|
||||
#[inline]
|
||||
pub fn new(caller_bounds: &'tcx List<Predicate<'tcx>>, reveal: Reveal) -> Self {
|
||||
ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, reveal) }
|
||||
pub fn new(
|
||||
caller_bounds: &'tcx List<Predicate<'tcx>>,
|
||||
reveal: Reveal,
|
||||
constness: hir::Constness,
|
||||
) -> Self {
|
||||
ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal, constness }) }
|
||||
}
|
||||
|
||||
pub fn with_user_facing(mut self) -> Self {
|
||||
self.packed.set_tag(Reveal::UserFacing);
|
||||
self.packed.set_tag(ParamTag { reveal: Reveal::UserFacing, ..self.packed.tag() });
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_constness(mut self, constness: hir::Constness) -> Self {
|
||||
self.packed.set_tag(ParamTag { constness, ..self.packed.tag() });
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_const(mut self) -> Self {
|
||||
self.packed.set_tag(ParamTag { constness: hir::Constness::Const, ..self.packed.tag() });
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn without_const(mut self) -> Self {
|
||||
self.packed.set_tag(ParamTag { constness: hir::Constness::NotConst, ..self.packed.tag() });
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn remap_constness_with(&mut self, mut constness: ty::BoundConstness) {
|
||||
*self = self.with_constness(constness.and(self.constness()))
|
||||
}
|
||||
|
||||
/// Returns a new parameter environment with the same clauses, but
|
||||
/// which "reveals" the true results of projections in all cases
|
||||
/// (even for associated types that are specializable). This is
|
||||
|
@ -1329,17 +1372,21 @@ impl<'tcx> ParamEnv<'tcx> {
|
|||
/// will be normalized to their underlying types.
|
||||
/// See PR #65989 and issue #65918 for more details
|
||||
pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self {
|
||||
if self.packed.tag() == traits::Reveal::All {
|
||||
if self.packed.tag().reveal == traits::Reveal::All {
|
||||
return self;
|
||||
}
|
||||
|
||||
ParamEnv::new(tcx.normalize_opaque_types(self.caller_bounds()), Reveal::All)
|
||||
ParamEnv::new(
|
||||
tcx.normalize_opaque_types(self.caller_bounds()),
|
||||
Reveal::All,
|
||||
self.constness(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns this same environment but with no caller bounds.
|
||||
#[inline]
|
||||
pub fn without_caller_bounds(self) -> Self {
|
||||
Self::new(List::empty(), self.reveal())
|
||||
Self::new(List::empty(), self.reveal(), self.constness())
|
||||
}
|
||||
|
||||
/// Creates a suitable environment in which to perform trait
|
||||
|
@ -1369,33 +1416,23 @@ impl<'tcx> ParamEnv<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)]
|
||||
pub struct ConstnessAnd<T> {
|
||||
pub constness: BoundConstness,
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that
|
||||
// the constness of trait bounds is being propagated correctly.
|
||||
pub trait WithConstness: Sized {
|
||||
impl PolyTraitRef<'tcx> {
|
||||
#[inline]
|
||||
fn with_constness(self, constness: BoundConstness) -> ConstnessAnd<Self> {
|
||||
ConstnessAnd { constness, value: self }
|
||||
pub fn with_constness(self, constness: BoundConstness) -> PolyTraitPredicate<'tcx> {
|
||||
self.map_bound(|trait_ref| ty::TraitPredicate {
|
||||
trait_ref,
|
||||
constness,
|
||||
polarity: ty::ImplPolarity::Positive,
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn with_const_if_const(self) -> ConstnessAnd<Self> {
|
||||
self.with_constness(BoundConstness::ConstIfConst)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn without_const(self) -> ConstnessAnd<Self> {
|
||||
pub fn without_const(self) -> PolyTraitPredicate<'tcx> {
|
||||
self.with_constness(BoundConstness::NotConst)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> WithConstness for T {}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)]
|
||||
pub struct ParamEnvAnd<'tcx, T> {
|
||||
pub param_env: ParamEnv<'tcx>,
|
||||
|
@ -1406,6 +1443,12 @@ impl<'tcx, T> ParamEnvAnd<'tcx, T> {
|
|||
pub fn into_parts(self) -> (ParamEnv<'tcx>, T) {
|
||||
(self.param_env, self.value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn without_const(mut self) -> Self {
|
||||
self.param_env = self.param_env.without_const();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for ParamEnvAnd<'tcx, T>
|
||||
|
|
|
@ -156,6 +156,16 @@ macro_rules! separate_provide_extern_default {
|
|||
};
|
||||
}
|
||||
|
||||
macro_rules! opt_remap_env_constness {
|
||||
([][$name:ident]) => {};
|
||||
([(remap_env_constness) $($rest:tt)*][$name:ident]) => {
|
||||
let $name = $name.without_const();
|
||||
};
|
||||
([$other:tt $($modifiers:tt)*][$name:ident]) => {
|
||||
opt_remap_env_constness!([$($modifiers)*][$name])
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! define_callbacks {
|
||||
(<$tcx:tt>
|
||||
$($(#[$attr:meta])*
|
||||
|
@ -202,6 +212,8 @@ macro_rules! define_callbacks {
|
|||
#[inline(always)]
|
||||
pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
|
||||
let key = key.into_query_param();
|
||||
opt_remap_env_constness!([$($modifiers)*][key]);
|
||||
|
||||
let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop);
|
||||
|
||||
let lookup = match cached {
|
||||
|
@ -229,6 +241,8 @@ macro_rules! define_callbacks {
|
|||
pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx>
|
||||
{
|
||||
let key = key.into_query_param();
|
||||
opt_remap_env_constness!([$($modifiers)*][key]);
|
||||
|
||||
let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, Clone::clone);
|
||||
|
||||
let lookup = match cached {
|
||||
|
|
|
@ -218,19 +218,6 @@ impl<'tcx> Relate<'tcx> for ty::BoundConstness {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::ConstnessAnd<T> {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
a: ty::ConstnessAnd<T>,
|
||||
b: ty::ConstnessAnd<T>,
|
||||
) -> RelateResult<'tcx, ty::ConstnessAnd<T>> {
|
||||
Ok(ty::ConstnessAnd {
|
||||
constness: relation.relate(a.constness, b.constness)?,
|
||||
value: relation.relate(a.value, b.value)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Relate<'tcx> for ast::Unsafety {
|
||||
fn relate<R: TypeRelation<'tcx>>(
|
||||
relation: &mut R,
|
||||
|
|
|
@ -480,7 +480,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> {
|
|||
type Lifted = ty::ParamEnv<'tcx>;
|
||||
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
|
||||
tcx.lift(self.caller_bounds())
|
||||
.map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal()))
|
||||
.map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal(), self.constness()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,9 +8,7 @@ use crate::infer::canonical::Canonical;
|
|||
use crate::ty::fold::ValidateBoundVars;
|
||||
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
|
||||
use crate::ty::InferTy::{self, *};
|
||||
use crate::ty::{
|
||||
self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness,
|
||||
};
|
||||
use crate::ty::{self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable};
|
||||
use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS};
|
||||
use polonius_engine::Atom;
|
||||
use rustc_data_structures::captures::Captures;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue