fn positive(
        &mut self,
        goal_depth: StackIndex,
        ex_clause: ExClause,
        selected_goal: InEnvironment<Goal>,
        minimums: &mut Minimums,
    ) -> ExplorationResult {
        debug_heading!(
            "positive(goal_depth={:?}, ex_clause={:?}, selected_goal={:?}, minimums={:?})",
            goal_depth,
            self.infer.normalize_deep(&ex_clause),
            selected_goal,
            minimums
        );

        // Subgoal abstraction: Rather than looking up the table for
        // `selected_goal` directly, first apply the truncation
        // function. This may introduce fresh variables, making the
        // goal that we are looking up more general, and forcing us to
        // reuse an existing table. For example, if we had a selected
        // goal of
        //
        //     // Vec<Vec<Vec<Vec<i32>>>>: Sized
        //
        // we might now produce a truncated goal of
        //
        //     // Vec<Vec<?T>>: Sized
        //
        // Obviously, the answer we are looking for -- if it exists -- will be
        // found amongst the answers of this new, truncated goal.
        //
        // Subtle point: Note that the **selected goal** remains
        // unchanged and will be carried over into the "pending
        // clause" for the positive link on the new subgoal. This
        // means that if our new, truncated subgoal produces
        // irrelevant answers (e.g., `Vec<Vec<u32>>: Sized`), they
        // will fail to unify with our selected goal, producing no
        // resolvent.
        let universe = selected_goal.environment.universe;
        let Truncated {
            overflow: _,
            value: truncated_subgoal,
        } = truncate(&mut self.infer, universe, self.max_size, &selected_goal);

        // Check if we need to create a new table and (if so) stop.
        let subgoal_table = match self.select_goal(
            goal_depth,
            Sign::Positive,
            &ex_clause,
            &selected_goal,
            truncated_subgoal,
            minimums,
        )? {
            Some(t) => t,
            None => return Ok(FullyExplored),
        };

        let pending_ex_clause = self.pending_ex_clause(goal_depth, &ex_clause, &selected_goal);

        // A table for this entry already exists. We want to take
        // whatever answers we can find in the table -- bearing in
        // mind that the table may still be in the process of being
        // evaluated!
        if let Some(subgoal_depth) = self.tables[subgoal_table].depth {
            // If the table is not completely evaluated, then there is
            // a cycle.  We'll still use whatever answers have been
            // found so far, but we'll also register ourselves to
            // receive any new answers that will come later.
            self.tables[subgoal_table].positives.push(pending_ex_clause.clone());
            self.update_lookup(goal_depth, subgoal_depth, Sign::Positive, minimums);
        }

        // Process the answers that have already been found one by
        // one.
        let new_ex_clauses: Vec<_> = {
            let infer = &mut self.infer;
            let subgoal_table_goal = &self.tables[subgoal_table].table_goal;
            self.tables[subgoal_table]
                .answers
                .iter()
                .filter_map(|(answer_subst, answer_delayed_literals)| {
                    // This is a bit subtle: when we incorporate the
                    // cached answer, we always use the
                    // `pending_ex_clause` as the starting point
                    // rather than `ex_clause`. This is because the
                    // pending ex-clause is canonicalized, and hence
                    // we wind up generating fresh copies of all the
                    // inference variables involved. In the case where
                    // there is more than one pending answer, this is
                    // important, because otherwise we can wind up
                    // "cross-contaminating" between answers here.
                    //
                    // Imagine that our ex-clause is `?T: Sour`, and
                    // we have two tabled answers `Lemon: Sour` and
                    // `Vingear: Sour` (this scenario btw is tested by
                    // `cached_answers1` and friends). When we
                    // incorporate the first cached answer, we wind up
                    // unifying `?T` with `Lemon` -- but we just store
                    // that in a vector, we don't immediately do anything with it.
                    //
                    // Then we try to incorporate the next cached answer,
                    // `Vinegar` -- but now we already have `?T = Lemon` as a constraint,
                    // so that (incorrectly) fails.
                    //
                    // There are other ways to fix this:
                    //
                    // - We might clone the answer set and then use
                    //   snapshots as we process each cached
                    //   answer. This is effectively what happens when
                    //   handling program clauses, except that in that
                    //   case no clone is needed, because the program
                    //   clauses are not stored in a structure that is
                    //   being updated during computation (unlike the
                    //   answer set).
                    //
                    // - We might alternatively clone our inference
                    //   table for each cached answer, so that `?T`
                    //   has distinct bindings on the different
                    //   paths. We would need to move `infer` from a
                    //   field to a parameter then.
                    //
                    // In both cases, we could incorporate persistent
                    // data structures to make those clones cheaper.
                    Self::incorporate_cached_answer(
                        infer,
                        &pending_ex_clause,
                        subgoal_table,
                        subgoal_table_goal,
                        answer_subst,
                        answer_delayed_literals,
                    ).yes()
                })
                .collect()
        };

        for (new_goal_depth, new_ex_clause) in new_ex_clauses {
            assert_eq!(new_goal_depth, goal_depth);
            let new_ex_clause = self.truncate_returned(goal_depth, new_ex_clause);
            self.new_clause(goal_depth, new_ex_clause, minimums)?;
        }

        Ok(FullyExplored)
    }
/// Try to solve a positive selected literal.
Try to solve a positive selected literal.
Try to solve a positive selected literal .
fn positive(
        &mut self,
        goal_depth: StackIndex,
        ex_clause: ExClause,
        selected_goal: InEnvironment<Goal>,
        minimums: &mut Minimums,
    ) -> ExplorationResult {
        debug_heading!(
            "positive(goal_depth={:?}, ex_clause={:?}, selected_goal={:?}, minimums={:?})",
            goal_depth,
            self.infer.normalize_deep(&ex_clause),
            selected_goal,
            minimums
        );
        // Subgoal abstraction: Rather than looking up the table for
        // `selected_goal` directly, first apply the truncation
        // function. This may introduce fresh variables, making the
        // goal that we are looking up more general, and forcing us to
        // reuse an existing table. For example, if we had a selected
        // goal of
        //
        //     // Vec<Vec<Vec<Vec<i32>>>>: Sized
        //
        // we might now produce a truncated goal of
        //
        //     // Vec<Vec<?T>>: Sized
        //
        // Obviously, the answer we are looking for -- if it exists -- will be
        // found amongst the answers of this new, truncated goal.
        //
        // Subtle point: Note that the **selected goal** remains
        // unchanged and will be carried over into the "pending
        // clause" for the positive link on the new subgoal. This
        // means that if our new, truncated subgoal produces
        // irrelevant answers (e.g., `Vec<Vec<u32>>: Sized`), they
        // will fail to unify with our selected goal, producing no
        // resolvent.
        let universe = selected_goal.environment.universe;
        let Truncated {
            overflow: _,
            value: truncated_subgoal,
        } = truncate(&mut self.infer, universe, self.max_size, &selected_goal);
        // Check if we need to create a new table and (if so) stop.
        let subgoal_table = match self.select_goal(
            goal_depth,
            Sign::Positive,
            &ex_clause,
            &selected_goal,
            truncated_subgoal,
            minimums,
        )? {
            Some(t) => t,
            None => return Ok(FullyExplored),
        };
        let pending_ex_clause = self.pending_ex_clause(goal_depth, &ex_clause, &selected_goal);
        // A table for this entry already exists. We want to take
        // whatever answers we can find in the table -- bearing in
        // mind that the table may still be in the process of being
        // evaluated!
        if let Some(subgoal_depth) = self.tables[subgoal_table].depth {
            // If the table is not completely evaluated, then there is
            // a cycle.  We'll still use whatever answers have been
            // found so far, but we'll also register ourselves to
            // receive any new answers that will come later.
            self.tables[subgoal_table].positives.push(pending_ex_clause.clone());
            self.update_lookup(goal_depth, subgoal_depth, Sign::Positive, minimums);
        }
        // Process the answers that have already been found one by
        // one.
        let new_ex_clauses: Vec<_> = {
            let infer = &mut self.infer;
            let subgoal_table_goal = &self.tables[subgoal_table].table_goal;
            self.tables[subgoal_table]
                .answers
                .iter()
                .filter_map(|(answer_subst, answer_delayed_literals)| {
                    // This is a bit subtle: when we incorporate the
                    // cached answer, we always use the
                    // `pending_ex_clause` as the starting point
                    // rather than `ex_clause`. This is because the
                    // pending ex-clause is canonicalized, and hence
                    // we wind up generating fresh copies of all the
                    // inference variables involved. In the case where
                    // there is more than one pending answer, this is
                    // important, because otherwise we can wind up
                    // "cross-contaminating" between answers here.
                    //
                    // Imagine that our ex-clause is `?T: Sour`, and
                    // we have two tabled answers `Lemon: Sour` and
                    // `Vingear: Sour` (this scenario btw is tested by
                    // `cached_answers1` and friends). When we
                    // incorporate the first cached answer, we wind up
                    // unifying `?T` with `Lemon` -- but we just store
                    // that in a vector, we don't immediately do anything with it.
                    //
                    // Then we try to incorporate the next cached answer,
                    // `Vinegar` -- but now we already have `?T = Lemon` as a constraint,
                    // so that (incorrectly) fails.
                    //
                    // There are other ways to fix this:
                    //
                    // - We might clone the answer set and then use
                    //   snapshots as we process each cached
                    //   answer. This is effectively what happens when
                    //   handling program clauses, except that in that
                    //   case no clone is needed, because the program
                    //   clauses are not stored in a structure that is
                    //   being updated during computation (unlike the
                    //   answer set).
                    //
                    // - We might alternatively clone our inference
                    //   table for each cached answer, so that `?T`
                    //   has distinct bindings on the different
                    //   paths. We would need to move `infer` from a
                    //   field to a parameter then.
                    //
                    // In both cases, we could incorporate persistent
                    // data structures to make those clones cheaper.
                    Self::incorporate_cached_answer(
                        infer,
                        &pending_ex_clause,
                        subgoal_table,
                        subgoal_table_goal,
                        answer_subst,
                        answer_delayed_literals,
                    ).yes()
                })
                .collect()
        };
        for (new_goal_depth, new_ex_clause) in new_ex_clauses {
            assert_eq!(new_goal_depth, goal_depth);
            let new_ex_clause = self.truncate_returned(goal_depth, new_ex_clause);
            self.new_clause(goal_depth, new_ex_clause, minimums)?;
        }
        Ok(FullyExplored)
    }
fn positive ( & mut self , goal_depth : StackIndex , ex_clause : ExClause , selected_goal : InEnvironment < Goal > , minimums : & mut Minimums , ) -> ExplorationResult { debug_heading ! ( " " goal_depth self infer normalize_deep ( ex_clause ) selected_goal minimums ) ; // Subgoal abstraction: Rather than looking up the table for // `selected_goal` directly, first apply the truncation // function. This may introduce fresh variables, making the // goal that we are looking up more general, and forcing us to // reuse an existing table. For example, if we had a selected // goal of // //     // Vec<Vec<Vec<Vec<i32>>>>: Sized // // we might now produce a truncated goal of // //     // Vec<Vec<?T>>: Sized // // Obviously, the answer we are looking for -- if it exists -- will be // found amongst the answers of this new, truncated goal. // // Subtle point: Note that the **selected goal** remains // unchanged and will be carried over into the "pending // clause" for the positive link on the new subgoal. This // means that if our new, truncated subgoal produces // irrelevant answers (e.g., `Vec<Vec<u32>>: Sized`), they // will fail to unify with our selected goal, producing no // resolvent. let universe = selected_goal . environment . universe ; let Truncated { overflow : _ , value : truncated_subgoal , } = truncate ( & mut self . infer , universe , self . max_size , & selected_goal ) ; // Check if we need to create a new table and (if so) stop. let subgoal_table = match self . select_goal ( goal_depth , Sign :: Positive , & ex_clause , & selected_goal , truncated_subgoal , minimums , ) ? { Some ( t ) => t , None => return Ok ( FullyExplored ) , } ; let pending_ex_clause = self . pending_ex_clause ( goal_depth , & ex_clause , & selected_goal ) ; // A table for this entry already exists. We want to take // whatever answers we can find in the table -- bearing in // mind that the table may still be in the process of being // evaluated! if let Some ( subgoal_depth ) = self . tables [ subgoal_table ] . depth { // If the table is not completely evaluated, then there is // a cycle.  We'll still use whatever answers have been // found so far, but we'll also register ourselves to // receive any new answers that will come later. self . tables [ subgoal_table ] . positives . push ( pending_ex_clause . clone ( ) ) ; self . update_lookup ( goal_depth , subgoal_depth , Sign :: Positive , minimums ) ; } // Process the answers that have already been found one by // one. let new_ex_clauses : Vec < _ > = { let infer = & mut self . infer ; let subgoal_table_goal = & self . tables [ subgoal_table ] . table_goal ; self . tables [ subgoal_table ] . answers . iter ( ) . filter_map ( | ( answer_subst , answer_delayed_literals ) | { // This is a bit subtle: when we incorporate the // cached answer, we always use the // `pending_ex_clause` as the starting point // rather than `ex_clause`. This is because the // pending ex-clause is canonicalized, and hence // we wind up generating fresh copies of all the // inference variables involved. In the case where // there is more than one pending answer, this is // important, because otherwise we can wind up // "cross-contaminating" between answers here. // // Imagine that our ex-clause is `?T: Sour`, and // we have two tabled answers `Lemon: Sour` and // `Vingear: Sour` (this scenario btw is tested by // `cached_answers1` and friends). When we // incorporate the first cached answer, we wind up // unifying `?T` with `Lemon` -- but we just store // that in a vector, we don't immediately do anything with it. // // Then we try to incorporate the next cached answer, // `Vinegar` -- but now we already have `?T = Lemon` as a constraint, // so that (incorrectly) fails. // // There are other ways to fix this: // // - We might clone the answer set and then use //   snapshots as we process each cached //   answer. This is effectively what happens when //   handling program clauses, except that in that //   case no clone is needed, because the program //   clauses are not stored in a structure that is //   being updated during computation (unlike the //   answer set). // // - We might alternatively clone our inference //   table for each cached answer, so that `?T` //   has distinct bindings on the different //   paths. We would need to move `infer` from a //   field to a parameter then. // // In both cases, we could incorporate persistent // data structures to make those clones cheaper. Self :: incorporate_cached_answer ( infer , & pending_ex_clause , subgoal_table , subgoal_table_goal , answer_subst , answer_delayed_literals , ) . yes ( ) } ) . collect ( ) } ; for ( new_goal_depth , new_ex_clause ) in new_ex_clauses { assert_eq ! ( new_goal_depth goal_depth ) ; let new_ex_clause = self . truncate_returned ( goal_depth , new_ex_clause ) ; self . new_clause ( goal_depth , new_ex_clause , minimums ) ? ; } Ok ( FullyExplored ) }
Try to solve a positive selected literal.
Try to solve a positive selected literal .
&mut self
goal_depth
StackIndex
ex_clause
ExClause
selected_goal
InEnvironment<Goal>
minimums
&mut Minimums