fn abstract_negative_literal<I: Context>(
        &mut self,
        infer: &mut dyn InferenceTable<C, I>,
        subgoal: &I::GoalInEnvironment,
    ) -> Option<C::CanonicalGoalInEnvironment> {
        // First, we have to check that the selected negative literal
        // is ground, and invert any universally quantified variables.
        //
        // DIVERGENCE -- In the RR paper, to ensure completeness, they
        // permit non-ground negative literals, but only consider
        // them to succeed when the target table has no answers at
        // all. This is equivalent inverting those free existentials
        // into universals, as discussed in the comments of
        // `invert`. This is clearly *sound*, but the completeness is
        // a subtle point. In particular, it can cause **us** to reach
        // false conclusions, because e.g. given a program like
        // (selected left-to-right):
        //
        //     not { ?T: Copy }, ?T = Vec<u32>
        //
        // we would select `not { ?T: Copy }` first. For this goal to
        // succeed we would require that -- effectively -- `forall<T>
        // { not { T: Copy } }`, which clearly doesn't hold. (In the
        // terms of RR, we would require that the table for `?T: Copy`
        // has failed before we can continue.)
        //
        // In the RR paper, this is acceptable because they assume all
        // of their input programs are both **normal** (negative
        // literals are selected after positive ones) and **safe**
        // (all free variables in negative literals occur in positive
        // literals). It is plausible for us to guarantee "normal"
        // form, we can reorder clauses as we need. I suspect we can
        // guarantee safety too, but I have to think about it.
        //
        // For now, we opt for the safer route of terming such
        // executions as floundering, because I think our use of
        // negative goals is sufficiently limited we can get away with
        // it. The practical effect is that we will judge more
        // executions as floundering than we ought to (i.e., where we
        // could instead generate an (imprecise) result). As you can
        // see a bit later, we also diverge in some other aspects that
        // affect completeness when it comes to subgoal abstraction.
        let inverted_subgoal = infer.invert_goal(subgoal)?;

        // DIVERGENCE
        //
        // If the negative subgoal has grown so large that we would have
        // to truncate it, we currently just abort the computation
        // entirely. This is not necessary -- the SA paper makes no
        // such distinction, for example, and applies truncation equally
        // for positive/negative literals. However, there are some complications
        // that arise that I do not wish to deal with right now.
        //
        // Let's work through an example to show you what I
        // mean. Imagine we have this (negative) selected literal;
        // hence `selected_subgoal` will just be the inner part:
        //
        //     // not { Vec<Vec<Vec<Vec<i32>>>>: Sized }
        //     //       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        //     //       `selected_goal`
        //
        // (In this case, the `inverted_subgoal` would be the same,
        // since there are no free universal variables.)
        //
        // If truncation **doesn't apply**, we would go and lookup the
        // table for the selected goal (`Vec<Vec<..>>: Sized`) and see
        // whether it has any answers. If it does, and they are
        // definite, then this negative literal is false. We don't
        // really care even how many answers there are and so forth
        // (if the goal is ground, as in this case, there can be at
        // most one definite answer, but if there are universals, then
        // the inverted goal would have variables; even so, a single
        // definite answer suffices to show that the `not { .. }` goal
        // is false).
        //
        // Truncation muddies the water, because the table may
        // generate answers that are not relevant to our original,
        // untracted literal.  Suppose that we truncate the selected
        // goal to:
        //
        //     // Vec<Vec<T>: Sized
        //
        // Clearly this table will have some solutions that don't
        // apply to us.  e.g., `Vec<Vec<u32>>: Sized` is a solution to
        // this table, but that doesn't imply that `not {
        // Vec<Vec<Vec<..>>>: Sized }` is false.
        //
        // This can be made to work -- we carry along the original
        // selected goal when we establish links between tables, and
        // we could use that to screen the resulting answers. (There
        // are some further complications around the fact that
        // selected goal may contain universally quantified free
        // variables that have been inverted, as discussed in the
        // prior paragraph above.) I just didn't feel like dealing
        // with it yet.
        match infer.truncate_goal(&inverted_subgoal) {
            Some(_) => None,
            None => Some(infer.canonicalize_goal(&inverted_subgoal)),
        }
    }
/// Given a selected negative subgoal, the subgoal is "inverted"
/// (see `InferenceTable<C, I>::invert`) and then potentially truncated
/// (see `abstract_positive_literal`). The result subgoal is
/// canonicalized. In some cases, this may return `None` and hence
/// fail to yield a useful result, for example if free existential
/// variables appear in `subgoal` (in which case the execution is
/// said to "flounder").
Given a selected negative subgoal, the subgoal is "inverted"
and then potentially truncated
. The result subgoal is
canonicalized. In some cases, this may return `None` and hence
fail to yield a useful result, for example if free existential
variables appear in `subgoal` (in which case the execution is
said to "flounder").
Given a selected negative subgoal the subgoal is " inverted " and then potentially truncated . The result subgoal is canonicalized . In some cases this may return ` None ` and hence fail to yield a useful result for example if free existential variables appear in ` subgoal ` ( in which case the execution is said to " flounder " ) .
fn abstract_negative_literal<I: Context>(
        &mut self,
        infer: &mut dyn InferenceTable<C, I>,
        subgoal: &I::GoalInEnvironment,
    ) -> Option<C::CanonicalGoalInEnvironment> {
        // First, we have to check that the selected negative literal
        // is ground, and invert any universally quantified variables.
        //
        // DIVERGENCE -- In the RR paper, to ensure completeness, they
        // permit non-ground negative literals, but only consider
        // them to succeed when the target table has no answers at
        // all. This is equivalent inverting those free existentials
        // into universals, as discussed in the comments of
        // `invert`. This is clearly *sound*, but the completeness is
        // a subtle point. In particular, it can cause **us** to reach
        // false conclusions, because e.g. given a program like
        // (selected left-to-right):
        //
        //     not { ?T: Copy }, ?T = Vec<u32>
        //
        // we would select `not { ?T: Copy }` first. For this goal to
        // succeed we would require that -- effectively -- `forall<T>
        // { not { T: Copy } }`, which clearly doesn't hold. (In the
        // terms of RR, we would require that the table for `?T: Copy`
        // has failed before we can continue.)
        //
        // In the RR paper, this is acceptable because they assume all
        // of their input programs are both **normal** (negative
        // literals are selected after positive ones) and **safe**
        // (all free variables in negative literals occur in positive
        // literals). It is plausible for us to guarantee "normal"
        // form, we can reorder clauses as we need. I suspect we can
        // guarantee safety too, but I have to think about it.
        //
        // For now, we opt for the safer route of terming such
        // executions as floundering, because I think our use of
        // negative goals is sufficiently limited we can get away with
        // it. The practical effect is that we will judge more
        // executions as floundering than we ought to (i.e., where we
        // could instead generate an (imprecise) result). As you can
        // see a bit later, we also diverge in some other aspects that
        // affect completeness when it comes to subgoal abstraction.
        let inverted_subgoal = infer.invert_goal(subgoal)?;
        // DIVERGENCE
        //
        // If the negative subgoal has grown so large that we would have
        // to truncate it, we currently just abort the computation
        // entirely. This is not necessary -- the SA paper makes no
        // such distinction, for example, and applies truncation equally
        // for positive/negative literals. However, there are some complications
        // that arise that I do not wish to deal with right now.
        //
        // Let's work through an example to show you what I
        // mean. Imagine we have this (negative) selected literal;
        // hence `selected_subgoal` will just be the inner part:
        //
        //     // not { Vec<Vec<Vec<Vec<i32>>>>: Sized }
        //     //       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        //     //       `selected_goal`
        //
        // (In this case, the `inverted_subgoal` would be the same,
        // since there are no free universal variables.)
        //
        // If truncation **doesn't apply**, we would go and lookup the
        // table for the selected goal (`Vec<Vec<..>>: Sized`) and see
        // whether it has any answers. If it does, and they are
        // definite, then this negative literal is false. We don't
        // really care even how many answers there are and so forth
        // (if the goal is ground, as in this case, there can be at
        // most one definite answer, but if there are universals, then
        // the inverted goal would have variables; even so, a single
        // definite answer suffices to show that the `not { .. }` goal
        // is false).
        //
        // Truncation muddies the water, because the table may
        // generate answers that are not relevant to our original,
        // untracted literal.  Suppose that we truncate the selected
        // goal to:
        //
        //     // Vec<Vec<T>: Sized
        //
        // Clearly this table will have some solutions that don't
        // apply to us.  e.g., `Vec<Vec<u32>>: Sized` is a solution to
        // this table, but that doesn't imply that `not {
        // Vec<Vec<Vec<..>>>: Sized }` is false.
        //
        // This can be made to work -- we carry along the original
        // selected goal when we establish links between tables, and
        // we could use that to screen the resulting answers. (There
        // are some further complications around the fact that
        // selected goal may contain universally quantified free
        // variables that have been inverted, as discussed in the
        // prior paragraph above.) I just didn't feel like dealing
        // with it yet.
        match infer.truncate_goal(&inverted_subgoal) {
            Some(_) => None,
            None => Some(infer.canonicalize_goal(&inverted_subgoal)),
        }
    }
fn abstract_negative_literal < I : Context > ( & mut self , infer : & mut dyn InferenceTable < C , I > , subgoal : & I :: GoalInEnvironment , ) -> Option < C :: CanonicalGoalInEnvironment > { // First, we have to check that the selected negative literal // is ground, and invert any universally quantified variables. // // DIVERGENCE -- In the RR paper, to ensure completeness, they // permit non-ground negative literals, but only consider // them to succeed when the target table has no answers at // all. This is equivalent inverting those free existentials // into universals, as discussed in the comments of // `invert`. This is clearly *sound*, but the completeness is // a subtle point. In particular, it can cause **us** to reach // false conclusions, because e.g. given a program like // (selected left-to-right): // //     not { ?T: Copy }, ?T = Vec<u32> // // we would select `not { ?T: Copy }` first. For this goal to // succeed we would require that -- effectively -- `forall<T> // { not { T: Copy } }`, which clearly doesn't hold. (In the // terms of RR, we would require that the table for `?T: Copy` // has failed before we can continue.) // // In the RR paper, this is acceptable because they assume all // of their input programs are both **normal** (negative // literals are selected after positive ones) and **safe** // (all free variables in negative literals occur in positive // literals). It is plausible for us to guarantee "normal" // form, we can reorder clauses as we need. I suspect we can // guarantee safety too, but I have to think about it. // // For now, we opt for the safer route of terming such // executions as floundering, because I think our use of // negative goals is sufficiently limited we can get away with // it. The practical effect is that we will judge more // executions as floundering than we ought to (i.e., where we // could instead generate an (imprecise) result). As you can // see a bit later, we also diverge in some other aspects that // affect completeness when it comes to subgoal abstraction. let inverted_subgoal = infer . invert_goal ( subgoal ) ? ; // DIVERGENCE // // If the negative subgoal has grown so large that we would have // to truncate it, we currently just abort the computation // entirely. This is not necessary -- the SA paper makes no // such distinction, for example, and applies truncation equally // for positive/negative literals. However, there are some complications // that arise that I do not wish to deal with right now. // // Let's work through an example to show you what I // mean. Imagine we have this (negative) selected literal; // hence `selected_subgoal` will just be the inner part: // //     // not { Vec<Vec<Vec<Vec<i32>>>>: Sized } //     //       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //     //       `selected_goal` // // (In this case, the `inverted_subgoal` would be the same, // since there are no free universal variables.) // // If truncation **doesn't apply**, we would go and lookup the // table for the selected goal (`Vec<Vec<..>>: Sized`) and see // whether it has any answers. If it does, and they are // definite, then this negative literal is false. We don't // really care even how many answers there are and so forth // (if the goal is ground, as in this case, there can be at // most one definite answer, but if there are universals, then // the inverted goal would have variables; even so, a single // definite answer suffices to show that the `not { .. }` goal // is false). // // Truncation muddies the water, because the table may // generate answers that are not relevant to our original, // untracted literal.  Suppose that we truncate the selected // goal to: // //     // Vec<Vec<T>: Sized // // Clearly this table will have some solutions that don't // apply to us.  e.g., `Vec<Vec<u32>>: Sized` is a solution to // this table, but that doesn't imply that `not { // Vec<Vec<Vec<..>>>: Sized }` is false. // // This can be made to work -- we carry along the original // selected goal when we establish links between tables, and // we could use that to screen the resulting answers. (There // are some further complications around the fact that // selected goal may contain universally quantified free // variables that have been inverted, as discussed in the // prior paragraph above.) I just didn't feel like dealing // with it yet. match infer . truncate_goal ( & inverted_subgoal ) { Some ( _ ) => None , None => Some ( infer . canonicalize_goal ( & inverted_subgoal ) ) , } }
Given a selected negative subgoal, the subgoal is "inverted"
(see `InferenceTable<C, I>::invert`) and then potentially truncated
(see `abstract_positive_literal`).
Given a selected negative subgoal the subgoal is " inverted " ( see ` InferenceTable<C I > :: invert ` ) and then potentially truncated ( see ` abstract_positive_literal ` ) .
&mut self
infer
&mut dyn InferenceTable<C, I>
subgoal
&I::GoalInEnvironment
&mut self
infer
&mut dyn InferenceTable<C, I>
subgoal
&I::GoalInEnvironment