let rec select_right_split (candidates: candidates) : selected option =
  
  match candidates.cd_right_splits with
    | [] ->
        None
            
    | ((candidate, split_literal, index, context_literals) as right_split) :: tail ->
        (* remove the right split *)
        candidates.cd_right_splits <- tail;
        
        (* drop invalidated right splits *)
        if
          Tools.array_exists
            (fun literal -> Context.element_for_literal candidates.cd_context literal = None)
            context_literals
        then begin
          select_right_split candidates
        end

        (* apply this right split *)
        else begin
          (* ignore if not necessary, i.e. effect already achieved by lemma propagation. *)
          match Context.check_contradictory candidates.cd_context split_literal with
            | Some _ ->
                select_right_split candidates
              
            | None ->

          (* keep the right split for later? *)
          begin
            if Array.length context_literals = 0 then
              (* incomplete branch - arbitrary backtracking,
                 no actual right split learned.
                 apply this right split once for completeness and then forget about it. *)

              ()
                    
            else
              (* move the right split to the applied right splits *)
              candidates.cd_applied_right_splits <-
                (right_split, State.active_choice_point candidates.cd_state) :: candidates.cd_applied_right_splits;
          end;

          (* we always do the right split.
             conceptually, its effect could have already been carried out
             some other assert on a lemma.
             but we enforce doing right splits before lemma propagation.
             the reason is that it is possible to ignore negative assert candidates.
             but then, if lemma propagation is done first,
             the right split could be inconsistent with the context
             when it is finally selected.
             for simplifying the resulting conflict analysis (or avoiding a new special case)
             enforcing eager right splits is the easiest way. *)

          let right_split =
            Term.request_negated_literal (Term.request_skolemized_literal split_literal)
          in
            (*check_right_split_consistent candidates right_split;*)

                  match Context.check_contradictory candidates.cd_context right_split with
              | Some element ->
                  let input_partner =
                    Context_unifier.create_input_partner
                      0
                      right_split
                      [] (* don't care about variables *)
                  in
                  let universal =
                    Term.request_universal_literal right_split
                  in
                  let vars =
                    List.map
                      (fun var ->
                         Subst.make_var var Subst.input_literal_offset
                      )
                      (Term.vars_of_literal universal)
                  in
                  let space =
                    Context_unifier.create_space
                      (Context_unifier_space.get_id candidates.cd_space_registry)
                      (* need to be universal, otherwise learning generalized lemmas
                         will compute parameterized lemmas as well. *)

                      [universal]
                      vars
                      vars
                      vars
                      [| input_partner |]
                      [| |] (* don't care about ordering *)
                      (fun _ -> ()) (* no close candidates computed *)
                      (fun _ -> false(* no assert candidates computed *)
                      (fun _ -> ()) (* no split candidates computed *)
                      (fun _ -> false(* not used in recomputation of candidates *)
                      (fun _ -> false(* not used in recomputation of candidates *)
                      true          (* this is said to be a lemma *)
                  in
                  let context_partner =
                    Context_unifier.create_context_partner
                      element
                      None
                      true
                  in
                  let context_unifier =
                    Context_unifier.create_context_unifier
                      space
                      [| context_partner |]
                      false
                  in
                    raise (Context_unifier.CLOSE context_unifier)
                   
                  

              | None ->            
          let context_unifier =
            Context_unifier.recompute_full_unifier ~recompute:false candidate.ca_raw_context_unifier
          in
            State.apply_split_right
              candidates.cd_state
              right_split
              context_unifier
              candidate.ca_raw_context_unifier.Context_unifier.rcu_space.Context_unifier.cus_clause
              candidate.ca_raw_context_unifier.Context_unifier.rcu_space.Context_unifier.cus_vars
              index
              (Context_unifier.create_space_utility_inc candidate.ca_raw_context_unifier.Context_unifier.rcu_space)
              context_literals;
                      
            Some
              {
                Selection_types.candidate_type = (*Selection_types*)State.SplitRight;
                Selection_types.literal = right_split;
                Selection_types.raw_context_unifier = candidate.ca_raw_context_unifier;
              }
        end