Skip to content

Commit 6a17037

Browse files
committed
u fucking wu
1 parent e22f0e3 commit 6a17037

File tree

13 files changed

+384
-268
lines changed

13 files changed

+384
-268
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::FnCtxt;
33
use rustc_infer::traits::solve::Goal;
44
use rustc_infer::traits::{self, ObligationCause};
55
use rustc_middle::ty::{self, Ty};
6+
use rustc_span::Span;
67
use rustc_trait_selection::solve::inspect::ProofTreeInferCtxtExt;
78
use rustc_trait_selection::solve::inspect::{InspectConfig, InspectGoal, ProofTreeVisitor};
89

@@ -58,7 +59,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5859
debug!(?ty);
5960

6061
match *ty.kind() {
61-
ty::Infer(ty::TyVar(found_vid)) => expected_vid == self.root_var(found_vid),
62+
ty::Infer(ty::TyVar(found_vid)) => {
63+
self.root_var(expected_vid) == self.root_var(found_vid)
64+
}
6265
_ => false,
6366
}
6467
}
@@ -73,7 +76,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7376
for obligation in obligations {
7477
let mut visitor = NestedObligationsForSelfTy {
7578
fcx: self,
76-
ty_var_root: self.root_var(self_ty),
79+
self_ty,
7780
obligations_for_self_ty: &mut obligations_for_self_ty,
7881
root_cause: &obligation.cause,
7982
};
@@ -92,25 +95,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9295

9396
struct NestedObligationsForSelfTy<'a, 'tcx> {
9497
fcx: &'a FnCtxt<'a, 'tcx>,
95-
ty_var_root: ty::TyVid,
98+
self_ty: ty::TyVid,
9699
root_cause: &'a ObligationCause<'tcx>,
97100
obligations_for_self_ty: &'a mut Vec<traits::PredicateObligation<'tcx>>,
98101
}
99102

100103
impl<'a, 'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'a, 'tcx> {
101104
type Result = ();
102105

106+
fn span(&self) -> Span {
107+
self.root_cause.span
108+
}
109+
103110
fn config(&self) -> InspectConfig {
104111
// Using an intentionally low depth to minimize the chance of future
105112
// breaking changes in case we adapt the approach later on. This also
106113
// avoids any hangs for exponentially growing proof trees.
107-
InspectConfig { max_depth: 3 }
114+
InspectConfig { max_depth: 5 }
108115
}
109116

110117
fn visit_goal(&mut self, inspect_goal: &InspectGoal<'_, 'tcx>) {
111118
let tcx = self.fcx.tcx;
112119
let goal = inspect_goal.goal();
113-
if self.fcx.predicate_has_self_ty(goal.predicate, self.ty_var_root) {
120+
if self.fcx.predicate_has_self_ty(goal.predicate, self.self_ty) {
114121
self.obligations_for_self_ty.push(traits::Obligation::new(
115122
tcx,
116123
self.root_cause.clone(),

compiler/rustc_middle/src/traits/solve/inspect.rs

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ pub struct Probe<'tcx> {
102102
/// What happened inside of this probe in chronological order.
103103
pub steps: Vec<ProbeStep<'tcx>>,
104104
pub kind: ProbeKind<'tcx>,
105+
pub final_state: CanonicalState<'tcx, ()>,
105106
}
106107

107108
impl Debug for Probe<'_> {

compiler/rustc_trait_selection/src/solve/assembly/mod.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Code shared by trait and projection goals for candidate assembly.
22
3-
use super::{EvalCtxt, SolverMode};
43
use crate::solve::GoalSource;
4+
use crate::solve::{inspect, EvalCtxt, SolverMode};
55
use crate::traits::coherence;
66
use rustc_hir::def_id::DefId;
77
use rustc_infer::traits::query::NoSolution;
@@ -16,6 +16,7 @@ use rustc_middle::ty::{fast_reject, TypeFoldable};
1616
use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
1717
use rustc_span::{ErrorGuaranteed, DUMMY_SP};
1818
use std::fmt::Debug;
19+
use std::mem;
1920

2021
pub(super) mod structural_traits;
2122

@@ -324,11 +325,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
324325
// FIXME: Add a test for this. It seems to be necessary for typenum but
325326
// is incredibly hard to minimize as it may rely on being inside of a
326327
// trait solver cycle.
327-
let result = self.evaluate_added_goals_and_make_canonical_response(certainty);
328-
let mut dummy_probe = self.inspect.new_probe();
329-
dummy_probe.probe_kind(ProbeKind::TraitCandidate { source, result });
330-
self.inspect.finish_probe(dummy_probe);
331-
if let Ok(result) = result { vec![Candidate { source, result }] } else { vec![] }
328+
let result = self
329+
.probe_trait_candidate(source)
330+
.enter(|this| this.evaluate_added_goals_and_make_canonical_response(certainty));
331+
if let Ok(cand) = result { vec![cand] } else { vec![] }
332332
}
333333

334334
#[instrument(level = "debug", skip_all)]
@@ -813,6 +813,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
813813
goal: Goal<'tcx, G>,
814814
candidates: &mut Vec<Candidate<'tcx>>,
815815
) {
816+
// HACK: We temporarily remove the `ProofTreeBuilder` to
817+
// avoid adding `Trait` candidates to the candidates used
818+
// to prove the current goal.
819+
let inspect = mem::replace(&mut self.inspect, inspect::ProofTreeBuilder::new_noop());
820+
816821
let tcx = self.tcx();
817822
let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> =
818823
goal.with(tcx, goal.predicate.trait_ref(tcx));
@@ -846,6 +851,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
846851
}
847852
}
848853
}
854+
self.inspect = inspect;
849855
}
850856

851857
/// If there are multiple ways to prove a trait or projection goal, we have

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

+52-29
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,25 @@ use crate::solve::{
1515
};
1616
use rustc_data_structures::fx::FxHashSet;
1717
use rustc_index::IndexVec;
18+
1819
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
1920
use rustc_infer::infer::canonical::CanonicalVarValues;
2021
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
2122
use rustc_infer::infer::resolve::EagerResolver;
23+
use rustc_infer::infer::type_variable::TypeVariableOrigin;
24+
use rustc_infer::infer::RegionVariableOrigin;
2225
use rustc_infer::infer::{InferCtxt, InferOk};
2326
use rustc_infer::traits::solve::NestedNormalizationGoals;
2427
use rustc_middle::infer::canonical::Canonical;
28+
use rustc_middle::infer::unify_key::ConstVariableOrigin;
2529
use rustc_middle::traits::query::NoSolution;
2630
use rustc_middle::traits::solve::{
2731
ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput,
2832
};
2933
use rustc_middle::traits::ObligationCause;
3034
use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable};
3135
use rustc_next_trait_solver::canonicalizer::{CanonicalizeMode, Canonicalizer};
32-
use rustc_span::DUMMY_SP;
36+
use rustc_span::{Span, DUMMY_SP};
3337
use std::assert_matches::assert_matches;
3438
use std::iter;
3539
use std::ops::Deref;
@@ -374,36 +378,55 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
374378
}
375379
}
376380

377-
impl<'tcx> inspect::ProofTreeBuilder<'tcx> {
378-
pub fn make_canonical_state<T: TypeFoldable<TyCtxt<'tcx>>>(
379-
ecx: &EvalCtxt<'_, 'tcx>,
380-
data: T,
381-
) -> inspect::CanonicalState<'tcx, T> {
382-
let state = inspect::State { var_values: ecx.var_values, data };
383-
let state = state.fold_with(&mut EagerResolver::new(ecx.infcx));
384-
Canonicalizer::canonicalize(
385-
ecx.infcx,
386-
CanonicalizeMode::Response { max_input_universe: ecx.max_input_universe },
387-
&mut vec![],
388-
state,
389-
)
381+
pub(in crate::solve) fn make_canonical_state<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
382+
infcx: &InferCtxt<'tcx>,
383+
var_values: &[ty::GenericArg<'tcx>],
384+
max_input_universe: ty::UniverseIndex,
385+
data: T,
386+
) -> inspect::CanonicalState<'tcx, T> {
387+
let var_values = CanonicalVarValues { var_values: infcx.tcx.mk_args(var_values) };
388+
let state = inspect::State { var_values, data };
389+
let state = state.fold_with(&mut EagerResolver::new(infcx));
390+
Canonicalizer::canonicalize(
391+
infcx,
392+
CanonicalizeMode::Response { max_input_universe },
393+
&mut vec![],
394+
state,
395+
)
396+
}
397+
398+
/// Instantiate a `CanonicalState`. This assumes that unifying the var values
399+
/// trivially succeeds. Adding any inference constraints which weren't present when
400+
/// originally computing the canonical query can result in bugs.
401+
pub(in crate::solve) fn instantiate_canonical_state<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
402+
infcx: &InferCtxt<'tcx>,
403+
span: Span,
404+
param_env: ty::ParamEnv<'tcx>,
405+
original_values: &mut Vec<ty::GenericArg<'tcx>>,
406+
state: inspect::CanonicalState<'tcx, T>,
407+
) -> T {
408+
assert!(original_values.len() <= state.value.var_values.len());
409+
for i in original_values.len()..state.value.var_values.len() {
410+
let unconstrained = match state.value.var_values.var_values[i].unpack() {
411+
ty::GenericArgKind::Lifetime(_) => {
412+
infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)).into()
413+
}
414+
ty::GenericArgKind::Type(_) => {
415+
infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span }).into()
416+
}
417+
ty::GenericArgKind::Const(ct) => infcx
418+
.next_const_var(ct.ty(), ConstVariableOrigin { param_def_id: None, span })
419+
.into(),
420+
};
421+
422+
original_values.push(unconstrained);
390423
}
391424

392-
/// Instantiate a `CanonicalState`. This assumes that unifying the var values
393-
/// trivially succeeds. Adding any inference constraints which weren't present when
394-
/// originally computing the canonical query can result in bugs.
395-
pub fn instantiate_canonical_state<T: TypeFoldable<TyCtxt<'tcx>>>(
396-
infcx: &InferCtxt<'tcx>,
397-
param_env: ty::ParamEnv<'tcx>,
398-
original_values: &[ty::GenericArg<'tcx>],
399-
state: inspect::CanonicalState<'tcx, T>,
400-
) -> T {
401-
let instantiation =
402-
EvalCtxt::compute_query_response_instantiation_values(infcx, original_values, &state);
425+
let instantiation =
426+
EvalCtxt::compute_query_response_instantiation_values(infcx, original_values, &state);
403427

404-
let inspect::State { var_values, data } = state.instantiate(infcx.tcx, &instantiation);
428+
let inspect::State { var_values, data } = state.instantiate(infcx.tcx, &instantiation);
405429

406-
EvalCtxt::unify_query_var_values(infcx, param_env, original_values, var_values);
407-
data
408-
}
430+
EvalCtxt::unify_query_var_values(infcx, param_env, original_values, var_values);
431+
data
409432
}

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

+32-20
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use super::{search_graph::SearchGraph, Goal};
3434
use super::{GoalSource, SolverMode};
3535
pub use select::InferCtxtSelectExt;
3636

37-
mod canonical;
37+
pub(super) mod canonical;
3838
mod probe;
3939
mod select;
4040

@@ -84,7 +84,7 @@ pub struct EvalCtxt<'a, 'tcx> {
8484

8585
pub(super) search_graph: &'a mut SearchGraph<'tcx>,
8686

87-
pub(super) nested_goals: NestedGoals<'tcx>,
87+
nested_goals: NestedGoals<'tcx>,
8888

8989
// Has this `EvalCtxt` errored out with `NoSolution` in `try_evaluate_added_goals`?
9090
//
@@ -161,7 +161,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
161161
/// Creates a root evaluation context and search graph. This should only be
162162
/// used from outside of any evaluation, and other methods should be preferred
163163
/// over using this manually (such as [`InferCtxtEvalExt::evaluate_root_goal`]).
164-
fn enter_root<R>(
164+
pub(super) fn enter_root<R>(
165165
infcx: &InferCtxt<'tcx>,
166166
generate_proof_tree: GenerateProofTree,
167167
f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> R,
@@ -242,7 +242,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
242242
search_graph,
243243
nested_goals: NestedGoals::new(),
244244
tainted: Ok(()),
245-
inspect: canonical_goal_evaluation.new_goal_evaluation_step(input),
245+
inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values, input),
246246
};
247247

248248
for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
@@ -255,7 +255,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
255255
}
256256

257257
let result = f(&mut ecx, input.goal);
258-
258+
ecx.inspect.probe_final_state(ecx.infcx, ecx.max_input_universe);
259259
canonical_goal_evaluation.goal_evaluation_step(ecx.inspect);
260260

261261
// When creating a query response we clone the opaque type constraints
@@ -338,7 +338,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
338338
/// storage.
339339
// FIXME(-Znext-solver=coinduction): `_source` is currently unused but will
340340
// be necessary once we implement the new coinduction approach.
341-
fn evaluate_goal_raw(
341+
pub(super) fn evaluate_goal_raw(
342342
&mut self,
343343
goal_evaluation_kind: GoalEvaluationKind,
344344
_source: GoalSource,
@@ -458,13 +458,23 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
458458
}
459459
}
460460

461+
#[instrument(level = "debug", skip(self))]
462+
pub(super) fn add_normalizes_to_goal(&mut self, goal: Goal<'tcx, ty::NormalizesTo<'tcx>>) {
463+
self.inspect.add_normalizes_to_goal(self.infcx, self.max_input_universe, goal);
464+
self.nested_goals.normalizes_to_goals.push(goal);
465+
}
466+
467+
#[instrument(level = "debug", skip(self))]
468+
pub(super) fn add_goal(&mut self, source: GoalSource, goal: Goal<'tcx, ty::Predicate<'tcx>>) {
469+
self.inspect.add_goal(self.infcx, self.max_input_universe, source, goal);
470+
self.nested_goals.goals.push((source, goal));
471+
}
472+
461473
// Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning
462474
// the certainty of all the goals.
463475
#[instrument(level = "debug", skip(self))]
464476
pub(super) fn try_evaluate_added_goals(&mut self) -> Result<Certainty, NoSolution> {
465-
let inspect = self.inspect.new_evaluate_added_goals();
466-
let inspect = core::mem::replace(&mut self.inspect, inspect);
467-
477+
self.inspect.start_evaluate_added_goals();
468478
let mut response = Ok(Certainty::overflow(false));
469479
for _ in 0..FIXPOINT_STEP_LIMIT {
470480
// FIXME: This match is a bit ugly, it might be nice to change the inspect
@@ -482,15 +492,12 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
482492
}
483493
}
484494

485-
self.inspect.eval_added_goals_result(response);
495+
self.inspect.evaluate_added_goals_result(response);
486496

487497
if response.is_err() {
488498
self.tainted = Err(NoSolution);
489499
}
490500

491-
let goal_evaluations = std::mem::replace(&mut self.inspect, inspect);
492-
self.inspect.added_goals_evaluation(goal_evaluations);
493-
494501
response
495502
}
496503

@@ -499,10 +506,9 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
499506
/// Goals for the next step get directly added to the nested goals of the `EvalCtxt`.
500507
fn evaluate_added_goals_step(&mut self) -> Result<Option<Certainty>, NoSolution> {
501508
let tcx = self.tcx();
509+
self.inspect.start_evaluate_added_goals_step();
502510
let mut goals = core::mem::take(&mut self.nested_goals);
503511

504-
self.inspect.evaluate_added_goals_loop_start();
505-
506512
// If this loop did not result in any progress, what's our final certainty.
507513
let mut unchanged_certainty = Some(Certainty::Yes);
508514
for goal in goals.normalizes_to_goals {
@@ -586,17 +592,23 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
586592
self.infcx.tcx
587593
}
588594

589-
pub(super) fn next_ty_infer(&self) -> Ty<'tcx> {
590-
self.infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span: DUMMY_SP })
595+
pub(super) fn next_ty_infer(&mut self) -> Ty<'tcx> {
596+
let ty = self.infcx.next_ty_var(TypeVariableOrigin { param_def_id: None, span: DUMMY_SP });
597+
self.inspect.add_var_value(ty);
598+
ty
591599
}
592600

593-
pub(super) fn next_const_infer(&self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
594-
self.infcx.next_const_var(ty, ConstVariableOrigin { param_def_id: None, span: DUMMY_SP })
601+
pub(super) fn next_const_infer(&mut self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
602+
let ct = self
603+
.infcx
604+
.next_const_var(ty, ConstVariableOrigin { param_def_id: None, span: DUMMY_SP });
605+
self.inspect.add_var_value(ct);
606+
ct
595607
}
596608

597609
/// Returns a ty infer or a const infer depending on whether `kind` is a `Ty` or `Const`.
598610
/// If `kind` is an integer inference variable this will still return a ty infer var.
599-
pub(super) fn next_term_infer_of_kind(&self, kind: ty::Term<'tcx>) -> ty::Term<'tcx> {
611+
pub(super) fn next_term_infer_of_kind(&mut self, kind: ty::Term<'tcx>) -> ty::Term<'tcx> {
600612
match kind.unpack() {
601613
ty::TermKind::Ty(_) => self.next_ty_infer().into(),
602614
ty::TermKind::Const(ct) => self.next_const_infer(ct.ty()).into(),

0 commit comments

Comments
 (0)