back

by lerno·1y ago·view on hn ↗
I don't quite see what you mean. As an example, let's say you use ZII and allocate 100 objects in a single allocation. These are now zero initialized and so either invalid (which should not happen) or do not hold non-null types. Can you explain how you intend this scenario to be resolved in your case?

Otherwise it's quite straightforward that they have an uninitialized state (zero) and are then wired up when used. Trying to prevent null pointers here is something that the program to do. However, making the compiler guarantee without requiring constructors it is a challenge I don't know how to tackle.

1 comments
> As an example, let's say you use ZII and allocate 100 objects in a single allocation

If you want to do that you can always use a nullable type. You can always assign it to a non-nullable type after initialization if you plan on using the aggregate a lot.

Usually you provide a vector type though, which has an underlying nullable array, but maintains a fill-index such that for all i < fill-index it the value is initialized, and then you have two indexing operations; one which returns a nullable type and the other which bounds-checks and returns a non-nullable type.

This could make sense for a from-scratch language, but C3 is trying to be an evolution of C, and such constraints would make it so much of a different language that it would be way out of scope.

I think Rust and similar languages fill that niche already, so there is no real need to try to offer that type of alternative.

I think we are miscommunicating. Let's imagine a language called "C@" where the only difference is that "@" is used in place of "*" for a non-nullable pointer type:

  typedef struct {
     foo @*data; //Non-nullable pointer to nullable pointer of foo
     size_t size;
     size_t fill;
  } foo_vec;
  
  void foo_vec_push(foo_vec @v, foo @x) {
    if (v->fill == v->size) {
      //realloc and zero data
    } else {
      data[idx++] = v;
    }
  }
  
  foo @ foo_vec_get(foo_vec @v, size_t idx) {
    if (idx < fill) {
      return (foo @)(data+idx);
    } else {
      abort();
    }
  }
I'm not sure how this constraint makes it "so much of a different language" at all.
In this case, how would you prevent the user from seeing an invalid foo_vec before initialization? This is either "oh, it's in an illegal state", in which case it's just an annotation without deeper enforcement or you need to somehow enforce that a non-null pointer is never seen, am I not right?
1. It's not quite trivial to statically disallow use-before-initialization, but it's definitely a solved problem if you disallow returning uninitialized variables.

2. The other option is to disallow declaration without initialization of non-nullable values. If you can't declare an uninitialized foo_vec, then the user can't ever see an invalid foo_vec.