let merge_fun_callers get_list get_value merge is_top acc proj kf =
  if is_top acc then acc
  else begin
    let acc = ref acc in
    let table = ref VarinfoSet.empty in
      try
        let merge m =
          acc := merge m !acc ;
          if is_top !acc then
            raise StopMerging (* acceleration when top is reached *)
        in
        let rec merge_fun_callers kf =
          let merge_fun_caller (kf,_) = merge_fun_callers kf in
          let vf = Kernel_function.get_vi kf in
            if VarinfoSet.mem vf !table
            then () (* no way to add something, the [kf] contribution is already accumulated. *)
            else
              begin
                table := VarinfoSet.add vf !table ;
                List.iter (fun x -> merge (get_value x)) (get_list proj kf) ;
                List.iter merge_fun_caller (!Db.Value.callers kf)
              end
        in merge_fun_callers kf ;
          !acc
      with StopMerging -> !acc
  end