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
|
@ -3,7 +3,7 @@ use crate::traits::{self, TraitEngine};
|
|||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, WithConstness};
|
||||
use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{ToPredicate, TypeFoldable};
|
||||
use rustc_session::{DiagnosticMessageId, Limit};
|
||||
use rustc_span::def_id::LOCAL_CRATE;
|
||||
|
|
|
@ -9,7 +9,6 @@ use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, Quer
|
|||
use rustc_middle::traits::query::Fallible;
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::ToPredicate;
|
||||
use rustc_middle::ty::WithConstness;
|
||||
use rustc_middle::ty::{self, Ty, TypeFoldable};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
|
|
|
@ -370,12 +370,17 @@ 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());
|
||||
new_env = ty::ParamEnv::new(
|
||||
tcx.mk_predicates(normalized_preds),
|
||||
param_env.reveal(),
|
||||
param_env.constness(),
|
||||
);
|
||||
}
|
||||
|
||||
let final_user_env = ty::ParamEnv::new(
|
||||
tcx.mk_predicates(user_computed_preds.into_iter()),
|
||||
user_env.reveal(),
|
||||
user_env.constness(),
|
||||
);
|
||||
debug!(
|
||||
"evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \
|
||||
|
|
|
@ -24,7 +24,7 @@ use rustc_middle::ty::error::ExpectedFound;
|
|||
use rustc_middle::ty::fold::TypeFolder;
|
||||
use rustc_middle::ty::{
|
||||
self, fast_reject, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt,
|
||||
TypeFoldable, WithConstness,
|
||||
TypeFoldable,
|
||||
};
|
||||
use rustc_session::DiagnosticMessageId;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
|
|
|
@ -21,7 +21,7 @@ use rustc_hir::lang_items::LangItem;
|
|||
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
|
||||
use rustc_middle::ty::{
|
||||
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
|
||||
Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
|
||||
Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable,
|
||||
};
|
||||
use rustc_middle::ty::{TypeAndMut, TypeckResults};
|
||||
use rustc_session::Limit;
|
||||
|
|
|
@ -4,7 +4,6 @@ use rustc_data_structures::obligation_forest::ProcessResult;
|
|||
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
|
||||
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
|
||||
use rustc_errors::ErrorReported;
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
|
||||
|
@ -231,21 +230,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
|||
self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
|
||||
}
|
||||
|
||||
fn select_all_with_constness_or_error(
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
constness: rustc_hir::Constness,
|
||||
) -> Vec<FulfillmentError<'tcx>> {
|
||||
{
|
||||
let errors = self.select_with_constness_where_possible(infcx, constness);
|
||||
if !errors.is_empty() {
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
|
||||
}
|
||||
|
||||
fn select_where_possible(
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
|
@ -254,15 +238,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
|||
self.select(&mut selcx)
|
||||
}
|
||||
|
||||
fn select_with_constness_where_possible(
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
constness: hir::Constness,
|
||||
) -> Vec<FulfillmentError<'tcx>> {
|
||||
let mut selcx = SelectionContext::with_constness(infcx, constness);
|
||||
self.select(&mut selcx)
|
||||
}
|
||||
|
||||
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
|
||||
self.predicates.map_pending_obligations(|o| o.obligation.clone())
|
||||
}
|
||||
|
@ -679,12 +654,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
|||
if obligation.predicate.is_known_global() {
|
||||
// no type variables present, can use evaluation for better caching.
|
||||
// FIXME: consider caching errors too.
|
||||
//
|
||||
// If the predicate is considered const, then we cannot use this because
|
||||
// it will cause false negatives in the ui tests.
|
||||
if !self.selcx.is_predicate_const(obligation.predicate)
|
||||
&& infcx.predicate_must_hold_considering_regions(obligation)
|
||||
{
|
||||
if infcx.predicate_must_hold_considering_regions(obligation) {
|
||||
debug!(
|
||||
"selecting trait at depth {} evaluated to holds",
|
||||
obligation.recursion_depth
|
||||
|
@ -738,12 +708,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
|||
if obligation.predicate.is_global(tcx) {
|
||||
// no type variables present, can use evaluation for better caching.
|
||||
// FIXME: consider caching errors too.
|
||||
//
|
||||
// If the predicate is considered const, then we cannot use this because
|
||||
// it will cause false negatives in the ui tests.
|
||||
if !self.selcx.is_predicate_const(obligation.predicate)
|
||||
&& self.selcx.infcx().predicate_must_hold_considering_regions(obligation)
|
||||
{
|
||||
if self.selcx.infcx().predicate_must_hold_considering_regions(obligation) {
|
||||
return ProcessResult::Changed(vec![]);
|
||||
} else {
|
||||
tracing::debug!("Does NOT hold: {:?}", obligation);
|
||||
|
|
|
@ -33,8 +33,7 @@ use rustc_hir::lang_items::LangItem;
|
|||
use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
|
||||
use rustc_middle::ty::{
|
||||
self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness,
|
||||
COMMON_VTABLE_ENTRIES,
|
||||
self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, COMMON_VTABLE_ENTRIES,
|
||||
};
|
||||
use rustc_span::{sym, Span};
|
||||
use smallvec::SmallVec;
|
||||
|
@ -307,8 +306,11 @@ 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());
|
||||
let elaborated_env = ty::ParamEnv::new(
|
||||
tcx.intern_predicates(&predicates),
|
||||
unnormalized_env.reveal(),
|
||||
unnormalized_env.constness(),
|
||||
);
|
||||
|
||||
// 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,8 +362,11 @@ pub fn normalize_param_env_or_error<'tcx>(
|
|||
// predicates here anyway. Keeping them here anyway because it seems safer.
|
||||
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());
|
||||
let outlives_env = ty::ParamEnv::new(
|
||||
tcx.intern_predicates(&outlives_env),
|
||||
unnormalized_env.reveal(),
|
||||
unnormalized_env.constness(),
|
||||
);
|
||||
let outlives_predicates = match do_normalize_predicates(
|
||||
tcx,
|
||||
region_context,
|
||||
|
@ -381,7 +386,11 @@ 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())
|
||||
ty::ParamEnv::new(
|
||||
tcx.intern_predicates(&predicates),
|
||||
unnormalized_env.reveal(),
|
||||
unnormalized_env.constness(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn fully_normalize<'a, 'tcx, T>(
|
||||
|
@ -564,14 +573,17 @@ fn prepare_vtable_segments<'tcx, T>(
|
|||
.predicates
|
||||
.into_iter()
|
||||
.filter_map(move |(pred, _)| {
|
||||
pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_ref()
|
||||
pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_pred()
|
||||
});
|
||||
|
||||
'diving_in_skip_visited_traits: loop {
|
||||
if let Some(next_super_trait) = direct_super_traits_iter.next() {
|
||||
if visited.insert(next_super_trait.to_predicate(tcx)) {
|
||||
// We're throwing away potential constness of super traits here.
|
||||
// FIXME: handle ~const super traits
|
||||
let next_super_trait = next_super_trait.map_bound(|t| t.trait_ref);
|
||||
stack.push((
|
||||
next_super_trait.value,
|
||||
next_super_trait,
|
||||
emit_vptr_on_new_entry,
|
||||
Some(direct_super_traits_iter),
|
||||
));
|
||||
|
@ -603,7 +615,11 @@ fn prepare_vtable_segments<'tcx, T>(
|
|||
if let Some(siblings) = siblings_opt {
|
||||
if let Some(next_inner_most_trait_ref) = siblings.next() {
|
||||
if visited.insert(next_inner_most_trait_ref.to_predicate(tcx)) {
|
||||
*inner_most_trait_ref = next_inner_most_trait_ref.value;
|
||||
// We're throwing away potential constness of super traits here.
|
||||
// FIXME: handle ~const super traits
|
||||
let next_inner_most_trait_ref =
|
||||
next_inner_most_trait_ref.map_bound(|t| t.trait_ref);
|
||||
*inner_most_trait_ref = next_inner_most_trait_ref;
|
||||
*emit_vptr = emit_vptr_on_new_entry;
|
||||
break 'exiting_out;
|
||||
} else {
|
||||
|
|
|
@ -18,7 +18,7 @@ use rustc_errors::FatalError;
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, Subst};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor, WithConstness};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor};
|
||||
use rustc_middle::ty::{Predicate, ToPredicate};
|
||||
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
@ -694,7 +694,11 @@ fn receiver_is_dispatchable<'tcx>(
|
|||
let caller_bounds: Vec<Predicate<'tcx>> =
|
||||
param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]).collect();
|
||||
|
||||
ty::ParamEnv::new(tcx.intern_predicates(&caller_bounds), param_env.reveal())
|
||||
ty::ParamEnv::new(
|
||||
tcx.intern_predicates(&caller_bounds),
|
||||
param_env.reveal(),
|
||||
param_env.constness(),
|
||||
)
|
||||
};
|
||||
|
||||
// Receiver: DispatchFromDyn<Receiver[Self => U]>
|
||||
|
|
|
@ -28,7 +28,7 @@ use rustc_hir::lang_items::LangItem;
|
|||
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
|
||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
|
||||
use rustc_middle::ty::subst::Subst;
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use rustc_middle::ty;
|
||||
|
||||
use crate::infer::canonical::OriginalQueryValues;
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::traits::{
|
||||
|
@ -64,10 +66,21 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
|
|||
obligation: &PredicateObligation<'tcx>,
|
||||
) -> Result<EvaluationResult, OverflowError> {
|
||||
let mut _orig_values = OriginalQueryValues::default();
|
||||
let c_pred = self.canonicalize_query_keep_static(
|
||||
obligation.param_env.and(obligation.predicate),
|
||||
&mut _orig_values,
|
||||
);
|
||||
|
||||
let param_env = match obligation.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::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 c_pred = self
|
||||
.canonicalize_query_keep_static(param_env.and(obligation.predicate), &mut _orig_values);
|
||||
// Run canonical query. If overflow occurs, rerun from scratch but this time
|
||||
// in standard trait query mode so that overflow is handled appropriately
|
||||
// within `SelectionContext`.
|
||||
|
|
|
@ -30,8 +30,14 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
|
|||
|
||||
fn perform_query(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
|
||||
mut canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>,
|
||||
) -> Fallible<CanonicalizedQueryResponse<'tcx, ()>> {
|
||||
match canonicalized.value.value.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(pred) => {
|
||||
canonicalized.value.param_env.remap_constness_with(pred.constness);
|
||||
}
|
||||
_ => canonicalized.value.param_env = canonicalized.value.param_env.without_const(),
|
||||
}
|
||||
tcx.type_op_prove_predicate(canonicalized)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use rustc_infer::traits::TraitEngine;
|
|||
use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
|
||||
use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable, WithConstness};
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use crate::traits;
|
||||
|
@ -303,7 +303,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
} else if lang_items.drop_trait() == Some(def_id)
|
||||
&& obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst
|
||||
{
|
||||
if self.is_in_const_context {
|
||||
if obligation.param_env.constness() == hir::Constness::Const {
|
||||
self.assemble_const_drop_candidates(obligation, stack, &mut candidates)?;
|
||||
} else {
|
||||
debug!("passing ~const Drop bound; in non-const context");
|
||||
|
@ -381,17 +381,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
.param_env
|
||||
.caller_bounds()
|
||||
.iter()
|
||||
.filter_map(|o| o.to_opt_poly_trait_ref());
|
||||
.filter_map(|o| o.to_opt_poly_trait_pred());
|
||||
|
||||
// Micro-optimization: filter out predicates relating to different traits.
|
||||
let matching_bounds =
|
||||
all_bounds.filter(|p| p.value.def_id() == stack.obligation.predicate.def_id());
|
||||
all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id());
|
||||
|
||||
// Keep only those bounds which may apply, and propagate overflow if it occurs.
|
||||
for bound in matching_bounds {
|
||||
let wc = self.evaluate_where_clause(stack, bound.value)?;
|
||||
// FIXME(oli-obk): it is suspicious that we are dropping the constness and
|
||||
// polarity here.
|
||||
let wc = self.evaluate_where_clause(stack, bound.map_bound(|t| t.trait_ref))?;
|
||||
if wc.may_apply() {
|
||||
candidates.vec.push(ParamCandidate((bound, stack.obligation.polarity())));
|
||||
candidates.vec.push(ParamCandidate(bound));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use rustc_infer::infer::InferOk;
|
|||
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
|
||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_middle::ty::{ToPolyTraitRef, ToPredicate, WithConstness};
|
||||
use rustc_middle::ty::{ToPolyTraitRef, ToPredicate};
|
||||
use rustc_span::def_id::DefId;
|
||||
|
||||
use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
|
||||
|
@ -58,8 +58,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
ParamCandidate(param) => {
|
||||
let obligations = self.confirm_param_candidate(obligation, param.0.value);
|
||||
Ok(ImplSource::Param(obligations, param.0.constness))
|
||||
let obligations =
|
||||
self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref));
|
||||
Ok(ImplSource::Param(obligations, param.skip_binder().constness))
|
||||
}
|
||||
|
||||
ImplCandidate(impl_def_id) => {
|
||||
|
@ -139,7 +140,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
let trait_predicate = self.infcx.shallow_resolve(obligation.predicate);
|
||||
let placeholder_trait_predicate =
|
||||
self.infcx().replace_bound_vars_with_placeholders(trait_predicate);
|
||||
self.infcx().replace_bound_vars_with_placeholders(trait_predicate).trait_ref;
|
||||
let placeholder_self_ty = placeholder_trait_predicate.self_ty();
|
||||
let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
|
||||
let (def_id, substs) = match *placeholder_self_ty.kind() {
|
||||
|
@ -150,8 +151,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
let candidate_predicate = tcx.item_bounds(def_id)[idx].subst(tcx, substs);
|
||||
let candidate = candidate_predicate
|
||||
.to_opt_poly_trait_ref()
|
||||
.expect("projection candidate is not a trait predicate");
|
||||
.to_opt_poly_trait_pred()
|
||||
.expect("projection candidate is not a trait predicate")
|
||||
.map_bound(|t| t.trait_ref);
|
||||
let mut obligations = Vec::new();
|
||||
let candidate = normalize_with_depth_to(
|
||||
self,
|
||||
|
@ -165,7 +167,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
obligations.extend(self.infcx.commit_if_ok(|_| {
|
||||
self.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.sup(placeholder_trait_predicate.to_poly_trait_ref(), candidate.value)
|
||||
.sup(placeholder_trait_predicate, candidate)
|
||||
.map(|InferOk { obligations, .. }| obligations)
|
||||
.map_err(|_| Unimplemented)
|
||||
})?);
|
||||
|
|
|
@ -39,7 +39,6 @@ use rustc_middle::ty::fast_reject;
|
|||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::relate::TypeRelation;
|
||||
use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef};
|
||||
use rustc_middle::ty::WithConstness;
|
||||
use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
|
||||
use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_span::symbol::sym;
|
||||
|
@ -128,9 +127,6 @@ pub struct SelectionContext<'cx, 'tcx> {
|
|||
/// and a negative impl
|
||||
allow_negative_impls: bool,
|
||||
|
||||
/// Are we in a const context that needs `~const` bounds to be const?
|
||||
is_in_const_context: bool,
|
||||
|
||||
/// The mode that trait queries run in, which informs our error handling
|
||||
/// policy. In essence, canonicalized queries need their errors propagated
|
||||
/// rather than immediately reported because we do not have accurate spans.
|
||||
|
@ -141,9 +137,9 @@ pub struct SelectionContext<'cx, 'tcx> {
|
|||
struct TraitObligationStack<'prev, 'tcx> {
|
||||
obligation: &'prev TraitObligation<'tcx>,
|
||||
|
||||
/// The trait ref from `obligation` but "freshened" with the
|
||||
/// The trait predicate from `obligation` but "freshened" with the
|
||||
/// selection-context's freshener. Used to check for recursion.
|
||||
fresh_trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
|
||||
fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
|
||||
/// Starts out equal to `depth` -- if, during evaluation, we
|
||||
/// encounter a cycle, then we will set this flag to the minimum
|
||||
|
@ -222,7 +218,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
intercrate: false,
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls: false,
|
||||
is_in_const_context: false,
|
||||
query_mode: TraitQueryMode::Standard,
|
||||
}
|
||||
}
|
||||
|
@ -234,7 +229,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
intercrate: true,
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls: false,
|
||||
is_in_const_context: false,
|
||||
query_mode: TraitQueryMode::Standard,
|
||||
}
|
||||
}
|
||||
|
@ -250,7 +244,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
intercrate: false,
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls,
|
||||
is_in_const_context: false,
|
||||
query_mode: TraitQueryMode::Standard,
|
||||
}
|
||||
}
|
||||
|
@ -266,26 +259,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
intercrate: false,
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls: false,
|
||||
is_in_const_context: false,
|
||||
query_mode,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_constness(
|
||||
infcx: &'cx InferCtxt<'cx, 'tcx>,
|
||||
constness: hir::Constness,
|
||||
) -> SelectionContext<'cx, 'tcx> {
|
||||
SelectionContext {
|
||||
infcx,
|
||||
freshener: infcx.freshener_keep_static(),
|
||||
intercrate: false,
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls: false,
|
||||
is_in_const_context: matches!(constness, hir::Constness::Const),
|
||||
query_mode: TraitQueryMode::Standard,
|
||||
}
|
||||
}
|
||||
|
||||
/// Enables tracking of intercrate ambiguity causes. These are
|
||||
/// used in coherence to give improved diagnostics. We don't do
|
||||
/// this until we detect a coherence error because it can lead to
|
||||
|
@ -318,20 +295,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
self.intercrate
|
||||
}
|
||||
|
||||
/// Returns `true` if the trait predicate is considerd `const` to this selection context.
|
||||
pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool {
|
||||
matches!(pred.constness, ty::BoundConstness::ConstIfConst) && self.is_in_const_context
|
||||
}
|
||||
|
||||
/// Returns `true` if the predicate is considered `const` to
|
||||
/// this selection context.
|
||||
pub fn is_predicate_const(&self, pred: ty::Predicate<'_>) -> bool {
|
||||
match pred.kind().skip_binder() {
|
||||
ty::PredicateKind::Trait(pred) => self.is_trait_predicate_const(pred),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Selection
|
||||
//
|
||||
|
@ -716,20 +679,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
let stack = self.push_stack(previous_stack, &obligation);
|
||||
let fresh_trait_ref = stack.fresh_trait_ref;
|
||||
let mut fresh_trait_pred = stack.fresh_trait_pred;
|
||||
let mut param_env = obligation.param_env;
|
||||
|
||||
debug!(?fresh_trait_ref);
|
||||
fresh_trait_pred = fresh_trait_pred.map_bound(|mut pred| {
|
||||
param_env = param_env.with_constness(pred.constness.and(param_env.constness()));
|
||||
pred
|
||||
});
|
||||
|
||||
if let Some(result) = self.check_evaluation_cache(
|
||||
obligation.param_env,
|
||||
fresh_trait_ref,
|
||||
obligation.polarity(),
|
||||
) {
|
||||
debug!(?fresh_trait_pred);
|
||||
|
||||
if let Some(result) = self.check_evaluation_cache(param_env, fresh_trait_pred) {
|
||||
debug!(?result, "CACHE HIT");
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
if let Some(result) = stack.cache().get_provisional(fresh_trait_ref) {
|
||||
if let Some(result) = stack.cache().get_provisional(fresh_trait_pred) {
|
||||
debug!(?result, "PROVISIONAL CACHE HIT");
|
||||
stack.update_reached_depth(result.reached_depth);
|
||||
return Ok(result.result);
|
||||
|
@ -754,19 +719,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
let reached_depth = stack.reached_depth.get();
|
||||
if reached_depth >= stack.depth {
|
||||
debug!(?result, "CACHE MISS");
|
||||
self.insert_evaluation_cache(
|
||||
obligation.param_env,
|
||||
fresh_trait_ref,
|
||||
obligation.polarity(),
|
||||
dep_node,
|
||||
result,
|
||||
);
|
||||
self.insert_evaluation_cache(param_env, fresh_trait_pred, dep_node, result);
|
||||
|
||||
stack.cache().on_completion(stack.dfn, |fresh_trait_ref, provisional_result| {
|
||||
stack.cache().on_completion(stack.dfn, |fresh_trait_pred, provisional_result| {
|
||||
self.insert_evaluation_cache(
|
||||
obligation.param_env,
|
||||
fresh_trait_ref,
|
||||
obligation.polarity(),
|
||||
param_env,
|
||||
fresh_trait_pred,
|
||||
dep_node,
|
||||
provisional_result.max(result),
|
||||
);
|
||||
|
@ -776,10 +734,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
debug!(
|
||||
"caching provisionally because {:?} \
|
||||
is a cycle participant (at depth {}, reached depth {})",
|
||||
fresh_trait_ref, stack.depth, reached_depth,
|
||||
fresh_trait_pred, stack.depth, reached_depth,
|
||||
);
|
||||
|
||||
stack.cache().insert_provisional(stack.dfn, reached_depth, fresh_trait_ref, result);
|
||||
stack.cache().insert_provisional(stack.dfn, reached_depth, fresh_trait_pred, result);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
|
@ -813,7 +771,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
.skip(1) // Skip top-most frame.
|
||||
.find(|prev| {
|
||||
stack.obligation.param_env == prev.obligation.param_env
|
||||
&& stack.fresh_trait_ref == prev.fresh_trait_ref
|
||||
&& stack.fresh_trait_pred == prev.fresh_trait_pred
|
||||
})
|
||||
.map(|stack| stack.depth)
|
||||
{
|
||||
|
@ -876,7 +834,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
// terms of `Fn` etc, but we could probably make this more
|
||||
// precise still.
|
||||
let unbound_input_types =
|
||||
stack.fresh_trait_ref.value.skip_binder().substs.types().any(|ty| ty.is_fresh());
|
||||
stack.fresh_trait_pred.skip_binder().trait_ref.substs.types().any(|ty| ty.is_fresh());
|
||||
|
||||
if stack.obligation.polarity() != ty::ImplPolarity::Negative {
|
||||
// This check was an imperfect workaround for a bug in the old
|
||||
|
@ -914,8 +872,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
&& stack.iter().skip(1).any(|prev| {
|
||||
stack.obligation.param_env == prev.obligation.param_env
|
||||
&& self.match_fresh_trait_refs(
|
||||
stack.fresh_trait_ref,
|
||||
prev.fresh_trait_ref,
|
||||
stack.fresh_trait_pred,
|
||||
prev.fresh_trait_pred,
|
||||
prev.obligation.param_env,
|
||||
)
|
||||
})
|
||||
|
@ -993,7 +951,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
// not just the lifetime choice for this particular (non-erased)
|
||||
// predicate.
|
||||
// See issue #80691
|
||||
if stack.fresh_trait_ref.has_erased_regions() {
|
||||
if stack.fresh_trait_pred.has_erased_regions() {
|
||||
result = result.max(EvaluatedToOkModuloRegions);
|
||||
}
|
||||
|
||||
|
@ -1004,8 +962,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
fn check_evaluation_cache(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
|
||||
polarity: ty::ImplPolarity,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) -> Option<EvaluationResult> {
|
||||
// Neither the global nor local cache is aware of intercrate
|
||||
// mode, so don't do any caching. In particular, we might
|
||||
|
@ -1017,19 +974,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
let tcx = self.tcx();
|
||||
if self.can_use_global_caches(param_env) {
|
||||
if let Some(res) = tcx.evaluation_cache.get(&(param_env.and(trait_ref), polarity), tcx)
|
||||
{
|
||||
if let Some(res) = tcx.evaluation_cache.get(¶m_env.and(trait_pred), tcx) {
|
||||
return Some(res);
|
||||
}
|
||||
}
|
||||
self.infcx.evaluation_cache.get(&(param_env.and(trait_ref), polarity), tcx)
|
||||
self.infcx.evaluation_cache.get(¶m_env.and(trait_pred), tcx)
|
||||
}
|
||||
|
||||
fn insert_evaluation_cache(
|
||||
&mut self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
|
||||
polarity: ty::ImplPolarity,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
dep_node: DepNodeIndex,
|
||||
result: EvaluationResult,
|
||||
) {
|
||||
|
@ -1048,23 +1003,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
if self.can_use_global_caches(param_env) {
|
||||
if !trait_ref.needs_infer() {
|
||||
debug!(?trait_ref, ?result, "insert_evaluation_cache global");
|
||||
if !trait_pred.needs_infer() {
|
||||
debug!(?trait_pred, ?result, "insert_evaluation_cache global");
|
||||
// This may overwrite the cache with the same value
|
||||
// FIXME: Due to #50507 this overwrites the different values
|
||||
// This should be changed to use HashMapExt::insert_same
|
||||
// when that is fixed
|
||||
self.tcx().evaluation_cache.insert(
|
||||
(param_env.and(trait_ref), polarity),
|
||||
dep_node,
|
||||
result,
|
||||
);
|
||||
self.tcx().evaluation_cache.insert(param_env.and(trait_pred), dep_node, result);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
debug!(?trait_ref, ?result, "insert_evaluation_cache");
|
||||
self.infcx.evaluation_cache.insert((param_env.and(trait_ref), polarity), dep_node, result);
|
||||
debug!(?trait_pred, ?result, "insert_evaluation_cache");
|
||||
self.infcx.evaluation_cache.insert(param_env.and(trait_pred), dep_node, result);
|
||||
}
|
||||
|
||||
/// For various reasons, it's possible for a subobligation
|
||||
|
@ -1142,16 +1093,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
for candidate in candidates {
|
||||
// Respect const trait obligations
|
||||
if self.is_trait_predicate_const(obligation.predicate.skip_binder()) {
|
||||
if obligation.is_const() {
|
||||
match candidate {
|
||||
// const impl
|
||||
ImplCandidate(def_id)
|
||||
if tcx.impl_constness(def_id) == hir::Constness::Const => {}
|
||||
// const param
|
||||
ParamCandidate((
|
||||
ty::ConstnessAnd { constness: ty::BoundConstness::ConstIfConst, .. },
|
||||
_,
|
||||
)) => {}
|
||||
ParamCandidate(trait_pred)
|
||||
if trait_pred.skip_binder().constness
|
||||
== ty::BoundConstness::ConstIfConst => {}
|
||||
// auto trait impl
|
||||
AutoImplCandidate(..) => {}
|
||||
// generator, this will raise error in other places
|
||||
|
@ -1260,7 +1210,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
fn check_candidate_cache(
|
||||
&mut self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
mut 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
|
||||
|
@ -1271,19 +1221,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
return None;
|
||||
}
|
||||
let tcx = self.tcx();
|
||||
let pred = &cache_fresh_trait_pred.skip_binder();
|
||||
let trait_ref = pred.trait_ref;
|
||||
let mut pred = cache_fresh_trait_pred.skip_binder();
|
||||
param_env = param_env.with_constness(pred.constness.and(param_env.constness()));
|
||||
|
||||
if self.can_use_global_caches(param_env) {
|
||||
if let Some(res) = tcx
|
||||
.selection_cache
|
||||
.get(&(param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), tcx)
|
||||
{
|
||||
if let Some(res) = tcx.selection_cache.get(¶m_env.and(pred), tcx) {
|
||||
return Some(res);
|
||||
}
|
||||
}
|
||||
self.infcx
|
||||
.selection_cache
|
||||
.get(&(param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), tcx)
|
||||
self.infcx.selection_cache.get(¶m_env.and(pred), tcx)
|
||||
}
|
||||
|
||||
/// Determines whether can we safely cache the result
|
||||
|
@ -1321,43 +1267,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
fn insert_candidate_cache(
|
||||
&mut self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
mut 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 pred = cache_fresh_trait_pred.skip_binder();
|
||||
let trait_ref = pred.trait_ref;
|
||||
let mut pred = cache_fresh_trait_pred.skip_binder();
|
||||
|
||||
param_env = param_env.with_constness(pred.constness.and(param_env.constness()));
|
||||
|
||||
if !self.can_cache_candidate(&candidate) {
|
||||
debug!(?trait_ref, ?candidate, "insert_candidate_cache - candidate is not cacheable");
|
||||
debug!(?pred, ?candidate, "insert_candidate_cache - candidate is not cacheable");
|
||||
return;
|
||||
}
|
||||
|
||||
if self.can_use_global_caches(param_env) {
|
||||
if let Err(Overflow) = candidate {
|
||||
// Don't cache overflow globally; we only produce this in certain modes.
|
||||
} else if !trait_ref.needs_infer() {
|
||||
} else if !pred.needs_infer() {
|
||||
if !candidate.needs_infer() {
|
||||
debug!(?trait_ref, ?candidate, "insert_candidate_cache global");
|
||||
debug!(?pred, ?candidate, "insert_candidate_cache global");
|
||||
// This may overwrite the cache with the same value.
|
||||
tcx.selection_cache.insert(
|
||||
(param_env.and(trait_ref).with_constness(pred.constness), pred.polarity),
|
||||
dep_node,
|
||||
candidate,
|
||||
);
|
||||
tcx.selection_cache.insert(param_env.and(pred), dep_node, candidate);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug!(?trait_ref, ?candidate, "insert_candidate_cache local");
|
||||
self.infcx.selection_cache.insert(
|
||||
(param_env.and(trait_ref).with_constness(pred.constness), pred.polarity),
|
||||
dep_node,
|
||||
candidate,
|
||||
);
|
||||
debug!(?pred, ?candidate, "insert_candidate_cache local");
|
||||
self.infcx.selection_cache.insert(param_env.and(pred), dep_node, candidate);
|
||||
}
|
||||
|
||||
/// Matches a predicate against the bounds of its self type.
|
||||
|
@ -1548,7 +1487,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
// Check if a bound would previously have been removed when normalizing
|
||||
// the param_env so that it can be given the lowest priority. See
|
||||
// #50825 for the motivation for this.
|
||||
let is_global = |cand: &ty::PolyTraitRef<'tcx>| {
|
||||
let is_global = |cand: &ty::PolyTraitPredicate<'tcx>| {
|
||||
cand.is_global(self.infcx.tcx) && !cand.has_late_bound_regions()
|
||||
};
|
||||
|
||||
|
@ -1581,25 +1520,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
| ConstDropCandidate,
|
||||
) => false,
|
||||
|
||||
(
|
||||
ParamCandidate((other, other_polarity)),
|
||||
ParamCandidate((victim, victim_polarity)),
|
||||
) => {
|
||||
let same_except_bound_vars = other.value.skip_binder()
|
||||
== victim.value.skip_binder()
|
||||
&& other.constness == victim.constness
|
||||
&& other_polarity == victim_polarity
|
||||
&& !other.value.skip_binder().has_escaping_bound_vars();
|
||||
(ParamCandidate(other), ParamCandidate(victim)) => {
|
||||
let same_except_bound_vars = other.skip_binder().trait_ref
|
||||
== victim.skip_binder().trait_ref
|
||||
&& other.skip_binder().constness == victim.skip_binder().constness
|
||||
&& other.skip_binder().polarity == victim.skip_binder().polarity
|
||||
&& !other.skip_binder().trait_ref.has_escaping_bound_vars();
|
||||
if same_except_bound_vars {
|
||||
// See issue #84398. In short, we can generate multiple ParamCandidates which are
|
||||
// the same except for unused bound vars. Just pick the one with the fewest bound vars
|
||||
// or the current one if tied (they should both evaluate to the same answer). This is
|
||||
// probably best characterized as a "hack", since we might prefer to just do our
|
||||
// best to *not* create essentially duplicate candidates in the first place.
|
||||
other.value.bound_vars().len() <= victim.value.bound_vars().len()
|
||||
} else if other.value == victim.value
|
||||
&& victim.constness == ty::BoundConstness::NotConst
|
||||
&& other_polarity == victim_polarity
|
||||
other.bound_vars().len() <= victim.bound_vars().len()
|
||||
} else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref
|
||||
&& victim.skip_binder().constness == ty::BoundConstness::NotConst
|
||||
&& other.skip_binder().polarity == victim.skip_binder().polarity
|
||||
{
|
||||
// Drop otherwise equivalent non-const candidates in favor of const candidates.
|
||||
true
|
||||
|
@ -1629,11 +1565,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
| TraitAliasCandidate(..)
|
||||
| ObjectCandidate(_)
|
||||
| ProjectionCandidate(_),
|
||||
) => !is_global(&cand.0.value),
|
||||
) => !is_global(cand),
|
||||
(ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => {
|
||||
// Prefer these to a global where-clause bound
|
||||
// (see issue #50825).
|
||||
is_global(&cand.0.value)
|
||||
is_global(cand)
|
||||
}
|
||||
(
|
||||
ImplCandidate(_)
|
||||
|
@ -1649,7 +1585,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
) => {
|
||||
// Prefer these to a global where-clause bound
|
||||
// (see issue #50825).
|
||||
is_global(&cand.0.value) && other.evaluation.must_apply_modulo_regions()
|
||||
is_global(cand) && other.evaluation.must_apply_modulo_regions()
|
||||
}
|
||||
|
||||
(ProjectionCandidate(i), ProjectionCandidate(j))
|
||||
|
@ -2209,8 +2145,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
fn match_fresh_trait_refs(
|
||||
&self,
|
||||
previous: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
|
||||
current: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
|
||||
previous: ty::PolyTraitPredicate<'tcx>,
|
||||
current: ty::PolyTraitPredicate<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> bool {
|
||||
let mut matcher = ty::_match::Match::new(self.tcx(), param_env);
|
||||
|
@ -2222,17 +2158,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
previous_stack: TraitObligationStackList<'o, 'tcx>,
|
||||
obligation: &'o TraitObligation<'tcx>,
|
||||
) -> TraitObligationStack<'o, 'tcx> {
|
||||
let fresh_trait_ref = obligation
|
||||
.predicate
|
||||
.to_poly_trait_ref()
|
||||
.fold_with(&mut self.freshener)
|
||||
.with_constness(obligation.predicate.skip_binder().constness);
|
||||
let fresh_trait_pred = obligation.predicate.fold_with(&mut self.freshener);
|
||||
|
||||
let dfn = previous_stack.cache.next_dfn();
|
||||
let depth = previous_stack.depth() + 1;
|
||||
TraitObligationStack {
|
||||
obligation,
|
||||
fresh_trait_ref,
|
||||
fresh_trait_pred,
|
||||
reached_depth: Cell::new(depth),
|
||||
previous: previous_stack,
|
||||
dfn,
|
||||
|
@ -2426,7 +2358,7 @@ impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> {
|
|||
debug!(reached_depth, "update_reached_depth");
|
||||
let mut p = self;
|
||||
while reached_depth < p.depth {
|
||||
debug!(?p.fresh_trait_ref, "update_reached_depth: marking as cycle participant");
|
||||
debug!(?p.fresh_trait_pred, "update_reached_depth: marking as cycle participant");
|
||||
p.reached_depth.set(p.reached_depth.get().min(reached_depth));
|
||||
p = p.previous.head.unwrap();
|
||||
}
|
||||
|
@ -2505,7 +2437,7 @@ struct ProvisionalEvaluationCache<'tcx> {
|
|||
/// - then we determine that `E` is in error -- we will then clear
|
||||
/// all cache values whose DFN is >= 4 -- in this case, that
|
||||
/// means the cached value for `F`.
|
||||
map: RefCell<FxHashMap<ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, ProvisionalEvaluation>>,
|
||||
map: RefCell<FxHashMap<ty::PolyTraitPredicate<'tcx>, ProvisionalEvaluation>>,
|
||||
}
|
||||
|
||||
/// A cache value for the provisional cache: contains the depth-first
|
||||
|
@ -2537,28 +2469,28 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
|
|||
/// `reached_depth` (from the returned value).
|
||||
fn get_provisional(
|
||||
&self,
|
||||
fresh_trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
|
||||
fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) -> Option<ProvisionalEvaluation> {
|
||||
debug!(
|
||||
?fresh_trait_ref,
|
||||
?fresh_trait_pred,
|
||||
"get_provisional = {:#?}",
|
||||
self.map.borrow().get(&fresh_trait_ref),
|
||||
self.map.borrow().get(&fresh_trait_pred),
|
||||
);
|
||||
Some(*self.map.borrow().get(&fresh_trait_ref)?)
|
||||
Some(*self.map.borrow().get(&fresh_trait_pred)?)
|
||||
}
|
||||
|
||||
/// Insert a provisional result into the cache. The result came
|
||||
/// from the node with the given DFN. It accessed a minimum depth
|
||||
/// of `reached_depth` to compute. It evaluated `fresh_trait_ref`
|
||||
/// of `reached_depth` to compute. It evaluated `fresh_trait_pred`
|
||||
/// and resulted in `result`.
|
||||
fn insert_provisional(
|
||||
&self,
|
||||
from_dfn: usize,
|
||||
reached_depth: usize,
|
||||
fresh_trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
|
||||
fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
result: EvaluationResult,
|
||||
) {
|
||||
debug!(?from_dfn, ?fresh_trait_ref, ?result, "insert_provisional");
|
||||
debug!(?from_dfn, ?fresh_trait_pred, ?result, "insert_provisional");
|
||||
|
||||
let mut map = self.map.borrow_mut();
|
||||
|
||||
|
@ -2582,7 +2514,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
map.insert(fresh_trait_ref, ProvisionalEvaluation { from_dfn, reached_depth, result });
|
||||
map.insert(fresh_trait_pred, ProvisionalEvaluation { from_dfn, reached_depth, result });
|
||||
}
|
||||
|
||||
/// Invoked when the node with dfn `dfn` does not get a successful
|
||||
|
@ -2633,16 +2565,16 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
|
|||
fn on_completion(
|
||||
&self,
|
||||
dfn: usize,
|
||||
mut op: impl FnMut(ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, EvaluationResult),
|
||||
mut op: impl FnMut(ty::PolyTraitPredicate<'tcx>, EvaluationResult),
|
||||
) {
|
||||
debug!(?dfn, "on_completion");
|
||||
|
||||
for (fresh_trait_ref, eval) in
|
||||
for (fresh_trait_pred, eval) in
|
||||
self.map.borrow_mut().drain_filter(|_k, eval| eval.from_dfn >= dfn)
|
||||
{
|
||||
debug!(?fresh_trait_ref, ?eval, "on_completion");
|
||||
debug!(?fresh_trait_pred, ?eval, "on_completion");
|
||||
|
||||
op(fresh_trait_ref, eval.result);
|
||||
op(fresh_trait_pred, eval.result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -508,9 +508,9 @@ crate fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<St
|
|||
Vec::with_capacity(predicates.len() + types_without_default_bounds.len());
|
||||
|
||||
for (p, _) in predicates {
|
||||
if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() {
|
||||
if Some(poly_trait_ref.value.def_id()) == sized_trait {
|
||||
types_without_default_bounds.remove(poly_trait_ref.value.self_ty().skip_binder());
|
||||
if let Some(poly_trait_ref) = p.to_opt_poly_trait_pred() {
|
||||
if Some(poly_trait_ref.def_id()) == sized_trait {
|
||||
types_without_default_bounds.remove(poly_trait_ref.self_ty().skip_binder());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use smallvec::SmallVec;
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
|
||||
|
||||
use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
|
||||
pub use rustc_infer::traits::{self, util::*};
|
||||
|
@ -126,8 +126,8 @@ impl<'tcx> TraitAliasExpander<'tcx> {
|
|||
|
||||
let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
|
||||
pred.subst_supertrait(tcx, &trait_ref)
|
||||
.to_opt_poly_trait_ref()
|
||||
.map(|trait_ref| item.clone_and_push(trait_ref.value, *span))
|
||||
.to_opt_poly_trait_pred()
|
||||
.map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span))
|
||||
});
|
||||
debug!("expand_trait_aliases: items={:?}", items.clone());
|
||||
|
||||
|
@ -183,8 +183,8 @@ impl Iterator for SupertraitDefIds<'tcx> {
|
|||
predicates
|
||||
.predicates
|
||||
.iter()
|
||||
.filter_map(|(pred, _)| pred.to_opt_poly_trait_ref())
|
||||
.map(|trait_ref| trait_ref.value.def_id())
|
||||
.filter_map(|(pred, _)| pred.to_opt_poly_trait_pred())
|
||||
.map(|trait_ref| trait_ref.def_id())
|
||||
.filter(|&super_def_id| visited.insert(super_def_id)),
|
||||
);
|
||||
Some(def_id)
|
||||
|
|
|
@ -6,7 +6,7 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::iter;
|
||||
|
@ -298,9 +298,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
|
||||
let extend = |obligation: traits::PredicateObligation<'tcx>| {
|
||||
let mut cause = cause.clone();
|
||||
if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() {
|
||||
if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_pred() {
|
||||
let derived_cause = traits::DerivedObligationCause {
|
||||
parent_trait_ref: parent_trait_ref.value,
|
||||
// FIXME(fee1-dead): when improving error messages, change this to PolyTraitPredicate
|
||||
parent_trait_ref: parent_trait_ref.map_bound(|t| t.trait_ref),
|
||||
parent_code: Lrc::new(obligation.cause.code.clone()),
|
||||
};
|
||||
cause.make_mut().code =
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue