Auto merge of #76244 - vandenheuvel:remove__paramenv__def_id, r=nikomatsakis
Removing the `def_id` field from hot `ParamEnv` to make it smaller This PR addresses https://github.com/rust-lang/rust/issues/74865.
This commit is contained in:
commit
7402a39447
35 changed files with 288 additions and 337 deletions
|
@ -1261,7 +1261,8 @@ crate fn required_region_bounds(
|
|||
| ty::PredicateAtom::ClosureKind(..)
|
||||
| ty::PredicateAtom::RegionOutlives(..)
|
||||
| ty::PredicateAtom::ConstEvaluatable(..)
|
||||
| ty::PredicateAtom::ConstEquate(..) => None,
|
||||
| ty::PredicateAtom::ConstEquate(..)
|
||||
| ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
|
||||
ty::PredicateAtom::TypeOutlives(ty::OutlivesPredicate(ref t, ref r)) => {
|
||||
// Search for a bound of the form `erased_self_ty
|
||||
// : 'a`, but be wary of something like `for<'a>
|
||||
|
|
|
@ -373,14 +373,12 @@ impl AutoTraitFinder<'tcx> {
|
|||
computed_preds.clone().chain(user_computed_preds.iter().cloned()),
|
||||
)
|
||||
.map(|o| o.predicate);
|
||||
new_env =
|
||||
ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal(), None);
|
||||
new_env = ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal());
|
||||
}
|
||||
|
||||
let final_user_env = ty::ParamEnv::new(
|
||||
tcx.mk_predicates(user_computed_preds.into_iter()),
|
||||
user_env.reveal(),
|
||||
None,
|
||||
);
|
||||
debug!(
|
||||
"evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \
|
||||
|
|
|
@ -4,12 +4,11 @@ use crate::infer::canonical::OriginalQueryValues;
|
|||
use crate::infer::InferCtxt;
|
||||
use crate::traits::query::NoSolution;
|
||||
use crate::traits::{
|
||||
ChalkEnvironmentAndGoal, ChalkEnvironmentClause, FulfillmentError, FulfillmentErrorCode,
|
||||
ObligationCause, PredicateObligation, SelectionError, TraitEngine,
|
||||
ChalkEnvironmentAndGoal, FulfillmentError, FulfillmentErrorCode, ObligationCause,
|
||||
PredicateObligation, SelectionError, TraitEngine,
|
||||
};
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
||||
pub struct FulfillmentContext<'tcx> {
|
||||
obligations: FxIndexSet<PredicateObligation<'tcx>>,
|
||||
|
@ -21,132 +20,6 @@ impl FulfillmentContext<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn environment<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
) -> &'tcx ty::List<ChalkEnvironmentClause<'tcx>> {
|
||||
use rustc_hir::{ForeignItemKind, ImplItemKind, ItemKind, Node, TraitItemKind};
|
||||
use rustc_middle::ty::subst::GenericArgKind;
|
||||
|
||||
debug!("environment(def_id = {:?})", def_id);
|
||||
|
||||
// The environment of an impl Trait type is its defining function's environment.
|
||||
if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
|
||||
return environment(tcx, parent);
|
||||
}
|
||||
|
||||
// Compute the bounds on `Self` and the type parameters.
|
||||
let ty::InstantiatedPredicates { predicates, .. } =
|
||||
tcx.predicates_of(def_id).instantiate_identity(tcx);
|
||||
|
||||
let clauses = predicates.into_iter().map(ChalkEnvironmentClause::Predicate);
|
||||
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
|
||||
let node = tcx.hir().get(hir_id);
|
||||
|
||||
enum NodeKind {
|
||||
TraitImpl,
|
||||
InherentImpl,
|
||||
Fn,
|
||||
Other,
|
||||
};
|
||||
|
||||
let node_kind = match node {
|
||||
Node::TraitItem(item) => match item.kind {
|
||||
TraitItemKind::Fn(..) => NodeKind::Fn,
|
||||
_ => NodeKind::Other,
|
||||
},
|
||||
|
||||
Node::ImplItem(item) => match item.kind {
|
||||
ImplItemKind::Fn(..) => NodeKind::Fn,
|
||||
_ => NodeKind::Other,
|
||||
},
|
||||
|
||||
Node::Item(item) => match item.kind {
|
||||
ItemKind::Impl { of_trait: Some(_), .. } => NodeKind::TraitImpl,
|
||||
ItemKind::Impl { of_trait: None, .. } => NodeKind::InherentImpl,
|
||||
ItemKind::Fn(..) => NodeKind::Fn,
|
||||
_ => NodeKind::Other,
|
||||
},
|
||||
|
||||
Node::ForeignItem(item) => match item.kind {
|
||||
ForeignItemKind::Fn(..) => NodeKind::Fn,
|
||||
_ => NodeKind::Other,
|
||||
},
|
||||
|
||||
// FIXME: closures?
|
||||
_ => NodeKind::Other,
|
||||
};
|
||||
|
||||
// FIXME(eddyb) isn't the unordered nature of this a hazard?
|
||||
let mut inputs = FxIndexSet::default();
|
||||
|
||||
match node_kind {
|
||||
// In a trait impl, we assume that the header trait ref and all its
|
||||
// constituents are well-formed.
|
||||
NodeKind::TraitImpl => {
|
||||
let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
|
||||
|
||||
// FIXME(chalk): this has problems because of late-bound regions
|
||||
//inputs.extend(trait_ref.substs.iter().flat_map(|arg| arg.walk()));
|
||||
inputs.extend(trait_ref.substs.iter());
|
||||
}
|
||||
|
||||
// In an inherent impl, we assume that the receiver type and all its
|
||||
// constituents are well-formed.
|
||||
NodeKind::InherentImpl => {
|
||||
let self_ty = tcx.type_of(def_id);
|
||||
inputs.extend(self_ty.walk());
|
||||
}
|
||||
|
||||
// In an fn, we assume that the arguments and all their constituents are
|
||||
// well-formed.
|
||||
NodeKind::Fn => {
|
||||
let fn_sig = tcx.fn_sig(def_id);
|
||||
let fn_sig = tcx.liberate_late_bound_regions(def_id, &fn_sig);
|
||||
|
||||
inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk()));
|
||||
}
|
||||
|
||||
NodeKind::Other => (),
|
||||
}
|
||||
let input_clauses = inputs.into_iter().filter_map(|arg| {
|
||||
match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => Some(ChalkEnvironmentClause::TypeFromEnv(ty)),
|
||||
|
||||
// FIXME(eddyb) no WF conditions from lifetimes?
|
||||
GenericArgKind::Lifetime(_) => None,
|
||||
|
||||
// FIXME(eddyb) support const generics in Chalk
|
||||
GenericArgKind::Const(_) => None,
|
||||
}
|
||||
});
|
||||
|
||||
tcx.mk_chalk_environment_clause_list(clauses.chain(input_clauses))
|
||||
}
|
||||
|
||||
/// We need to wrap a `ty::Predicate` in an elaborated environment *before* we
|
||||
/// canonicalize. This is due to the fact that we insert extra clauses into the
|
||||
/// environment for all input types (`FromEnv`).
|
||||
fn in_environment(
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
) -> ChalkEnvironmentAndGoal<'tcx> {
|
||||
assert!(!infcx.is_in_snapshot());
|
||||
let obligation = infcx.resolve_vars_if_possible(obligation);
|
||||
|
||||
let environment = match obligation.param_env.def_id {
|
||||
Some(def_id) => environment(infcx.tcx, def_id),
|
||||
None if obligation.param_env.caller_bounds().is_empty() => ty::List::empty(),
|
||||
// FIXME(chalk): this is hit in ui/where-clauses/where-clause-constraints-are-local-for-trait-impl
|
||||
// and ui/generics/generic-static-methods
|
||||
//_ => bug!("non-empty `ParamEnv` with no def-id"),
|
||||
_ => ty::List::empty(),
|
||||
};
|
||||
|
||||
ChalkEnvironmentAndGoal { environment, goal: obligation.predicate }
|
||||
}
|
||||
|
||||
impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
||||
fn normalize_projection_type(
|
||||
&mut self,
|
||||
|
@ -195,6 +68,8 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
|||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
|
||||
assert!(!infcx.is_in_snapshot());
|
||||
|
||||
let mut errors = Vec::new();
|
||||
let mut next_round = FxIndexSet::default();
|
||||
let mut making_progress;
|
||||
|
@ -205,10 +80,11 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
|||
// We iterate over all obligations, and record if we are able
|
||||
// to unambiguously prove at least one obligation.
|
||||
for obligation in self.obligations.drain(..) {
|
||||
let goal_in_environment = in_environment(infcx, &obligation);
|
||||
let obligation = infcx.resolve_vars_if_possible(&obligation);
|
||||
let environment = obligation.param_env.caller_bounds();
|
||||
let goal = ChalkEnvironmentAndGoal { environment, goal: obligation.predicate };
|
||||
let mut orig_values = OriginalQueryValues::default();
|
||||
let canonical_goal =
|
||||
infcx.canonicalize_query(&goal_in_environment, &mut orig_values);
|
||||
let canonical_goal = infcx.canonicalize_query(&goal, &mut orig_values);
|
||||
|
||||
match infcx.tcx.evaluate_goal(canonical_goal) {
|
||||
Ok(response) => {
|
||||
|
|
|
@ -663,6 +663,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||
obligation
|
||||
)
|
||||
}
|
||||
|
||||
ty::PredicateAtom::TypeWellFormedFromEnv(..) => span_bug!(
|
||||
span,
|
||||
"TypeWellFormedFromEnv predicate should only exist in the environment"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ pub struct PendingPredicateObligation<'tcx> {
|
|||
|
||||
// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
static_assert_size!(PendingPredicateObligation<'_>, 64);
|
||||
static_assert_size!(PendingPredicateObligation<'_>, 56);
|
||||
|
||||
impl<'a, 'tcx> FulfillmentContext<'tcx> {
|
||||
/// Creates a new fulfillment context.
|
||||
|
@ -355,6 +355,9 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
|||
obligation.with(pred.to_predicate(self.selcx.tcx())),
|
||||
]))
|
||||
}
|
||||
ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
|
||||
bug!("TypeWellFormedFromEnv is only used for Chalk")
|
||||
}
|
||||
},
|
||||
&ty::PredicateKind::Atom(atom) => match atom {
|
||||
ty::PredicateAtom::Trait(ref data, _) => {
|
||||
|
@ -536,6 +539,9 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
|
||||
bug!("TypeWellFormedFromEnv is only used for Chalk")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -302,11 +302,8 @@ pub fn normalize_param_env_or_error<'tcx>(
|
|||
|
||||
debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
|
||||
|
||||
let elaborated_env = ty::ParamEnv::new(
|
||||
tcx.intern_predicates(&predicates),
|
||||
unnormalized_env.reveal(),
|
||||
unnormalized_env.def_id,
|
||||
);
|
||||
let elaborated_env =
|
||||
ty::ParamEnv::new(tcx.intern_predicates(&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
|
||||
|
@ -360,7 +357,7 @@ pub fn normalize_param_env_or_error<'tcx>(
|
|||
let outlives_env: Vec<_> =
|
||||
non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect();
|
||||
let outlives_env =
|
||||
ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal(), None);
|
||||
ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal());
|
||||
let outlives_predicates = match do_normalize_predicates(
|
||||
tcx,
|
||||
region_context,
|
||||
|
@ -380,11 +377,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.intern_predicates(&predicates),
|
||||
unnormalized_env.reveal(),
|
||||
unnormalized_env.def_id,
|
||||
)
|
||||
ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal())
|
||||
}
|
||||
|
||||
pub fn fully_normalize<'a, 'tcx, T>(
|
||||
|
|
|
@ -276,7 +276,8 @@ fn predicates_reference_self(
|
|||
| ty::PredicateAtom::ClosureKind(..)
|
||||
| ty::PredicateAtom::Subtype(..)
|
||||
| ty::PredicateAtom::ConstEvaluatable(..)
|
||||
| ty::PredicateAtom::ConstEquate(..) => None,
|
||||
| ty::PredicateAtom::ConstEquate(..)
|
||||
| ty::PredicateAtom::TypeWellFormedFromEnv(..) => None,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
|
@ -310,7 +311,8 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
|||
| ty::PredicateAtom::ClosureKind(..)
|
||||
| ty::PredicateAtom::TypeOutlives(..)
|
||||
| ty::PredicateAtom::ConstEvaluatable(..)
|
||||
| ty::PredicateAtom::ConstEquate(..) => false,
|
||||
| ty::PredicateAtom::ConstEquate(..)
|
||||
| ty::PredicateAtom::TypeWellFormedFromEnv(..) => false,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -654,11 +656,7 @@ fn receiver_is_dispatchable<'tcx>(
|
|||
.chain(iter::once(trait_predicate))
|
||||
.collect();
|
||||
|
||||
ty::ParamEnv::new(
|
||||
tcx.intern_predicates(&caller_bounds),
|
||||
param_env.reveal(),
|
||||
param_env.def_id,
|
||||
)
|
||||
ty::ParamEnv::new(tcx.intern_predicates(&caller_bounds), param_env.reveal())
|
||||
};
|
||||
|
||||
// Receiver: DispatchFromDyn<Receiver[Self => U]>
|
||||
|
|
|
@ -593,6 +593,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
|
||||
bug!("TypeWellFormedFromEnv is only used for chalk")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,6 +127,9 @@ pub fn predicate_obligations<'a, 'tcx>(
|
|||
wf.compute(c1.into());
|
||||
wf.compute(c2.into());
|
||||
}
|
||||
ty::PredicateAtom::TypeWellFormedFromEnv(..) => {
|
||||
bug!("TypeWellFormedFromEnv is only used for Chalk")
|
||||
}
|
||||
}
|
||||
|
||||
wf.normalize()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue