Skip to content

Commit b5f4d62

Browse files
committed
very gamer, much perf
1 parent a1927d6 commit b5f4d62

File tree

15 files changed

+250
-157
lines changed

15 files changed

+250
-157
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;
@@ -2561,6 +2561,14 @@ rustc_queries! {
25612561
desc { "computing autoderef types for `{}`", goal.canonical.value.value }
25622562
}
25632563

2564+
/// Used by `-Znext-solver` to compute proof trees.
2565+
query evaluate_root_goal_for_proof_tree_raw(
2566+
goal: solve::CanonicalInput<'tcx>,
2567+
) -> (solve::QueryResult<'tcx>, &'tcx solve::inspect::Probe<TyCtxt<'tcx>>) {
2568+
no_hash
2569+
desc { "computing proof tree for `{}`", goal.canonical.value.goal.predicate }
2570+
}
2571+
25642572
/// Returns the Rust target features for the current target. These are not always the same as LLVM target features!
25652573
query rust_target_features(_: CrateNum) -> &'tcx UnordMap<String, rustc_target::target_features::Stability> {
25662574
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: 25 additions & 18 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,27 +272,28 @@ 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+
origin_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+
origin_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

289291
Self::unify_query_var_values(
290-
self.delegate,
292+
delegate,
291293
param_env,
292294
&original_values,
293295
var_values,
294-
self.origin_span,
296+
origin_span,
295297
);
296298

297299
let ExternalConstraintsData {
@@ -300,8 +302,8 @@ where
300302
normalization_nested_goals,
301303
} = &*external_constraints;
302304

303-
self.register_region_constraints(region_constraints);
304-
self.register_new_opaque_types(opaque_types);
305+
Self::register_region_constraints(delegate, region_constraints, origin_span);
306+
Self::register_new_opaque_types(delegate, opaque_types, origin_span);
305307

306308
(normalization_nested_goals.clone(), certainty)
307309
}
@@ -424,21 +426,26 @@ where
424426
}
425427

426428
fn register_region_constraints(
427-
&mut self,
429+
delegate: &D,
428430
outlives: &[ty::OutlivesPredicate<I, I::GenericArg>],
431+
span: I::Span,
429432
) {
430433
for &ty::OutlivesPredicate(lhs, rhs) in outlives {
431434
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),
435+
ty::GenericArgKind::Lifetime(lhs) => delegate.sub_regions(rhs, lhs, span),
436+
ty::GenericArgKind::Type(lhs) => delegate.register_ty_outlives(lhs, rhs, span),
434437
ty::GenericArgKind::Const(_) => panic!("const outlives: {lhs:?}: {rhs:?}"),
435438
}
436439
}
437440
}
438441

439-
fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)]) {
442+
fn register_new_opaque_types(
443+
delegate: &D,
444+
opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)],
445+
span: I::Span,
446+
) {
440447
for &(key, ty) in opaque_types {
441-
let prev = self.delegate.register_hidden_type_in_storage(key, ty, self.origin_span);
448+
let prev = delegate.register_hidden_type_in_storage(key, ty, span);
442449
// We eagerly resolve inference variables when computing the query response.
443450
// This can cause previously distinct opaque type keys to now be structurally equal.
444451
//
@@ -447,7 +454,7 @@ where
447454
// types here. However, doing so is difficult as it may result in nested goals and
448455
// any errors may make it harder to track the control flow for diagnostics.
449456
if let Some(prev) = prev {
450-
self.delegate.add_duplicate_opaque_type(key, prev, self.origin_span);
457+
delegate.add_duplicate_opaque_type(key, prev, span);
451458
}
452459
}
453460
}

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

Lines changed: 73 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,7 @@ where
212212
goal: Goal<I, I::Predicate>,
213213
span: I::Span,
214214
) -> (Result<NestedNormalizationGoals<I>, NoSolution>, inspect::GoalEvaluation<I>) {
215-
EvalCtxt::enter_root(self, self.cx().recursion_limit(), span, |ecx| {
216-
ecx.evaluate_goal_for_proof_tree(goal)
217-
})
215+
evaluate_root_goal_for_proof_tree(self, goal, span)
218216
}
219217
}
220218

@@ -324,11 +322,10 @@ where
324322
cx: I,
325323
search_graph: &'a mut SearchGraph<D>,
326324
canonical_input: CanonicalInput<I>,
327-
canonical_goal_evaluation: &mut inspect::GoalEvaluationBuilder<D>,
325+
proof_tree_builder: &mut inspect::ProofTreeBuilder<D>,
328326
f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R,
329327
) -> R {
330328
let (ref delegate, input, var_values) = D::build_with_canonical(cx, &canonical_input);
331-
332329
for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
333330
let prev = delegate.register_hidden_type_in_storage(key, ty, I::Span::dummy());
334331
// It may be possible that two entries in the opaque type storage end up
@@ -359,12 +356,12 @@ where
359356
nested_goals: Default::default(),
360357
origin_span: I::Span::dummy(),
361358
tainted: Ok(()),
362-
inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values),
359+
inspect: proof_tree_builder.new_evaluation_step(var_values),
363360
};
364361

365362
let result = f(&mut ecx, input.goal);
366363
ecx.inspect.probe_final_state(ecx.delegate, ecx.max_input_universe);
367-
canonical_goal_evaluation.goal_evaluation_step(ecx.inspect);
364+
proof_tree_builder.finish_evaluation_step(ecx.inspect);
368365

369366
// When creating a query response we clone the opaque type constraints
370367
// instead of taking them. This would cause an ICE here, since we have
@@ -434,12 +431,13 @@ where
434431
let opaque_types = self.delegate.clone_opaque_types_lookup_table();
435432
let (goal, opaque_types) = eager_resolve_vars(self.delegate, (goal, opaque_types));
436433

437-
let (orig_values, canonical_goal) = self.canonicalize_goal(goal, opaque_types);
434+
let (orig_values, canonical_goal) =
435+
Self::canonicalize_goal(self.delegate, goal, opaque_types);
438436
let canonical_result = self.search_graph.evaluate_goal(
439437
self.cx(),
440438
canonical_goal,
441439
self.step_kind_for_source(source),
442-
&mut inspect::GoalEvaluationBuilder::new_noop(),
440+
&mut inspect::ProofTreeBuilder::new_noop(),
443441
);
444442
let response = match canonical_result {
445443
Err(e) => return Err(e),
@@ -449,8 +447,13 @@ where
449447
let has_changed =
450448
if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No };
451449

452-
let (normalization_nested_goals, certainty) =
453-
self.instantiate_and_apply_query_response(goal.param_env, &orig_values, response);
450+
let (normalization_nested_goals, certainty) = Self::instantiate_and_apply_query_response(
451+
self.delegate,
452+
goal.param_env,
453+
&orig_values,
454+
response,
455+
self.origin_span,
456+
);
454457

455458
// FIXME: We previously had an assert here that checked that recomputing
456459
// a goal after applying its constraints did not change its response.
@@ -514,35 +517,6 @@ where
514517
))
515518
}
516519

517-
/// Evaluate a goal to build a proof tree. This is a copy of [EvalCtxt::evaluate_goal_raw].
518-
pub(super) fn evaluate_goal_for_proof_tree(
519-
&mut self,
520-
goal: Goal<I, I::Predicate>,
521-
) -> (Result<NestedNormalizationGoals<I>, NoSolution>, inspect::GoalEvaluation<I>) {
522-
let opaque_types = self.delegate.clone_opaque_types_lookup_table();
523-
let (goal, opaque_types) = eager_resolve_vars(self.delegate, (goal, opaque_types));
524-
525-
let (orig_values, canonical_goal) = self.canonicalize_goal(goal, opaque_types);
526-
let mut goal_evaluation = inspect::GoalEvaluationBuilder::new(goal, &orig_values);
527-
let canonical_result = self.search_graph.evaluate_goal(
528-
self.cx(),
529-
canonical_goal,
530-
self.step_kind_for_source(GoalSource::Misc),
531-
&mut goal_evaluation,
532-
);
533-
goal_evaluation.query_result(canonical_result);
534-
let proof_tree = goal_evaluation.finalize();
535-
let response = match canonical_result {
536-
Err(e) => return (Err(e), proof_tree),
537-
Ok(response) => response,
538-
};
539-
540-
let (normalization_nested_goals, _certainty) =
541-
self.instantiate_and_apply_query_response(goal.param_env, &orig_values, response);
542-
543-
(Ok(normalization_nested_goals), proof_tree)
544-
}
545-
546520
pub(super) fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
547521
let Goal { param_env, predicate } = goal;
548522
let kind = predicate.kind();
@@ -1293,3 +1267,62 @@ where
12931267
if predicate.allow_normalization() { predicate.super_fold_with(self) } else { predicate }
12941268
}
12951269
}
1270+
1271+
/// Do not call this directly, use the `tcx` query instead.
1272+
pub fn evaluate_root_goal_for_proof_tree_raw_provider<
1273+
D: SolverDelegate<Interner = I>,
1274+
I: Interner,
1275+
>(
1276+
cx: I,
1277+
canonical_goal: CanonicalInput<I>,
1278+
) -> (QueryResult<I>, I::ProbeRef) {
1279+
let mut inspect = inspect::ProofTreeBuilder::new();
1280+
let canonical_result = SearchGraph::<D>::evaluate_root_goal_for_proof_tree(
1281+
cx,
1282+
cx.recursion_limit(),
1283+
canonical_goal,
1284+
&mut inspect,
1285+
);
1286+
let final_revision = inspect.unwrap();
1287+
(canonical_result, cx.mk_probe_ref(final_revision))
1288+
}
1289+
1290+
/// Evaluate a goal to build a proof tree.
1291+
///
1292+
/// This is a copy of [EvalCtxt::evaluate_goal_raw] which avoids relying on the
1293+
/// [EvalCtxt] and uses a separate cache.
1294+
pub(super) fn evaluate_root_goal_for_proof_tree<D: SolverDelegate<Interner = I>, I: Interner>(
1295+
delegate: &D,
1296+
goal: Goal<I, I::Predicate>,
1297+
origin_span: I::Span,
1298+
) -> (Result<NestedNormalizationGoals<I>, NoSolution>, inspect::GoalEvaluation<I>) {
1299+
let opaque_types = delegate.clone_opaque_types_lookup_table();
1300+
let (goal, opaque_types) = eager_resolve_vars(delegate, (goal, opaque_types));
1301+
1302+
let (orig_values, canonical_goal) = EvalCtxt::canonicalize_goal(delegate, goal, opaque_types);
1303+
1304+
let (canonical_result, final_revision) =
1305+
delegate.cx().evaluate_root_goal_for_proof_tree_raw(canonical_goal);
1306+
1307+
let proof_tree = inspect::GoalEvaluation {
1308+
uncanonicalized_goal: goal,
1309+
orig_values,
1310+
final_revision,
1311+
result: canonical_result,
1312+
};
1313+
1314+
let response = match canonical_result {
1315+
Err(e) => return (Err(e), proof_tree),
1316+
Ok(response) => response,
1317+
};
1318+
1319+
let (normalization_nested_goals, _certainty) = EvalCtxt::instantiate_and_apply_query_response(
1320+
delegate,
1321+
goal.param_env,
1322+
&proof_tree.orig_values,
1323+
response,
1324+
origin_span,
1325+
);
1326+
1327+
(Ok(normalization_nested_goals), proof_tree)
1328+
}

0 commit comments

Comments
 (0)