Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CannotProve solution #45

Merged
merged 3 commits into from
Jun 13, 2017
Merged

Conversation

scalexm
Copy link
Member

@scalexm scalexm commented Jun 13, 2017

Added a CannotProve solution in order to deal with #44. In particular, unifying a for all variable with something else automatically leads to CannotProve (or error). CannotProve solutions have the lowest priority when combining multiple solutions.

Examples 1 and 2 in this issue are now all treated as CannotProve. Example 3 is not shown in this PR since this specific issue arises only when elaborating clauses à la #12, but this PR will indeed resolve this ambiguity in the future.

/// Record that a goal has been processed that can neither be proved nor
/// refuted, and thus the overall solution cannot be `Unique`
ambiguous: bool,
cannot_prove: bool,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: comment would be good

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I'm changing that.

}
};

if ambiguous {
debug!("ambiguous result: {:?}", obligation);
obligations.push(obligation);
}

// If one of the obligations cannot be proven, then the whole goal
// cannot be proven either.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make sure I understand: We don't stop immediately here because if we were to encounter a hard error somewhere else, that would "override" this cannot prove result, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah exactly. I'm adding a bit of documentation here too. Notice that for the same reason, in the case where the unification set cannot_prove = true, we don't return CannotProve early here:
https://github.com/scalexm/chalk/blob/cannot-prove/src/solve/solver.rs#L214

@@ -346,7 +346,12 @@ impl<'s> Fulfill<'s> {
/// the outcome of type inference by updating the replacements it provides.
pub fn solve(mut self, subst: Substitution) -> Result<Solution> {
let outcome = self.fulfill()?;
if outcome.is_complete() && !self.ambiguous {

if self.cannot_prove {
Copy link
Contributor

@nikomatsakis nikomatsakis Jun 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having a cannot_prove field, can we use a local variable in fulfill() and extend the Outcome enum? In that case, I think we would replace these two ifs with something like:

match outcome {
    Outcome::CannotProve => return Ok(Solution::CannotProve),
    Outcome::Complete => {
        // No obligations remain, so we have definitively solved our goals,
        ...
        return ...; // as before
    }
    Outcome::Incomplete => { /* fallthrough to figure out some good suggestions */ }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see that in this case unify would have to return Outcome (or UnifyOutcome). This way is ok too. It feels a bit less direct to me somehow, but maybe some comments would suffice to clear it up.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes and moreover unify is called outside of Fulfill (see previous comment) so unify would still have to change an internal state somehow, so I thought that a flag was lighter.

Copy link
Contributor

@nikomatsakis nikomatsakis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good! I think we could add some docs, but otherwise it's good.

@nikomatsakis nikomatsakis merged commit 759034a into rust-lang:master Jun 13, 2017
@scalexm scalexm deleted the cannot-prove branch June 14, 2017 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants