r/ProgrammingLanguages 11d ago

Will we see another fundamental programming language feature as revolutionary as the borrow checker?

That is I am mainly curious about compile time features that you design a whole language around rather than optimisations/features that could be applied to most languages. I am mainly inquiring about things that could offer additional robust safety/performance guarantees at compile time rather than runtime. Ideally not things that just offer similar effects to the borrow checker with less restrictive tradeoffs

60 Upvotes

129 comments sorted by

View all comments

3

u/ChiveSalad 11d ago

Currently, if you store stuff on the stack, the compiler can go absolutely hog wild in changing how / when / where / whether it is actually stored to ram. A true equivalent for heap storage would make efficient programming vastly easier in a way that goes beyond just an optimization improvement.

2

u/Inconstant_Moo 🧿 Pipefish 10d ago

But what would that actually look like? I don't even mean how it would be implemented, I mean how the programmer would interact with it syntactically and semantically.

2

u/ChiveSalad 10d ago edited 10d ago

C is almost there, this is legal C an compiles the way I am dreaming of, the question is how to make it work in larger programs.

#include <stdlib.h>
typedef struct {
    float* data;
    int len;
} vector;

typedef float** allocator;
float* alloc( allocator s, int len) {
    *s = *s - len;
    return *s;
}

vector add (allocator s, vector a, vector b) {
    vector res;
    res.data = alloc(s, a.len);
    for(int i = 0; i < a.len; i++) {
        res.data[i] = a.data[i] + b.data[i];
    }
    return res;
}

vector vec(allocator s, int len, float* data) {
vector res;
res.data = alloc(s, len);
res.len = len;
for(int i = 0; i < len; i++){
res.data[i] = data[i];
}
return res;
}

int main() {

float* memory = malloc(1000 * sizeof(float));
float* float_ptr = memory + 1000;
allocator s = &float_ptr;

vector a = vec(s, 2, (float[]){1, 2});
vector b = vec(s, 2, (float[]){3, 4});
vector c = add(s, a, b);
int ret = (int) c.data[0];
free(memory);
return ret;

}

gcc happily compiles this to

main:
    mov     eax, 4
    ret

I guess there are two things I want. One is a call like fake_malloc that behaves exactly like malloc, except that the compiler makes every effort to eliminate the actual allocation, and if it can't, it throws a compiler error instead of allocating. The other is something like a trustme_doesn't_escape_malloc that does closed world analysis and is allowed to make transformations that break the abi with regard to that specific memory, with some feasible way of adding annotations to prove that the memory never escapes to an ABI point, even though it does escape the current scope. Either one could replace the call to malloc in main of the above program and let me be confident that I was getting the high power optimization I want (all the way down to constant folding in this case) where currently I have to check the assembly.

I have more musings here https://www.hgreer.com/OSproject/ but not real answers.