Remove `constness` from `ParamEnv`

This commit is contained in:
Deadbeef 2023-07-27 15:50:42 +00:00
parent 3e11b223d7
commit e6b423aebb
34 changed files with 89 additions and 361 deletions

View File

@ -409,18 +409,12 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
}
if let ty::FnDef(def_id, args) = *constant.literal.ty().kind() {
// const_trait_impl: use a non-const param env when checking that a FnDef type is well formed.
// this is because the well-formedness of the function does not need to be proved to have `const`
// impls for trait bounds.
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
let prev = self.cx.param_env;
self.cx.param_env = prev.without_const();
self.cx.normalize_and_prove_instantiated_predicates(
def_id,
instantiated_predicates,
locations,
);
self.cx.param_env = prev;
}
}
}

View File

@ -228,7 +228,6 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
assert!(key.param_env.is_const());
// see comment in eval_to_allocation_raw_provider for what we're doing here
if key.param_env.reveal() == Reveal::All {
let mut key = key;
@ -269,7 +268,6 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
assert!(key.param_env.is_const());
// Because the constant is computed twice (once per value of `Reveal`), we are at risk of
// reporting the same error twice here. To resolve this, we check whether we can evaluate the
// constant in the more restrictive `Reveal::UserFacing`, which most likely already was

View File

@ -958,7 +958,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} else {
self.param_env
};
let param_env = param_env.with_const();
let val = self.ctfe_query(span, |tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?;
self.raw_const_to_mplace(val)
}

View File

@ -698,10 +698,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
ty::ConstKind::Unevaluated(uv) => {
let instance = self.resolve(uv.def, uv.args)?;
let cid = GlobalId { instance, promoted: None };
self.ctfe_query(span, |tcx| {
tcx.eval_to_valtree(self.param_env.with_const().and(cid))
})?
.unwrap_or_else(|| bug!("unable to create ValTree for {uv:?}"))
self.ctfe_query(span, |tcx| tcx.eval_to_valtree(self.param_env.and(cid)))?
.unwrap_or_else(|| bug!("unable to create ValTree for {uv:?}"))
}
ty::ConstKind::Bound(..) | ty::ConstKind::Infer(..) => {
span_bug!(self.cur_span(), "unexpected ConstKind in ctfe: {val:?}")

View File

@ -21,7 +21,7 @@ use std::mem;
use std::ops::Deref;
use super::ops::{self, NonConstOp, Status};
use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop};
use super::resolver::FlowSensitiveAnalysis;
use super::{ConstCx, Qualif};
use crate::const_eval::is_unstable_const_fn;
@ -34,7 +34,7 @@ type QualifResults<'mir, 'tcx, Q> =
pub struct Qualifs<'mir, 'tcx> {
has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
needs_drop: Option<QualifResults<'mir, 'tcx, NeedsDrop>>,
needs_non_const_drop: Option<QualifResults<'mir, 'tcx, NeedsNonConstDrop>>,
// needs_non_const_drop: Option<QualifResults<'mir, 'tcx, NeedsNonConstDrop>>,
}
impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
@ -77,15 +77,17 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
local: Local,
location: Location,
) -> bool {
// FIXME(effects) replace with `NeedsNonconstDrop` after const traits work again
/*
let ty = ccx.body.local_decls[local].ty;
if !NeedsNonConstDrop::in_any_value_of_ty(ccx, ty) {
if !NeedsDrop::in_any_value_of_ty(ccx, ty) {
return false;
}
let needs_non_const_drop = self.needs_non_const_drop.get_or_insert_with(|| {
let ConstCx { tcx, body, .. } = *ccx;
FlowSensitiveAnalysis::new(NeedsNonConstDrop, ccx)
FlowSensitiveAnalysis::new(NeedsDrop, ccx)
.into_engine(tcx, &body)
.iterate_to_fixpoint()
.into_results_cursor(&body)
@ -93,6 +95,9 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
needs_non_const_drop.seek_before_primary_effect(location);
needs_non_const_drop.get().contains(local)
*/
self.needs_drop(ccx, local, location)
}
/// Returns `true` if `local` is `HasMutInterior` at the given `Location`.
@ -798,16 +803,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
Ok(Some(ImplSource::UserDefined(data))) => {
let callee_name = tcx.item_name(callee);
if let Some(&did) = tcx
.associated_item_def_ids(data.impl_def_id)
.iter()
.find(|did| tcx.item_name(**did) == callee_name)
{
// using internal args is ok here, since this is only
// used for the `resolve` call below
fn_args = GenericArgs::identity_for_item(tcx, did);
callee = did;
}
if let hir::Constness::NotConst = tcx.constness(data.impl_def_id) {
self.check_op(ops::FnCallNonConst {
@ -820,6 +815,17 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
});
return;
}
if let Some(&did) = tcx
.associated_item_def_ids(data.impl_def_id)
.iter()
.find(|did| tcx.item_name(**did) == callee_name)
{
// using internal args is ok here, since this is only
// used for the `resolve` call below
fn_args = GenericArgs::identity_for_item(tcx, did);
callee = did;
}
}
_ if !tcx.is_const_fn_raw(callee) => {
// At this point, it is only legal when the caller is in a trait
@ -996,8 +1002,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
let mut err_span = self.span;
let ty_of_dropped_place = dropped_place.ty(self.body, self.tcx).ty;
// FIXME(effects) replace with `NeedsNonConstDrop` once we fix const traits
let ty_needs_non_const_drop =
qualifs::NeedsNonConstDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place);
qualifs::NeedsDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place);
debug!(?ty_of_dropped_place, ?ty_needs_non_const_drop);

View File

@ -5,7 +5,7 @@ use rustc_span::{symbol::sym, Span};
use super::check::Qualifs;
use super::ops::{self, NonConstOp};
use super::qualifs::{NeedsNonConstDrop, Qualif};
use super::qualifs::{NeedsDrop, Qualif};
use super::ConstCx;
/// Returns `true` if we should use the more precise live drop checker that runs after drop
@ -82,7 +82,9 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
match &terminator.kind {
mir::TerminatorKind::Drop { place: dropped_place, .. } => {
let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
// FIXME(effects) use `NeedsNonConstDrop`
if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
// Instead of throwing a bug, we just return here. This is because we have to
// run custom `const Drop` impls.
return;

View File

@ -23,7 +23,8 @@ pub fn in_any_value_of_ty<'tcx>(
ConstQualifs {
has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty),
needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty),
needs_non_const_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty),
// FIXME(effects)
needs_non_const_drop: NeedsDrop::in_any_value_of_ty(cx, ty),
custom_eq: CustomEq::in_any_value_of_ty(cx, ty),
tainted_by_errors,
}

View File

@ -219,11 +219,7 @@ fn compare_method_predicate_entailment<'tcx>(
// The key step here is to update the caller_bounds's predicates to be
// the new hybrid bounds we computed.
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
let param_env = ty::ParamEnv::new(
tcx.mk_clauses(&hybrid_preds.predicates),
Reveal::UserFacing,
hir::Constness::NotConst,
);
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
let infcx = &tcx.infer_ctxt().build();
@ -1923,11 +1919,7 @@ fn compare_type_predicate_entailment<'tcx>(
let impl_ty_span = tcx.def_span(impl_ty_def_id);
let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_def_id);
let param_env = ty::ParamEnv::new(
tcx.mk_clauses(&hybrid_preds.predicates),
Reveal::UserFacing,
hir::Constness::NotConst,
);
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
@ -2102,7 +2094,7 @@ pub(super) fn check_type_bounds<'tcx>(
.to_predicate(tcx),
),
};
ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing, param_env.constness())
ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
};
debug!(?normalize_param_env);

View File

@ -129,9 +129,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
// We don't need to normalize this param-env or anything, since we're only
// substituting it with free params, so no additional param-env normalization
// can occur on top of what has been done in the param_env query itself.
let param_env = ty::EarlyBinder::bind(tcx.param_env(adt_def_id))
.instantiate(tcx, adt_to_impl_args)
.with_constness(tcx.constness(drop_impl_def_id));
let param_env =
ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);
for (pred, span) in tcx.predicates_of(drop_impl_def_id).instantiate_identity(tcx) {
let normalize_cause = traits::ObligationCause::misc(span, adt_def_id);

View File

@ -75,12 +75,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
self.body_def_id,
ObligationCauseCode::WellFormed(loc),
);
// for a type to be WF, we do not need to check if const trait predicates satisfy.
let param_env = self.param_env.without_const();
self.ocx.register_obligation(traits::Obligation::new(
self.tcx(),
cause,
param_env,
self.param_env,
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))),
));
}
@ -504,7 +502,7 @@ fn augment_param_env<'tcx>(
);
// FIXME(compiler-errors): Perhaps there is a case where we need to normalize this
// i.e. traits::normalize_param_env_or_error
ty::ParamEnv::new(bounds, param_env.reveal(), param_env.constness())
ty::ParamEnv::new(bounds, param_env.reveal())
}
/// We use the following trait as an example throughout this function.
@ -1415,7 +1413,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
traits::wf::predicate_obligations(
infcx,
wfcx.param_env.without_const(),
wfcx.param_env,
wfcx.body_def_id,
p.as_predicate(),
sp,

View File

@ -81,7 +81,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!(?bound_sig, ?liberated_sig);
let mut fcx = FnCtxt::new(self, self.param_env.without_const(), closure.def_id);
let mut fcx = FnCtxt::new(self, self.param_env, closure.def_id);
let generator_types = check_fn(
&mut fcx,
liberated_sig,

View File

@ -1334,7 +1334,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
t_cast,
t.span,
expr.span,
self.param_env.constness(),
hir::Constness::NotConst,
) {
Ok(cast_check) => {
debug!(
@ -1428,7 +1428,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Create a new function context.
let def_id = block.def_id;
let fcx = FnCtxt::new(self, self.param_env.with_const(), def_id);
let fcx = FnCtxt::new(self, self.param_env, def_id);
crate::GatherLocalsVisitor::new(&fcx).visit_body(body);
let ty = fcx.check_expr_with_expectation(&body.value, expected);

View File

@ -45,12 +45,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
for cast in deferred_cast_checks.drain(..) {
let prev_env = self.param_env;
self.param_env = self.param_env.with_constness(cast.constness);
cast.check(self);
self.param_env = prev_env;
}
*self.deferred_cast_checks.borrow_mut() = deferred_cast_checks;

View File

@ -71,7 +71,7 @@ use rustc_middle::traits;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::config;
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::{sym, Span};
use rustc_span::Span;
fluent_messages! { "../messages.ftl" }
@ -182,11 +182,7 @@ fn typeck_with_fallback<'tcx>(
let body = tcx.hir().body(body_id);
let param_env = tcx.param_env(def_id);
let param_env = if tcx.has_attr(def_id, sym::rustc_do_not_const_check) {
param_env.without_const()
} else {
param_env
};
let inh = Inherited::new(tcx, def_id);
let mut fcx = FnCtxt::new(&inh, param_env, def_id);
@ -263,11 +259,7 @@ fn typeck_with_fallback<'tcx>(
// Closure and generator analysis may run after fallback
// because they don't constrain other type variables.
// Closure analysis only runs on closures. Therefore they only need to fulfill non-const predicates (as of now)
let prev_constness = fcx.param_env.constness();
fcx.param_env = fcx.param_env.without_const();
fcx.closure_analyze(body);
fcx.param_env = fcx.param_env.with_constness(prev_constness);
assert!(fcx.deferred_call_resolutions.borrow().is_empty());
// Before the generator analysis, temporary scopes shall be marked to provide more
// precise information on types to be captured.

View File

@ -79,7 +79,6 @@ impl<'tcx> PredicateObligation<'tcx> {
}
pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> PredicateObligation<'tcx> {
self.param_env = self.param_env.without_const();
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = self.predicate.kind().skip_binder() && trait_pred.is_const_if_const() {
self.predicate = tcx.mk_predicate(self.predicate.kind().map_bound(|_| ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred.without_const()))));
}
@ -88,14 +87,6 @@ impl<'tcx> PredicateObligation<'tcx> {
}
impl<'tcx> PolyTraitObligation<'tcx> {
/// Returns `true` if the trait predicate is considered `const` in its ParamEnv.
pub fn is_const(&self) -> bool {
matches!(
(self.predicate.skip_binder().constness, self.param_env.constness()),
(ty::BoundConstness::ConstIfConst, hir::Constness::Const)
)
}
pub fn derived_cause(
&self,
variant: impl FnOnce(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,

View File

@ -139,7 +139,6 @@ 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));
@ -158,8 +157,6 @@ impl<'tcx> TyCtxt<'tcx> {
cid: GlobalId<'tcx>,
span: Option<Span>,
) -> EvalToValTreeResult<'tcx> {
let param_env = param_env.with_const();
debug!(?param_env);
// 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));
@ -204,7 +201,6 @@ impl<'tcx> TyCtxtAt<'tcx> {
gid: GlobalId<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Result<mir::ConstAllocation<'tcx>, 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())
@ -224,8 +220,7 @@ impl<'tcx> TyCtxtEnsure<'tcx> {
let args = GenericArgs::identity_for_item(self.tcx, def_id);
let instance = ty::Instance::new(def_id, args);
let cid = GlobalId { instance, promoted: None };
let param_env =
self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx).with_const();
let param_env = self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx);
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
// improve caching of queries.
let inputs = self.tcx.erase_regions(param_env.and(cid));
@ -238,7 +233,7 @@ impl<'tcx> TyCtxtEnsure<'tcx> {
assert!(self.tcx.is_static(def_id));
let instance = ty::Instance::mono(self.tcx, def_id);
let gid = GlobalId { instance, promoted: None };
let param_env = ty::ParamEnv::reveal_all().with_const();
let param_env = ty::ParamEnv::reveal_all();
trace!("eval_to_allocation: Need to compute {:?}", gid);
self.eval_to_allocation_raw(param_env.and(gid))
}

View File

@ -168,7 +168,6 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::ParamEnv<'tcx> {
fn encode(&self, e: &mut E) {
self.caller_bounds().encode(e);
self.reveal().encode(e);
self.constness().encode(e);
}
}
@ -306,8 +305,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::ParamEnv<'tcx> {
fn decode(d: &mut D) -> Self {
let caller_bounds = Decodable::decode(d);
let reveal = Decodable::decode(d);
let constness = Decodable::decode(d);
ty::ParamEnv::new(caller_bounds, reveal, constness)
ty::ParamEnv::new(caller_bounds, reveal)
}
}

View File

@ -867,20 +867,6 @@ pub struct TraitPredicate<'tcx> {
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
impl<'tcx> TraitPredicate<'tcx> {
pub fn remap_constness(&mut self, param_env: &mut ParamEnv<'tcx>) {
*param_env = param_env.with_constness(self.constness.and(param_env.constness()))
}
/// Remap the constness of this predicate before emitting it for diagnostics.
pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) {
// this is different to `remap_constness` that callees want to print this predicate
// in case of selection errors. `T: ~const Drop` bounds cannot end up here when the
// param_env is not const because it is always satisfied in non-const contexts.
if let hir::Constness::NotConst = param_env.constness() {
self.constness = ty::BoundConstness::NotConst;
}
}
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
}
@ -922,14 +908,6 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
self.map_bound(|trait_ref| trait_ref.self_ty())
}
/// Remap the constness of this predicate before emitting it for diagnostics.
pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) {
*self = self.map_bound(|mut p| {
p.remap_constness_diag(param_env);
p
});
}
#[inline]
pub fn is_const_if_const(self) -> bool {
self.skip_binder().is_const_if_const()
@ -1700,15 +1678,12 @@ pub struct ParamEnv<'tcx> {
#[derive(Copy, Clone)]
struct ParamTag {
reveal: traits::Reveal,
constness: hir::Constness,
}
impl_tag! {
impl Tag for ParamTag;
ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst },
ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::NotConst },
ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const },
ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::Const },
ParamTag { reveal: traits::Reveal::UserFacing },
ParamTag { reveal: traits::Reveal::All },
}
impl<'tcx> fmt::Debug for ParamEnv<'tcx> {
@ -1716,7 +1691,6 @@ 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()
}
}
@ -1725,7 +1699,6 @@ 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);
}
}
@ -1737,7 +1710,6 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
Ok(ParamEnv::new(
self.caller_bounds().try_fold_with(folder)?,
self.reveal().try_fold_with(folder)?,
self.constness(),
))
}
}
@ -1756,7 +1728,7 @@ impl<'tcx> ParamEnv<'tcx> {
/// type-checking.
#[inline]
pub fn empty() -> Self {
Self::new(List::empty(), Reveal::UserFacing, hir::Constness::NotConst)
Self::new(List::empty(), Reveal::UserFacing)
}
#[inline]
@ -1769,16 +1741,6 @@ impl<'tcx> ParamEnv<'tcx> {
self.packed.tag().reveal
}
#[inline]
pub fn constness(self) -> hir::Constness {
self.packed.tag().constness
}
#[inline]
pub fn is_const(self) -> bool {
self.packed.tag().constness == hir::Constness::Const
}
/// Construct a trait environment with no where-clauses in scope
/// where the values of all `impl Trait` and other hidden types
/// are revealed. This is suitable for monomorphized, post-typeck
@ -1788,17 +1750,13 @@ impl<'tcx> ParamEnv<'tcx> {
/// or invoke `param_env.with_reveal_all()`.
#[inline]
pub fn reveal_all() -> Self {
Self::new(List::empty(), Reveal::All, hir::Constness::NotConst)
Self::new(List::empty(), Reveal::All)
}
/// Construct a trait environment with the given set of predicates.
#[inline]
pub fn new(
caller_bounds: &'tcx List<Clause<'tcx>>,
reveal: Reveal,
constness: hir::Constness,
) -> Self {
ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal, constness }) }
pub fn new(caller_bounds: &'tcx List<Clause<'tcx>>, reveal: Reveal) -> Self {
ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal }) }
}
pub fn with_user_facing(mut self) -> Self {
@ -1806,29 +1764,6 @@ impl<'tcx> ParamEnv<'tcx> {
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
@ -1843,17 +1778,13 @@ impl<'tcx> ParamEnv<'tcx> {
return self;
}
ParamEnv::new(
tcx.reveal_opaque_types_in_bounds(self.caller_bounds()),
Reveal::All,
self.constness(),
)
ParamEnv::new(tcx.reveal_opaque_types_in_bounds(self.caller_bounds()), Reveal::All)
}
/// Returns this same environment but with no caller bounds.
#[inline]
pub fn without_caller_bounds(self) -> Self {
Self::new(List::empty(), self.reveal(), self.constness())
Self::new(List::empty(), self.reveal())
}
/// Creates a suitable environment in which to perform trait

View File

@ -602,7 +602,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(), self.constness()))
.map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal()))
}
}

View File

@ -449,14 +449,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
return Err(NoSolution);
}
if !goal.param_env.is_const() {
// `Destruct` is automatically implemented for every type in
// non-const environments.
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
} else {
// FIXME(-Ztrait-solver=next): Implement this when we get const working in the new solver
Err(NoSolution)
}
// FIXME(-Ztrait-solver=next): Implement this when we get const working in the new solver
// `Destruct` is automatically implemented for every type in
// non-const environments.
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
fn consider_builtin_transmute_candidate(

View File

@ -347,14 +347,12 @@ impl<'tcx> AutoTraitFinder<'tcx> {
new_env = ty::ParamEnv::new(
tcx.mk_clauses_from_iter(normalized_preds.filter_map(|p| p.as_clause())),
param_env.reveal(),
param_env.constness(),
);
}
let final_user_env = ty::ParamEnv::new(
tcx.mk_clauses_from_iter(user_computed_preds.into_iter().filter_map(|p| p.as_clause())),
user_env.reveal(),
user_env.constness(),
);
debug!(
"evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \

View File

@ -687,9 +687,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
match bound_predicate.skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
let trait_predicate = bound_predicate.rebind(trait_predicate);
let mut trait_predicate = self.resolve_vars_if_possible(trait_predicate);
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
trait_predicate.remap_constness_diag(obligation.param_env);
let predicate_is_const = ty::BoundConstness::ConstIfConst
== trait_predicate.skip_binder().constness;
@ -3108,11 +3107,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
span: Span,
) -> UnsatisfiedConst {
let mut unsatisfied_const = UnsatisfiedConst(false);
if trait_predicate.is_const_if_const() && obligation.param_env.is_const() {
if trait_predicate.is_const_if_const() {
let non_const_predicate = trait_ref.without_const();
let non_const_obligation = Obligation {
cause: obligation.cause.clone(),
param_env: obligation.param_env.without_const(),
param_env: obligation.param_env,
predicate: non_const_predicate.to_predicate(self.tcx),
recursion_depth: obligation.recursion_depth,
};

View File

@ -3136,7 +3136,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
ObligationCauseCode::ImplDerivedObligation(ref data) => {
let mut parent_trait_pred =
self.resolve_vars_if_possible(data.derived.parent_trait_pred);
parent_trait_pred.remap_constness_diag(param_env);
let parent_def_id = parent_trait_pred.def_id();
let (self_ty, file) =
self.tcx.short_ty_string(parent_trait_pred.skip_binder().self_ty());

View File

@ -328,11 +328,7 @@ pub fn normalize_param_env_or_error<'tcx>(
debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
let elaborated_env = ty::ParamEnv::new(
tcx.mk_clauses(&predicates),
unnormalized_env.reveal(),
unnormalized_env.constness(),
);
let elaborated_env = ty::ParamEnv::new(tcx.mk_clauses(&predicates), unnormalized_env.reveal());
// HACK: we are trying to normalize the param-env inside *itself*. The problem is that
// normalization expects its param-env to be already normalized, which means we have
@ -376,11 +372,8 @@ pub fn normalize_param_env_or_error<'tcx>(
// here. I believe they should not matter, because we are ignoring TypeOutlives param-env
// predicates here anyway. Keeping them here anyway because it seems safer.
let outlives_env = non_outlives_predicates.iter().chain(&outlives_predicates).cloned();
let outlives_env = ty::ParamEnv::new(
tcx.mk_clauses_from_iter(outlives_env),
unnormalized_env.reveal(),
unnormalized_env.constness(),
);
let outlives_env =
ty::ParamEnv::new(tcx.mk_clauses_from_iter(outlives_env), unnormalized_env.reveal());
let Ok(outlives_predicates) =
do_normalize_predicates(tcx, cause, outlives_env, outlives_predicates)
else {
@ -393,11 +386,7 @@ pub fn normalize_param_env_or_error<'tcx>(
let mut predicates = non_outlives_predicates;
predicates.extend(outlives_predicates);
debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
ty::ParamEnv::new(
tcx.mk_clauses(&predicates),
unnormalized_env.reveal(),
unnormalized_env.constness(),
)
ty::ParamEnv::new(tcx.mk_clauses(&predicates), unnormalized_env.reveal())
}
/// Normalize a type and process all resulting obligations, returning any errors.

View File

@ -761,11 +761,7 @@ fn receiver_is_dispatchable<'tcx>(
let caller_bounds =
param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]);
ty::ParamEnv::new(
tcx.mk_clauses_from_iter(caller_bounds),
param_env.reveal(),
param_env.constness(),
)
ty::ParamEnv::new(tcx.mk_clauses_from_iter(caller_bounds), param_env.reveal())
};
// Receiver: DispatchFromDyn<Receiver[Self => U]>

View File

@ -1,5 +1,4 @@
use rustc_infer::traits::{TraitEngine, TraitEngineExt};
use rustc_middle::ty;
use crate::infer::canonical::OriginalQueryValues;
use crate::infer::InferCtxt;
@ -66,17 +65,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
) -> Result<EvaluationResult, OverflowError> {
let mut _orig_values = OriginalQueryValues::default();
let param_env = match obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
// we ignore the value set to it.
let mut _constness = pred.constness;
obligation
.param_env
.with_constness(_constness.and(obligation.param_env.constness()))
}
// constness has no effect on the given predicate.
_ => obligation.param_env.without_const(),
};
let param_env = obligation.param_env;
if self.next_trait_solver() {
self.probe(|snapshot| {

View File

@ -82,7 +82,6 @@ fn relate_mir_and_user_args<'tcx>(
def_id: DefId,
user_args: UserArgs<'tcx>,
) -> Result<(), NoSolution> {
let param_env = param_env.without_const();
let UserArgs { user_self_ty, args } = user_args;
let tcx = ocx.infcx.tcx;
let cause = ObligationCause::dummy_with_span(span);

View File

@ -839,7 +839,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) {
// If the predicate is `~const Destruct` in a non-const environment, we don't actually need
// to check anything. We'll short-circuit checking any obligations in confirmation, too.
if !obligation.is_const() {
// FIXME(effects)
if true {
candidates.vec.push(ConstDestructCandidate(None));
return;
}

View File

@ -13,8 +13,8 @@ use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_middle::traits::{BuiltinImplSource, SelectionOutputTypeParameterMismatch};
use rustc_middle::ty::{
self, Binder, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate,
TraitPredicate, TraitRef, Ty, TyCtxt, TypeVisitableExt,
self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate,
TraitPredicate, Ty, TyCtxt, TypeVisitableExt,
};
use rustc_span::def_id::DefId;
@ -647,7 +647,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn confirm_fn_pointer_candidate(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
is_const: bool,
// FIXME(effects)
_is_const: bool,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
debug!(?obligation, "confirm_fn_pointer_candidate");
@ -674,16 +675,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
let cause = obligation.derived_cause(BuiltinDerivedObligation);
if obligation.is_const() && !is_const {
// function is a trait method
if let ty::FnDef(def_id, args) = self_ty.kind() && let Some(trait_id) = tcx.trait_of_item(*def_id) {
let trait_ref = TraitRef::from_method(tcx, trait_id, *args);
let poly_trait_pred = Binder::dummy(trait_ref).with_constness(ty::BoundConstness::ConstIfConst);
let obligation = Obligation::new(tcx, cause.clone(), obligation.param_env, poly_trait_pred);
nested.push(obligation);
}
}
// Confirm the `type Output: Sized;` bound that is present on `FnOnce`
let output_ty = self.infcx.instantiate_binder_with_placeholders(sig.output());
let output_ty = normalize_with_depth_to(
@ -1211,7 +1202,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
impl_def_id: Option<DefId>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
// `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop`
if !obligation.is_const() {
// FIXME(effects)
if true {
return Ok(vec![]);
}

View File

@ -1000,13 +1000,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
let stack = self.push_stack(previous_stack, &obligation);
let mut fresh_trait_pred = stack.fresh_trait_pred;
let mut param_env = obligation.param_env;
fresh_trait_pred = fresh_trait_pred.map_bound(|mut pred| {
pred.remap_constness(&mut param_env);
pred
});
let fresh_trait_pred = stack.fresh_trait_pred;
let param_env = obligation.param_env;
debug!(?fresh_trait_pred);
@ -1386,8 +1381,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
(result, dep_node)
}
/// filter_impls filters constant trait obligations and candidates that have a positive impl
/// for a negative goal and a negative impl for a positive goal
/// filter_impls filters candidates that have a positive impl for a negative
/// goal and a negative impl for a positive goal
#[instrument(level = "debug", skip(self, candidates))]
fn filter_impls(
&mut self,
@ -1399,42 +1394,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let mut result = Vec::with_capacity(candidates.len());
for candidate in candidates {
// Respect const trait obligations
if obligation.is_const() {
match candidate {
// const impl
ImplCandidate(def_id) if tcx.constness(def_id) == hir::Constness::Const => {}
// const param
ParamCandidate(trait_pred) if trait_pred.is_const_if_const() => {}
// const projection
ProjectionCandidate(_, ty::BoundConstness::ConstIfConst)
// auto trait impl
| AutoImplCandidate
// generator / future, this will raise error in other places
// or ignore error with const_async_blocks feature
| GeneratorCandidate
| FutureCandidate
// FnDef where the function is const
| FnPointerCandidate { is_const: true }
| ConstDestructCandidate(_)
| ClosureCandidate { is_const: true } => {}
FnPointerCandidate { is_const: false } => {
if let ty::FnDef(def_id, _) = obligation.self_ty().skip_binder().kind() && tcx.trait_of_item(*def_id).is_some() {
// Trait methods are not seen as const unless the trait is implemented as const.
// We do not filter that out in here, but nested obligations will be needed to confirm this.
} else {
continue
}
}
_ => {
// reject all other types of candidates
continue;
}
}
}
if let ImplCandidate(def_id) = candidate {
if ty::ImplPolarity::Reservation == tcx.impl_polarity(def_id)
|| obligation.polarity() == tcx.impl_polarity(def_id)
@ -1528,7 +1487,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn check_candidate_cache(
&mut self,
mut param_env: ty::ParamEnv<'tcx>,
param_env: ty::ParamEnv<'tcx>,
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
// Neither the global nor local cache is aware of intercrate
@ -1539,8 +1498,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return None;
}
let tcx = self.tcx();
let mut pred = cache_fresh_trait_pred.skip_binder();
pred.remap_constness(&mut param_env);
let pred = cache_fresh_trait_pred.skip_binder();
if self.can_use_global_caches(param_env) {
if let Some(res) = tcx.selection_cache.get(&(param_env, pred), tcx) {
@ -1586,15 +1544,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(skip(self, param_env, cache_fresh_trait_pred, dep_node), level = "debug")]
fn insert_candidate_cache(
&mut self,
mut param_env: ty::ParamEnv<'tcx>,
param_env: ty::ParamEnv<'tcx>,
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
dep_node: DepNodeIndex,
candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>,
) {
let tcx = self.tcx();
let mut pred = cache_fresh_trait_pred.skip_binder();
pred.remap_constness(&mut param_env);
let pred = cache_fresh_trait_pred.skip_binder();
if !self.can_cache_candidate(&candidate) {
debug!(?pred, ?candidate, "insert_candidate_cache - candidate is not cacheable");

View File

@ -144,85 +144,9 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
}
let local_did = def_id.as_local();
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): This isn't correct for
// RPITITs in const trait fn.
let hir_id = local_did.and_then(|def_id| tcx.opt_local_def_id_to_hir_id(def_id));
// FIXME(consts): This is not exactly in line with the constness query.
let constness = match hir_id {
Some(hir_id) => match tcx.hir().get(hir_id) {
hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. })
if tcx.is_const_default_method(def_id) =>
{
hir::Constness::Const
}
hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. })
| hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. })
| hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Const(..), ..
})
| hir::Node::AnonConst(_)
| hir::Node::ConstBlock(_)
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. })
| hir::Node::ImplItem(hir::ImplItem {
kind:
hir::ImplItemKind::Fn(
hir::FnSig {
header: hir::FnHeader { constness: hir::Constness::Const, .. },
..
},
..,
),
..
}) => hir::Constness::Const,
hir::Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..),
..
}) => {
let parent_hir_id = tcx.hir().parent_id(hir_id);
match tcx.hir().get(parent_hir_id) {
hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl(hir::Impl { constness, .. }),
..
}) => *constness,
_ => span_bug!(
tcx.def_span(parent_hir_id.owner),
"impl item's parent node is not an impl",
),
}
}
hir::Node::Item(hir::Item {
kind:
hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..),
..
})
| hir::Node::TraitItem(hir::TraitItem {
kind:
hir::TraitItemKind::Fn(
hir::FnSig { header: hir::FnHeader { constness, .. }, .. },
..,
),
..
})
| hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl(hir::Impl { constness, .. }),
..
}) => *constness,
_ => hir::Constness::NotConst,
},
// FIXME(consts): It's suspicious that a param-env for a foreign item
// will always have NotConst param-env, though we don't typically use
// that param-env for anything meaningful right now, so it's likely
// not an issue.
None => hir::Constness::NotConst,
};
let unnormalized_env =
ty::ParamEnv::new(tcx.mk_clauses(&predicates), traits::Reveal::UserFacing, constness);
ty::ParamEnv::new(tcx.mk_clauses(&predicates), traits::Reveal::UserFacing);
let body_id = local_did.unwrap_or(CRATE_DEF_ID);
let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);

View File

@ -6,7 +6,7 @@ use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor};
use rustc_hir::{
self as hir, BlockCheckMode, BodyId, Constness, Expr, ExprKind, FnDecl, Impl, Item, ItemKind, UnsafeSource,
self as hir, BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, Impl, Item, ItemKind, UnsafeSource,
Unsafety,
};
use rustc_lint::{LateContext, LateLintPass};
@ -526,6 +526,5 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
}),
)),
Reveal::UserFacing,
Constness::NotConst,
)
}

View File

@ -83,7 +83,7 @@ impl Variant {
impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if !in_external_macro(cx.sess(), expr.span)
&& (!cx.param_env.is_const() || cx.tcx.features().active(sym!(const_float_classify)))
&& cx.tcx.features().active(sym!(const_float_classify))
&& let ExprKind::Binary(kind, lhs, rhs) = expr.kind
&& let ExprKind::Binary(lhs_kind, lhs_lhs, lhs_rhs) = lhs.kind
&& let ExprKind::Binary(rhs_kind, rhs_lhs, rhs_rhs) = rhs.kind

View File

@ -399,7 +399,7 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>
let obligation = Obligation::new(
tcx,
ObligationCause::dummy_with_span(body.span),
ConstCx::new(tcx, body).param_env.with_const(),
ConstCx::new(tcx, body).param_env,
TraitRef::from_lang_item(tcx, LangItem::Destruct, body.span, [ty]).with_constness(BoundConstness::ConstIfConst),
);