use std::convert::Infallible; use std::marker::PhantomData; use rustc_type_ir::data_structures::ensure_sufficient_stack; use rustc_type_ir::search_graph::{self, PathKind}; use rustc_type_ir::solve::{CanonicalInput, Certainty, NoSolution, QueryResult}; use rustc_type_ir::{Interner, TypingMode}; use crate::canonical::response_no_constraints_raw; use crate::delegate::SolverDelegate; use crate::solve::{ EvalCtxt, FIXPOINT_STEP_LIMIT, has_no_inference_or_external_constraints, inspect, }; /// This type is never constructed. We only use it to implement `search_graph::Delegate` /// for all types which impl `SolverDelegate` and doing it directly fails in coherence. pub(super) struct SearchGraphDelegate { _marker: PhantomData, } pub(super) type SearchGraph = search_graph::SearchGraph>; impl search_graph::Delegate for SearchGraphDelegate where D: SolverDelegate, I: Interner, { type Cx = D::Interner; const ENABLE_PROVISIONAL_CACHE: bool = true; type ValidationScope = Infallible; fn enter_validation_scope( _cx: Self::Cx, _input: CanonicalInput, ) -> Option { None } const FIXPOINT_STEP_LIMIT: usize = FIXPOINT_STEP_LIMIT; type ProofTreeBuilder = inspect::ProofTreeBuilder; fn inspect_is_noop(inspect: &mut Self::ProofTreeBuilder) -> bool { inspect.is_noop() } const DIVIDE_AVAILABLE_DEPTH_ON_OVERFLOW: usize = 4; fn initial_provisional_result( cx: I, kind: PathKind, input: CanonicalInput, ) -> QueryResult { match kind { PathKind::Coinductive => response_no_constraints(cx, input, Certainty::Yes), PathKind::Unknown | PathKind::ForcedAmbiguity => { response_no_constraints(cx, input, Certainty::overflow(false)) } // Even though we know these cycles to be unproductive, we still return // overflow during coherence. This is both as we are not 100% confident in // the implementation yet and any incorrect errors would be unsound there. // The affected cases are also fairly artificial and not necessarily desirable // so keeping this as ambiguity is fine for now. // // See `tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs` for an // example where this would matter. We likely should change these cycles to `NoSolution` // even in coherence once this is a bit more settled. PathKind::Inductive => match input.typing_mode { TypingMode::Coherence => { response_no_constraints(cx, input, Certainty::overflow(false)) } TypingMode::Analysis { .. } | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => Err(NoSolution), }, } } fn is_initial_provisional_result(result: QueryResult) -> Option { match result { Ok(response) => { if has_no_inference_or_external_constraints(response) { if response.value.certainty == Certainty::Yes { return Some(PathKind::Coinductive); } else if response.value.certainty == Certainty::overflow(false) { return Some(PathKind::Unknown); } } None } Err(NoSolution) => Some(PathKind::Inductive), } } fn stack_overflow_result(cx: I, input: CanonicalInput) -> QueryResult { response_no_constraints(cx, input, Certainty::overflow(true)) } fn fixpoint_overflow_result(cx: I, input: CanonicalInput) -> QueryResult { response_no_constraints(cx, input, Certainty::overflow(false)) } fn is_ambiguous_result(result: QueryResult) -> bool { result.is_ok_and(|response| { has_no_inference_or_external_constraints(response) && matches!(response.value.certainty, Certainty::Maybe { .. }) }) } fn propagate_ambiguity( cx: I, for_input: CanonicalInput, from_result: QueryResult, ) -> QueryResult { let certainty = from_result.unwrap().value.certainty; response_no_constraints(cx, for_input, certainty) } fn compute_goal( search_graph: &mut SearchGraph, cx: I, input: CanonicalInput, inspect: &mut Self::ProofTreeBuilder, ) -> QueryResult { ensure_sufficient_stack(|| { EvalCtxt::enter_canonical(cx, search_graph, input, inspect, |ecx, goal| { let result = ecx.compute_goal(goal); ecx.inspect.query_result(result); result }) }) } } fn response_no_constraints( cx: I, input: CanonicalInput, certainty: Certainty, ) -> QueryResult { Ok(response_no_constraints_raw( cx, input.canonical.max_universe, input.canonical.variables, certainty, )) }