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.rs78
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 {