Skip to content

Commit a2c8b0b

Browse files
committed
Auto merge of #145951 - lcnr:proof-tree-as-query, r=compiler-errors
cleanup and cache proof tree building There's some cruft left over from when we had deep proof trees. We never encounter overflow when evaluating proof trees. Even if the recursion limit is `0`, we still only hit the overflow limit when evaluating nested goals of the root. The root goal simply inherits the `root_depth` of the `SearchGraph`. Split `evaluate_root_goal_for_proof_tree` from the rest of the trait solver. This enables us to simplify the implementation of `evaluate_goal_raw` and the `ProofTreeBuilder` as we no longer need to manually track the state of the builder and can instead use separate types for that. It does require making a few internal methods into associated functions taking a `delegate` and a `span` instead of the `EvalCtxt` itself. I've also split `SearchGraph::evaluate_goal` and `SearchGraph::evaluate_root_goal_for_proof_tree` for the same reason. Both functions don't actually share too much code, so by splitting them each version gets significantly easier to read. Add a `query evaluate_root_goal_for_proof_tree_raw` to cache proof tree building. This requires arena allocating `inspect::Probe`. I've added a new type alias `I::ProbeRef` for this. We may need to adapt this for rust-analyzer? It would definitely be easy to remove the `Copy` bound here 🤔
2 parents f6df223 + 0edb22c commit a2c8b0b

File tree

15 files changed

+331
-441
lines changed

15 files changed

+331
-441
lines changed

compiler/rustc_interface/src/passes.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use rustc_span::{
4141
Symbol, sym,
4242
};
4343
use rustc_target::spec::PanicStrategy;
44-
use rustc_trait_selection::traits;
44+
use rustc_trait_selection::{solve, traits};
4545
use tracing::{info, instrument};
4646

4747
use crate::interface::Compiler;
@@ -895,6 +895,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
895895
rustc_hir_typeck::provide(providers);
896896
ty::provide(providers);
897897
traits::provide(providers);
898+
solve::provide(providers);
898899
rustc_passes::provide(providers);
899900
rustc_traits::provide(providers);
900901
rustc_ty_utils::provide(providers);

compiler/rustc_middle/src/arena.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ macro_rules! arena_types {
8080
rustc_middle::infer::canonical::Canonical<'tcx,
8181
rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>>
8282
>,
83+
[] inspect_probe: rustc_middle::traits::solve::inspect::Probe<rustc_middle::ty::TyCtxt<'tcx>>,
8384
[] effective_visibilities: rustc_middle::middle::privacy::EffectiveVisibilities,
8485
[] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
8586
[] dyn_compatibility_violations: rustc_middle::traits::DynCompatibilityViolation,

compiler/rustc_middle/src/query/erase.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_span::ErrorGuaranteed;
66

77
use crate::mir::interpret::EvalToValTreeResult;
88
use crate::query::CyclePlaceholder;
9+
use crate::traits::solve;
910
use crate::ty::adjustment::CoerceUnsizedInfo;
1011
use crate::ty::{self, Ty, TyCtxt};
1112
use crate::{mir, traits};
@@ -219,6 +220,10 @@ impl<T0, T1> EraseType for (&'_ T0, &'_ T1) {
219220
type Result = [u8; size_of::<(&'static (), &'static ())>()];
220221
}
221222

223+
impl<T0> EraseType for (solve::QueryResult<'_>, &'_ T0) {
224+
type Result = [u8; size_of::<(solve::QueryResult<'static>, &'static ())>()];
225+
}
226+
222227
impl<T0, T1> EraseType for (&'_ T0, &'_ [T1]) {
223228
type Result = [u8; size_of::<(&'static (), &'static [()])>()];
224229
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ use crate::traits::query::{
131131
};
132132
use crate::traits::{
133133
CodegenObligationError, DynCompatibilityViolation, EvaluationResult, ImplSource,
134-
ObligationCause, OverflowError, WellFormedLoc, specialization_graph,
134+
ObligationCause, OverflowError, WellFormedLoc, solve, specialization_graph,
135135
};
136136
use crate::ty::fast_reject::SimplifiedType;
137137
use crate::ty::layout::ValidityRequirement;
@@ -2563,6 +2563,14 @@ rustc_queries! {
25632563
desc { "computing autoderef types for `{}`", goal.canonical.value.value }
25642564
}
25652565

2566+
/// Used by `-Znext-solver` to compute proof trees.
2567+
query evaluate_root_goal_for_proof_tree_raw(
2568+
goal: solve::CanonicalInput<'tcx>,
2569+
) -> (solve::QueryResult<'tcx>, &'tcx solve::inspect::Probe<TyCtxt<'tcx>>) {
2570+
no_hash
2571+
desc { "computing proof tree for `{}`", goal.canonical.value.goal.predicate }
2572+
}
2573+
25662574
/// Returns the Rust target features for the current target. These are not always the same as LLVM target features!
25672575
query rust_target_features(_: CrateNum) -> &'tcx UnordMap<String, rustc_target::target_features::Stability> {
25682576
arena_cache

compiler/rustc_middle/src/ty/context.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ use crate::query::plumbing::QuerySystem;
7272
use crate::query::{IntoQueryParam, LocalCrate, Providers, TyCtxtAt};
7373
use crate::thir::Thir;
7474
use crate::traits;
75-
use crate::traits::solve;
7675
use crate::traits::solve::{
77-
ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData,
76+
self, CanonicalInput, ExternalConstraints, ExternalConstraintsData, PredefinedOpaques,
77+
PredefinedOpaquesData, QueryResult, inspect,
7878
};
7979
use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
8080
use crate::ty::{
@@ -737,6 +737,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
737737
self.opaque_types_defined_by(defining_anchor).iter().chain(coroutines_defined_by),
738738
)
739739
}
740+
741+
type ProbeRef = &'tcx inspect::Probe<TyCtxt<'tcx>>;
742+
fn mk_probe_ref(self, probe: inspect::Probe<Self>) -> &'tcx inspect::Probe<TyCtxt<'tcx>> {
743+
self.arena.alloc(probe)
744+
}
745+
fn evaluate_root_goal_for_proof_tree_raw(
746+
self,
747+
canonical_goal: CanonicalInput<'tcx>,
748+
) -> (QueryResult<'tcx>, &'tcx inspect::Probe<TyCtxt<'tcx>>) {
749+
self.evaluate_root_goal_for_proof_tree_raw(canonical_goal)
750+
}
740751
}
741752

742753
macro_rules! bidirectional_lang_item_map {

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,22 +56,23 @@ where
5656
///
5757
/// This expects `goal` and `opaque_types` to be eager resolved.
5858
pub(super) fn canonicalize_goal(
59-
&self,
59+
delegate: &D,
6060
goal: Goal<I, I::Predicate>,
6161
opaque_types: Vec<(ty::OpaqueTypeKey<I>, I::Ty)>,
6262
) -> (Vec<I::GenericArg>, CanonicalInput<I, I::Predicate>) {
6363
let mut orig_values = Default::default();
6464
let canonical = Canonicalizer::canonicalize_input(
65-
self.delegate,
65+
delegate,
6666
&mut orig_values,
6767
QueryInput {
6868
goal,
69-
predefined_opaques_in_body: self
69+
predefined_opaques_in_body: delegate
7070
.cx()
7171
.mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types }),
7272
},
7373
);
74-
let query_input = ty::CanonicalQueryInput { canonical, typing_mode: self.typing_mode() };
74+
let query_input =
75+
ty::CanonicalQueryInput { canonical, typing_mode: delegate.typing_mode() };
7576
(orig_values, query_input)
7677
}
7778

@@ -271,37 +272,32 @@ where
271272
/// - we apply the `external_constraints` returned by the query, returning
272273
/// the `normalization_nested_goals`
273274
pub(super) fn instantiate_and_apply_query_response(
274-
&mut self,
275+
delegate: &D,
275276
param_env: I::ParamEnv,
276277
original_values: &[I::GenericArg],
277278
response: CanonicalResponse<I>,
279+
span: I::Span,
278280
) -> (NestedNormalizationGoals<I>, Certainty) {
279281
let instantiation = Self::compute_query_response_instantiation_values(
280-
self.delegate,
282+
delegate,
281283
&original_values,
282284
&response,
283-
self.origin_span,
285+
span,
284286
);
285287

286288
let Response { var_values, external_constraints, certainty } =
287-
self.delegate.instantiate_canonical(response, instantiation);
289+
delegate.instantiate_canonical(response, instantiation);
288290

289-
Self::unify_query_var_values(
290-
self.delegate,
291-
param_env,
292-
&original_values,
293-
var_values,
294-
self.origin_span,
295-
);
291+
Self::unify_query_var_values(delegate, param_env, &original_values, var_values, span);
296292

297293
let ExternalConstraintsData {
298294
region_constraints,
299295
opaque_types,
300296
normalization_nested_goals,
301297
} = &*external_constraints;
302298

303-
self.register_region_constraints(region_constraints);
304-
self.register_new_opaque_types(opaque_types);
299+
Self::register_region_constraints(delegate, region_constraints, span);
300+
Self::register_new_opaque_types(delegate, opaque_types, span);
305301

306302
(normalization_nested_goals.clone(), certainty)
307303
}
@@ -424,21 +420,26 @@ where
424420
}
425421

426422
fn register_region_constraints(
427-
&mut self,
423+
delegate: &D,
428424
outlives: &[ty::OutlivesPredicate<I, I::GenericArg>],
425+
span: I::Span,
429426
) {
430427
for &ty::OutlivesPredicate(lhs, rhs) in outlives {
431428
match lhs.kind() {
432-
ty::GenericArgKind::Lifetime(lhs) => self.register_region_outlives(lhs, rhs),
433-
ty::GenericArgKind::Type(lhs) => self.register_ty_outlives(lhs, rhs),
429+
ty::GenericArgKind::Lifetime(lhs) => delegate.sub_regions(rhs, lhs, span),
430+
ty::GenericArgKind::Type(lhs) => delegate.register_ty_outlives(lhs, rhs, span),
434431
ty::GenericArgKind::Const(_) => panic!("const outlives: {lhs:?}: {rhs:?}"),
435432
}
436433
}
437434
}
438435

439-
fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)]) {
436+
fn register_new_opaque_types(
437+
delegate: &D,
438+
opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)],
439+
span: I::Span,
440+
) {
440441
for &(key, ty) in opaque_types {
441-
let prev = self.delegate.register_hidden_type_in_storage(key, ty, self.origin_span);
442+
let prev = delegate.register_hidden_type_in_storage(key, ty, span);
442443
// We eagerly resolve inference variables when computing the query response.
443444
// This can cause previously distinct opaque type keys to now be structurally equal.
444445
//
@@ -447,7 +448,7 @@ where
447448
// types here. However, doing so is difficult as it may result in nested goals and
448449
// any errors may make it harder to track the control flow for diagnostics.
449450
if let Some(prev) = prev {
450-
self.delegate.add_duplicate_opaque_type(key, prev, self.origin_span);
451+
delegate.add_duplicate_opaque_type(key, prev, span);
451452
}
452453
}
453454
}

0 commit comments

Comments
 (0)