Function pointer to function that returns function pointer

I'm writing a simple text-based "choose your own adventure" game. Initially I had code like this:

    fn page1() {
        if player_chooses_to_go_west {
        } else {
    fn page2() { todo!() }
    fn page3() { todo!() }
    fn main() { page1(); }

but this is no good, since the call stack will grow indefinitely as the game progresses.

Next attempt is to have the current state of the game represented by a function pointer, and each function returns the next function pointer - like so:

    fn page1() -> fn() -> fn() {
        if player_chooses_to_go_left {
        } else {

    fn page2() -> fn() -> fn() { todo!() }
    fn page3() -> fn() -> fn() { todo!() }
    fn main() {
        let mut f = page1;
        loop {
            f = f();

This feels workable, except that I can't get the right return types for the functions. They just grow forever - fn(), fn() -> fn(), fn() -> fn() -> fn(), etc.!
(Changing to boxed closures doesn't help - the same problem emerges.)
It feels like this approach should work, since each function is ultimately just returning a thin pointer. But perhaps the type system won't allow it.
Is there a way that this approach can work?

For future reference, I got it working like the code below. It's ugly but it gets the job done. :slight_smile:

use std::any::Any;

fn page1() -> Box<dyn Any> {
    let player_chooses_to_go_left = true;
    let boxed_f: Box<fn() -> Box<dyn Any>> = if player_chooses_to_go_left {
    } else {

fn page2() -> Box<dyn Any> { todo!() }
fn page3() -> Box<dyn Any> { todo!() }

fn main() {
    let mut f: Box<fn() -> Box<dyn Any>> = Box::new(page1);
    loop {
        let next_f = f();
        f = next_f.downcast().unwrap();

Don't know that it's the best design, but anyway:


I'm not the best Rust expert here, but wouldn't this be a case where making use of closures and trait bounds make more sense ? Something like this (please correct my code if you notice a mistake):

fn page<T>() -> &T
    T: Fn() -> &T,
{// TODO...}

(would something like that even compile ?)

That said, I don't exactly understand your design decision. What is the incentive to represent your pages as function pointers ? Correct me if I am wrong, but doesn't a Choose-Your-Own-Adventure game/visual novel work just like a state machine ? Wouldn't it be easier to implement your pages as the different cases of an Enum or with Structs and using functions to transition between pages (states) ?

A minimal change to fix the original code is to introduce a type for the functions returned:

struct Page(fn() -> Page);

fn start() -> Page {

fn page1() -> Page {
    Page(if goes_left() { page2 } else { page3 })

This is a general solution (in many programming languages, even) to an infinitely recursive type: adding a nominal type makes it workable, because recursive data structures are a feature in almost any language that has data structures, so the compiler has to support them, and adding a function instead of a direct value doesn't especially complicate the matter.


I like this, basically in each iteration of loop calling the same function but its actually just a renamed different function

The current simple design (functions returning function pointers) is almost certainly not what I'll end up with. I know it's going to get much more complicated - most likely the pages will be stored externally, for example. I just wanted to see if it could work.

TIL you can use Self in a recursive struct definition o.O

(I thought Self was for impl blocks only… well, and trait definitions, too…)


RFC 2300 stabilized in Rust 1.32... but it just seemed natural to me for whatever reason. [1] Sorta funny, there's a lot of other pre-NLL-or-so habits I haven't kicked.

  1. I thought maybe I picked it up from "too many lists", but a skim suggests not. ↩︎


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.