Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/infer/select.rs')
| -rw-r--r-- | crates/hir-ty/src/next_solver/infer/select.rs | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/crates/hir-ty/src/next_solver/infer/select.rs b/crates/hir-ty/src/next_solver/infer/select.rs index 4f111fa662..392e2b9329 100644 --- a/crates/hir-ty/src/next_solver/infer/select.rs +++ b/crates/hir-ty/src/next_solver/infer/select.rs @@ -12,6 +12,7 @@ use crate::{ Const, ErrorGuaranteed, GenericArgs, Goal, TraitRef, Ty, TypeError, infer::{ InferCtxt, + select::EvaluationResult::*, traits::{Obligation, ObligationCause, PredicateObligation, TraitObligation}, }, inspect::{InspectCandidate, InspectGoal, ProofTreeVisitor}, @@ -47,6 +48,83 @@ pub enum NotConstEvaluatable { MentionsParam, } +/// The result of trait evaluation. The order is important +/// here as the evaluation of a list is the maximum of the +/// evaluations. +/// +/// The evaluation results are ordered: +/// - `EvaluatedToOk` implies `EvaluatedToOkModuloRegions` +/// implies `EvaluatedToAmbig` implies `EvaluatedToAmbigStackDependent` +/// - the "union" of evaluation results is equal to their maximum - +/// all the "potential success" candidates can potentially succeed, +/// so they are noops when unioned with a definite error, and within +/// the categories it's easy to see that the unions are correct. +#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] +pub enum EvaluationResult { + /// Evaluation successful. + EvaluatedToOk, + /// Evaluation successful, but there were unevaluated region obligations. + EvaluatedToOkModuloRegions, + /// Evaluation successful, but need to rerun because opaque types got + /// hidden types assigned without it being known whether the opaque types + /// are within their defining scope + EvaluatedToOkModuloOpaqueTypes, + /// Evaluation is known to be ambiguous -- it *might* hold for some + /// assignment of inference variables, but it might not. + /// + /// While this has the same meaning as `EvaluatedToAmbigStackDependent` -- we can't + /// know whether this obligation holds or not -- it is the result we + /// would get with an empty stack, and therefore is cacheable. + EvaluatedToAmbig, + /// Evaluation failed because of recursion involving inference + /// variables. We are somewhat imprecise there, so we don't actually + /// know the real result. + /// + /// This can't be trivially cached because the result depends on the + /// stack results. + EvaluatedToAmbigStackDependent, + /// Evaluation failed. + EvaluatedToErr, +} + +impl EvaluationResult { + /// Returns `true` if this evaluation result is known to apply, even + /// considering outlives constraints. + pub fn must_apply_considering_regions(self) -> bool { + self == EvaluatedToOk + } + + /// Returns `true` if this evaluation result is known to apply, ignoring + /// outlives constraints. + pub fn must_apply_modulo_regions(self) -> bool { + self <= EvaluatedToOkModuloRegions + } + + pub fn may_apply(self) -> bool { + match self { + EvaluatedToOkModuloOpaqueTypes + | EvaluatedToOk + | EvaluatedToOkModuloRegions + | EvaluatedToAmbig + | EvaluatedToAmbigStackDependent => true, + + EvaluatedToErr => false, + } + } + + pub fn is_stack_dependent(self) -> bool { + match self { + EvaluatedToAmbigStackDependent => true, + + EvaluatedToOkModuloOpaqueTypes + | EvaluatedToOk + | EvaluatedToOkModuloRegions + | EvaluatedToAmbig + | EvaluatedToErr => false, + } + } +} + /// Indicates that trait evaluation caused overflow and in which pass. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum OverflowError { |