@@ -9,6 +9,7 @@ use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
99use rustc_type_ir:: inherent:: * ;
1010use rustc_type_ir:: relate:: Relate ;
1111use rustc_type_ir:: relate:: solver_relating:: RelateExt ;
12+ use rustc_type_ir:: search_graph:: PathKind ;
1213use rustc_type_ir:: visit:: { TypeSuperVisitable , TypeVisitable , TypeVisitableExt , TypeVisitor } ;
1314use rustc_type_ir:: { self as ty, CanonicalVarValues , InferCtxtLike , Interner , TypingMode } ;
1415use rustc_type_ir_macros:: { Lift_Generic , TypeFoldable_Generic , TypeVisitable_Generic } ;
@@ -20,12 +21,51 @@ use crate::solve::inspect::{self, ProofTreeBuilder};
2021use crate :: solve:: search_graph:: SearchGraph ;
2122use crate :: solve:: {
2223 CanonicalInput , Certainty , FIXPOINT_STEP_LIMIT , Goal , GoalEvaluationKind , GoalSource ,
23- HasChanged , NestedNormalizationGoals , NoSolution , PredefinedOpaquesData , QueryResult ,
24+ HasChanged , NestedNormalizationGoals , NoSolution , PredefinedOpaquesData , QueryInput ,
25+ QueryResult ,
2426} ;
2527
2628pub ( super ) mod canonical;
2729mod probe;
2830
31+ /// The kind of goal we're currently proving.
32+ ///
33+ /// This has effects on cycle handling handling and on how we compute
34+ /// query responses, see the variant descriptions for more info.
35+ #[ derive( Debug , Copy , Clone ) ]
36+ enum CurrentGoalKind {
37+ Misc ,
38+ /// We're proving an trait goal for a coinductive trait, either an auto trait or `Sized`.
39+ ///
40+ /// These are currently the only goals whose impl where-clauses are considered to be
41+ /// productive steps.
42+ CoinductiveTrait ,
43+ /// Unlike other goals, `NormalizesTo` goals act like functions with the expected term
44+ /// always being fully unconstrained. This would weaken inference however, as the nested
45+ /// goals never get the inference constraints from the actual normalized-to type.
46+ ///
47+ /// Because of this we return any ambiguous nested goals from `NormalizesTo` to the
48+ /// caller when then adds these to its own context. The caller is always an `AliasRelate`
49+ /// goal so this never leaks out of the solver.
50+ NormalizesTo ,
51+ }
52+
53+ impl CurrentGoalKind {
54+ fn from_query_input < I : Interner > ( cx : I , input : QueryInput < I , I :: Predicate > ) -> CurrentGoalKind {
55+ match input. goal . predicate . kind ( ) . skip_binder ( ) {
56+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) => {
57+ if cx. trait_is_coinductive ( pred. trait_ref . def_id ) {
58+ CurrentGoalKind :: CoinductiveTrait
59+ } else {
60+ CurrentGoalKind :: Misc
61+ }
62+ }
63+ ty:: PredicateKind :: NormalizesTo ( _) => CurrentGoalKind :: NormalizesTo ,
64+ _ => CurrentGoalKind :: Misc ,
65+ }
66+ }
67+ }
68+
2969pub struct EvalCtxt < ' a , D , I = <D as SolverDelegate >:: Interner >
3070where
3171 D : SolverDelegate < Interner = I > ,
@@ -51,14 +91,10 @@ where
5191 /// The variable info for the `var_values`, only used to make an ambiguous response
5292 /// with no constraints.
5393 variables : I :: CanonicalVars ,
54- /// Whether we're currently computing a `NormalizesTo` goal. Unlike other goals,
55- /// `NormalizesTo` goals act like functions with the expected term always being
56- /// fully unconstrained. This would weaken inference however, as the nested goals
57- /// never get the inference constraints from the actual normalized-to type. Because
58- /// of this we return any ambiguous nested goals from `NormalizesTo` to the caller
59- /// when then adds these to its own context. The caller is always an `AliasRelate`
60- /// goal so this never leaks out of the solver.
61- is_normalizes_to_goal : bool ,
94+
95+ /// What kind of goal we're currently computing, see the enum definition
96+ /// for more info.
97+ current_goal_kind : CurrentGoalKind ,
6298 pub ( super ) var_values : CanonicalVarValues < I > ,
6399
64100 predefined_opaques_in_body : I :: PredefinedOpaques ,
@@ -226,8 +262,11 @@ where
226262 self . delegate . typing_mode ( )
227263 }
228264
229- pub ( super ) fn set_is_normalizes_to_goal ( & mut self ) {
230- self . is_normalizes_to_goal = true ;
265+ pub ( super ) fn step_kind_for_source ( & self , source : GoalSource ) -> PathKind {
266+ match ( self . current_goal_kind , source) {
267+ ( CurrentGoalKind :: CoinductiveTrait , GoalSource :: ImplWhereBound ) => PathKind :: Coinductive ,
268+ _ => PathKind :: Inductive ,
269+ }
231270 }
232271
233272 /// Creates a root evaluation context and search graph. This should only be
@@ -256,7 +295,7 @@ where
256295 max_input_universe : ty:: UniverseIndex :: ROOT ,
257296 variables : Default :: default ( ) ,
258297 var_values : CanonicalVarValues :: dummy ( ) ,
259- is_normalizes_to_goal : false ,
298+ current_goal_kind : CurrentGoalKind :: Misc ,
260299 origin_span,
261300 tainted : Ok ( ( ) ) ,
262301 } ;
@@ -294,7 +333,7 @@ where
294333 delegate,
295334 variables : canonical_input. canonical . variables ,
296335 var_values,
297- is_normalizes_to_goal : false ,
336+ current_goal_kind : CurrentGoalKind :: from_query_input ( cx , input ) ,
298337 predefined_opaques_in_body : input. predefined_opaques_in_body ,
299338 max_input_universe : canonical_input. canonical . max_universe ,
300339 search_graph,
@@ -340,6 +379,7 @@ where
340379 cx : I ,
341380 search_graph : & ' a mut SearchGraph < D > ,
342381 canonical_input : CanonicalInput < I > ,
382+ step_kind_from_parent : PathKind ,
343383 goal_evaluation : & mut ProofTreeBuilder < D > ,
344384 ) -> QueryResult < I > {
345385 let mut canonical_goal_evaluation =
@@ -352,6 +392,7 @@ where
352392 search_graph. with_new_goal (
353393 cx,
354394 canonical_input,
395+ step_kind_from_parent,
355396 & mut canonical_goal_evaluation,
356397 |search_graph, canonical_goal_evaluation| {
357398 EvalCtxt :: enter_canonical (
@@ -395,12 +436,10 @@ where
395436 /// `NormalizesTo` is only used by `AliasRelate`, all other callsites
396437 /// should use [`EvalCtxt::evaluate_goal`] which discards that empty
397438 /// storage.
398- // FIXME(-Znext-solver=coinduction): `_source` is currently unused but will
399- // be necessary once we implement the new coinduction approach.
400439 pub ( super ) fn evaluate_goal_raw (
401440 & mut self ,
402441 goal_evaluation_kind : GoalEvaluationKind ,
403- _source : GoalSource ,
442+ source : GoalSource ,
404443 goal : Goal < I , I :: Predicate > ,
405444 ) -> Result < ( NestedNormalizationGoals < I > , HasChanged , Certainty ) , NoSolution > {
406445 let ( orig_values, canonical_goal) = self . canonicalize_goal ( goal) ;
@@ -410,6 +449,7 @@ where
410449 self . cx ( ) ,
411450 self . search_graph ,
412451 canonical_goal,
452+ self . step_kind_for_source ( source) ,
413453 & mut goal_evaluation,
414454 ) ;
415455 let response = match canonical_response {
0 commit comments