Rollup merge of #140641 - lcnr:opaque-type-storage-entries, r=compiler-errors
detect additional uses of opaques after writeback Based on #140607. It's a lot harder to encounter in practice than I though 😅 😁 I've still added it with the expectation that somebody will encounter it at some point. Also modifies the `EvalCtxt` to use the same impl to detect newly added opaque types. r? ``@compiler-errors``
This commit is contained in:
@@ -250,13 +250,7 @@ where
|
||||
// to the `var_values`.
|
||||
let opaque_types = self
|
||||
.delegate
|
||||
.clone_opaque_types_lookup_table()
|
||||
.into_iter()
|
||||
.filter(|(a, _)| {
|
||||
self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
|
||||
})
|
||||
.chain(self.delegate.clone_duplicate_opaque_types())
|
||||
.collect();
|
||||
.clone_opaque_types_added_since(self.initial_opaque_types_storage_num_entries);
|
||||
|
||||
ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals }
|
||||
}
|
||||
|
||||
@@ -23,8 +23,7 @@ use crate::solve::inspect::{self, ProofTreeBuilder};
|
||||
use crate::solve::search_graph::SearchGraph;
|
||||
use crate::solve::{
|
||||
CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource,
|
||||
HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryInput,
|
||||
QueryResult,
|
||||
HasChanged, NestedNormalizationGoals, NoSolution, QueryInput, QueryResult,
|
||||
};
|
||||
|
||||
pub(super) mod canonical;
|
||||
@@ -99,8 +98,6 @@ where
|
||||
current_goal_kind: CurrentGoalKind,
|
||||
pub(super) var_values: CanonicalVarValues<I>,
|
||||
|
||||
predefined_opaques_in_body: I::PredefinedOpaques,
|
||||
|
||||
/// The highest universe index nameable by the caller.
|
||||
///
|
||||
/// When we enter a new binder inside of the query we create new universes
|
||||
@@ -111,6 +108,10 @@ where
|
||||
/// if we have a coinductive cycle and because that's the only way we can return
|
||||
/// new placeholders to the caller.
|
||||
pub(super) max_input_universe: ty::UniverseIndex,
|
||||
/// The opaque types from the canonical input. We only need to return opaque types
|
||||
/// which have been added to the storage while evaluating this goal.
|
||||
pub(super) initial_opaque_types_storage_num_entries:
|
||||
<D::Infcx as InferCtxtLike>::OpaqueTypeStorageEntries,
|
||||
|
||||
pub(super) search_graph: &'a mut SearchGraph<D>,
|
||||
|
||||
@@ -305,10 +306,8 @@ where
|
||||
|
||||
// Only relevant when canonicalizing the response,
|
||||
// which we don't do within this evaluation context.
|
||||
predefined_opaques_in_body: delegate
|
||||
.cx()
|
||||
.mk_predefined_opaques_in_body(PredefinedOpaquesData::default()),
|
||||
max_input_universe: ty::UniverseIndex::ROOT,
|
||||
initial_opaque_types_storage_num_entries: Default::default(),
|
||||
variables: Default::default(),
|
||||
var_values: CanonicalVarValues::dummy(),
|
||||
current_goal_kind: CurrentGoalKind::Misc,
|
||||
@@ -342,25 +341,10 @@ where
|
||||
canonical_goal_evaluation: &mut ProofTreeBuilder<D>,
|
||||
f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R,
|
||||
) -> R {
|
||||
let (ref delegate, input, var_values) =
|
||||
SolverDelegate::build_with_canonical(cx, &canonical_input);
|
||||
|
||||
let mut ecx = EvalCtxt {
|
||||
delegate,
|
||||
variables: canonical_input.canonical.variables,
|
||||
var_values,
|
||||
current_goal_kind: CurrentGoalKind::from_query_input(cx, input),
|
||||
predefined_opaques_in_body: input.predefined_opaques_in_body,
|
||||
max_input_universe: canonical_input.canonical.max_universe,
|
||||
search_graph,
|
||||
nested_goals: Default::default(),
|
||||
origin_span: I::Span::dummy(),
|
||||
tainted: Ok(()),
|
||||
inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values),
|
||||
};
|
||||
let (ref delegate, input, var_values) = D::build_with_canonical(cx, &canonical_input);
|
||||
|
||||
for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
|
||||
let prev = ecx.delegate.register_hidden_type_in_storage(key, ty, ecx.origin_span);
|
||||
let prev = delegate.register_hidden_type_in_storage(key, ty, I::Span::dummy());
|
||||
// It may be possible that two entries in the opaque type storage end up
|
||||
// with the same key after resolving contained inference variables.
|
||||
//
|
||||
@@ -373,13 +357,24 @@ where
|
||||
// the canonical input. This is more annoying to implement and may cause a
|
||||
// perf regression, so we do it inside of the query for now.
|
||||
if let Some(prev) = prev {
|
||||
debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_type_storage`");
|
||||
debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_types_storage`");
|
||||
}
|
||||
}
|
||||
|
||||
if !ecx.nested_goals.is_empty() {
|
||||
panic!("prepopulating opaque types shouldn't add goals: {:?}", ecx.nested_goals);
|
||||
}
|
||||
let initial_opaque_types_storage_num_entries = delegate.opaque_types_storage_num_entries();
|
||||
let mut ecx = EvalCtxt {
|
||||
delegate,
|
||||
variables: canonical_input.canonical.variables,
|
||||
var_values,
|
||||
current_goal_kind: CurrentGoalKind::from_query_input(cx, input),
|
||||
max_input_universe: canonical_input.canonical.max_universe,
|
||||
initial_opaque_types_storage_num_entries,
|
||||
search_graph,
|
||||
nested_goals: Default::default(),
|
||||
origin_span: I::Span::dummy(),
|
||||
tainted: Ok(()),
|
||||
inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values),
|
||||
};
|
||||
|
||||
let result = f(&mut ecx, input.goal);
|
||||
ecx.inspect.probe_final_state(ecx.delegate, ecx.max_input_universe);
|
||||
|
||||
@@ -26,32 +26,33 @@ where
|
||||
I: Interner,
|
||||
{
|
||||
pub(in crate::solve) fn enter(self, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> T) -> T {
|
||||
let ProbeCtxt { ecx: outer_ecx, probe_kind, _result } = self;
|
||||
let ProbeCtxt { ecx: outer, probe_kind, _result } = self;
|
||||
|
||||
let delegate = outer_ecx.delegate;
|
||||
let max_input_universe = outer_ecx.max_input_universe;
|
||||
let mut nested_ecx = EvalCtxt {
|
||||
let delegate = outer.delegate;
|
||||
let max_input_universe = outer.max_input_universe;
|
||||
let mut nested = EvalCtxt {
|
||||
delegate,
|
||||
variables: outer_ecx.variables,
|
||||
var_values: outer_ecx.var_values,
|
||||
current_goal_kind: outer_ecx.current_goal_kind,
|
||||
predefined_opaques_in_body: outer_ecx.predefined_opaques_in_body,
|
||||
variables: outer.variables,
|
||||
var_values: outer.var_values,
|
||||
current_goal_kind: outer.current_goal_kind,
|
||||
max_input_universe,
|
||||
search_graph: outer_ecx.search_graph,
|
||||
nested_goals: outer_ecx.nested_goals.clone(),
|
||||
origin_span: outer_ecx.origin_span,
|
||||
tainted: outer_ecx.tainted,
|
||||
inspect: outer_ecx.inspect.take_and_enter_probe(),
|
||||
initial_opaque_types_storage_num_entries: outer
|
||||
.initial_opaque_types_storage_num_entries,
|
||||
search_graph: outer.search_graph,
|
||||
nested_goals: outer.nested_goals.clone(),
|
||||
origin_span: outer.origin_span,
|
||||
tainted: outer.tainted,
|
||||
inspect: outer.inspect.take_and_enter_probe(),
|
||||
};
|
||||
let r = nested_ecx.delegate.probe(|| {
|
||||
let r = f(&mut nested_ecx);
|
||||
nested_ecx.inspect.probe_final_state(delegate, max_input_universe);
|
||||
let r = nested.delegate.probe(|| {
|
||||
let r = f(&mut nested);
|
||||
nested.inspect.probe_final_state(delegate, max_input_universe);
|
||||
r
|
||||
});
|
||||
if !nested_ecx.inspect.is_noop() {
|
||||
if !nested.inspect.is_noop() {
|
||||
let probe_kind = probe_kind(&r);
|
||||
nested_ecx.inspect.probe_kind(probe_kind);
|
||||
outer_ecx.inspect = nested_ecx.inspect.finish_probe();
|
||||
nested.inspect.probe_kind(probe_kind);
|
||||
outer.inspect = nested.inspect.finish_probe();
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user