1 use crate::search_graph
::DepthFirstNumber
;
2 use chalk_ir
::interner
::Interner
;
4 Canonical
, ConstrainedSubst
, Constraints
, Goal
, InEnvironment
, Substitution
, UCanonical
,
9 pub type UCanonicalGoal
<I
> = UCanonical
<InEnvironment
<Goal
<I
>>>;
18 pub use recursive
::RecursiveSolver
;
20 /// The `minimums` struct is used while solving to track whether we encountered
21 /// any cycles in the process.
22 #[derive(Copy, Clone, Debug)]
23 pub(crate) struct Minimums
{
24 pub(crate) positive
: DepthFirstNumber
,
28 pub fn new() -> Self {
30 positive
: DepthFirstNumber
::MAX
,
34 pub fn update_from(&mut self, minimums
: Minimums
) {
35 self.positive
= ::std
::cmp
::min(self.positive
, minimums
.positive
);
39 /// A (possible) solution for a proposed goal.
40 #[derive(Clone, Debug, PartialEq, Eq)]
41 pub enum Solution
<I
: Interner
> {
42 /// The goal indeed holds, and there is a unique value for all existential
43 /// variables. In this case, we also record a set of lifetime constraints
44 /// which must also hold for the goal to be valid.
45 Unique(Canonical
<ConstrainedSubst
<I
>>),
47 /// The goal may be provable in multiple ways, but regardless we may have some guidance
48 /// for type inference. In this case, we don't return any lifetime
49 /// constraints, since we have not "committed" to any particular solution
54 /// When a goal holds ambiguously (e.g., because there are multiple possible
55 /// solutions), we issue a set of *guidance* back to type inference.
56 #[derive(Clone, Debug, PartialEq, Eq)]
57 pub enum Guidance
<I
: Interner
> {
58 /// The existential variables *must* have the given values if the goal is
59 /// ever to hold, but that alone isn't enough to guarantee the goal will
61 Definite(Canonical
<Substitution
<I
>>),
63 /// There are multiple plausible values for the existentials, but the ones
64 /// here are suggested as the preferred choice heuristically. These should
65 /// be used for inference fallback only.
66 Suggested(Canonical
<Substitution
<I
>>),
68 /// There's no useful information to feed back to type inference
72 impl<I
: Interner
> Solution
<I
> {
73 /// There are multiple candidate solutions, which may or may not agree on
74 /// the values for existential variables; attempt to combine them. This
75 /// operation does not depend on the order of its arguments.
77 // This actually isn't as precise as it could be, in two ways:
79 // a. It might be that while there are multiple distinct candidates, they
80 // all agree about *some things*. To be maximally precise, we would
81 // compute the intersection of what they agree on. It's not clear though
82 // that this is actually what we want Rust's inference to do, and it's
83 // certainly not what it does today.
85 // b. There might also be an ambiguous candidate and a successful candidate,
86 // both with the same refined-goal. In that case, we could probably claim
87 // success, since if the conditions of the ambiguous candidate were met,
88 // we know the success would apply. Example: `?0: Clone` yields ambiguous
89 // candidate `Option<?0>: Clone` and successful candidate `Option<?0>:
92 // But you get the idea.
93 pub(crate) fn combine(self, other
: Solution
<I
>, interner
: &I
) -> Solution
<I
> {
94 use self::Guidance
::*;
101 "combine {} with {}",
102 self.display(interner
),
103 other
.display(interner
)
106 // Otherwise, always downgrade to Ambig:
108 let guidance
= match (self.into_guidance(), other
.into_guidance()) {
109 (Definite(ref subst1
), Definite(ref subst2
)) if subst1
== subst2
=> {
110 Definite(subst1
.clone())
112 (Suggested(ref subst1
), Suggested(ref subst2
)) if subst1
== subst2
=> {
113 Suggested(subst1
.clone())
117 Solution
::Ambig(guidance
)
120 /// View this solution purely in terms of type inference guidance
121 pub(crate) fn into_guidance(self) -> Guidance
<I
> {
123 Solution
::Unique(constrained
) => Guidance
::Definite(Canonical
{
124 value
: constrained
.value
.subst
,
125 binders
: constrained
.binders
,
127 Solution
::Ambig(guidance
) => guidance
,
131 /// Extract a constrained substitution from this solution, even if ambiguous.
132 pub(crate) fn constrained_subst(&self, interner
: &I
) -> Option
<Canonical
<ConstrainedSubst
<I
>>> {
134 Solution
::Unique(ref constrained
) => Some(constrained
.clone()),
135 Solution
::Ambig(Guidance
::Definite(ref canonical
))
136 | Solution
::Ambig(Guidance
::Suggested(ref canonical
)) => {
137 let value
= ConstrainedSubst
{
138 subst
: canonical
.value
.clone(),
139 constraints
: Constraints
::empty(interner
),
143 binders
: canonical
.binders
.clone(),
146 Solution
::Ambig(_
) => None
,
150 /// Determine whether this solution contains type information that *must*
151 /// hold, and returns the subst in that case.
152 pub(crate) fn definite_subst(&self, interner
: &I
) -> Option
<Canonical
<ConstrainedSubst
<I
>>> {
154 Solution
::Unique(constrained
) => Some(constrained
.clone()),
155 Solution
::Ambig(Guidance
::Definite(canonical
)) => {
156 let value
= ConstrainedSubst
{
157 subst
: canonical
.value
.clone(),
158 constraints
: Constraints
::empty(interner
),
162 binders
: canonical
.binders
.clone(),
169 pub fn is_unique(&self) -> bool
{
171 Solution
::Unique(..) => true,
176 pub(crate) fn is_ambig(&self) -> bool
{
178 Solution
::Ambig(_
) => true,
183 pub fn display
<'a
>(&'a
self, interner
: &'a I
) -> SolutionDisplay
<'a
, I
> {
191 pub struct SolutionDisplay
<'a
, I
: Interner
> {
192 solution
: &'a Solution
<I
>,
196 impl<'a
, I
: Interner
> fmt
::Display
for SolutionDisplay
<'a
, I
> {
197 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> Result
<(), fmt
::Error
> {
198 let SolutionDisplay { solution, interner }
= self;
200 Solution
::Unique(constrained
) => write
!(f
, "Unique; {}", constrained
.display(interner
)),
201 Solution
::Ambig(Guidance
::Definite(subst
)) => write
!(
203 "Ambiguous; definite substitution {}",
204 subst
.display(interner
)
206 Solution
::Ambig(Guidance
::Suggested(subst
)) => write
!(
208 "Ambiguous; suggested substitution {}",
209 subst
.display(interner
)
211 Solution
::Ambig(Guidance
::Unknown
) => write
!(f
, "Ambiguous; no inference guidance"),