Mandatory inlined functions for unsized types and 'super lifetime?

Thinking about this more, the combination of let super variables and the 'super' lifetime does not need inline fn`, as callee-allocated super bindings can be put into a datastructure provided by the callee. Basically, return slot pointers on steroids. Consider the following:

fn foo_or_bar(flag: bool) -> &'super dyn Debug {
    if flag {
        let super foo: Foo = Foo::new();
        &foo
    } else {
        let super bar: Bar = Bar::new();
        &bar
    }
}

We know statically that there are two codepaths that need to allocate variables in the callee stack frame, so we can transform that function into one that takes an enum:

enum Super {
    Uninit,
    Foo(Foo),
    Bar(Bar),
}

fn foo_or_bar<'callee>(flag: bool, mut callee: &'callee mut Super) -> &'callee dyn Debug {
    if flag {
        *callee = Super::Foo(Foo::new());
        if let Super::Foo(foo) = callee {
            foo
        } else {
            unreachable!()
        }
    } else {
        *callee = Super::Bar(Bar::new());
        if let Super::Bar(bar) = callee {
            bar
        } else {
            unreachable!()
        }
    }
}

fn call_foo_or_bar(flag: bool) {
        let mut callee = Super::Uninit;
        let r: &dyn Debug = foo_or_bar(flag, &mut callee);
        dbg!(r);
}

Furthermore, if one 'super returning function calls another 'super returning function, the straightforward thing to do is to combine the scratchpad datastructures together. For example:

fn foo(foo: Foo) -> &'super Foo {
    /* ... */
}

fn bar_or_foo(f: bool) -> &'super dyn Any {
   /* ... */
}

would transform to:

enum FooScratchpad {
    Uninit,
    Foo(Foo),
}

fn foo(foo: Foo, scratchpad: &mut FooScratchpad) -> &'super Foo {
    /* ... */
}


enum BarScratchpad {
    Uninit,
    Bar(Bar),
    Foo(FooScratchpad),
}

fn bar_or_foo(f: bool, scratchpad: &mut BarScratchpad) -> &'super dyn Any {
   /* ... */
}

Scope and Dropping

Again, the simplest approach to scope/drop would be to just forbid types with drop glue from being declared with let super.

In particular, in the nested version of this idea, you could wind up having drop called quite high up the call stack. This may be surprising! It might be better to treat all &'super references as akin to &own, and have the returned reference be responsible for calling drop, with all other variables in scope always dropped prior to the function returning. That way the return value would still reflect 100% of what might be dropped after the function returns.

Unsized Return Values

Without special syntax, this "allocate the maximum possible space needed" approach should also work for unsized return values, with the actual return value being a &own reference. Maybe I'm missing something, but I don't seem to see this approach having been proposed in RFC1909, or the discussion around it.

When you think about it, it'd actually be quite similar to how impl Future and so-on works in case of deeply nested futures.

Object Safety

This technique could even be used with trait methods! Since the above transformation means we know the maximum size of the r-value, we can store that in the vtable and allocate the neccessary space dynamically with alloca!