The missing bit in DIP1000
Ola Fosheim Grøstad
ola.fosheim.grostad at gmail.com
Thu Jun 23 08:56:49 UTC 2022
There are some reflections to be had with how DIP1000 changes the
type system. I think this change is coming from not making the
true type system explicit.
Imagine that all types come in two varieties: scope and heap.
When we write
```d
void f(int x){…}
```
the full type would be:
```d
void f(scope(int) x){…}
```
If we now introduce «|» to mean union, so that the union type A
and type B becomes «A|B» then we can think that when we write
```d
int* p;
```
the full type would be:
```d
(scope(int)|heap(int)|null)* p;
```
So in the context of DIP1000, when we write:
```d
void f(int x){
int* p = null;
if (condition) p = &x;
g(p);
if (condition) p = null;
else p = new int(5);
g(p)
}
```
the full typing ought to be:
```d
void f(scope(int) x){
(scope(int)|heap(int)|null)* p=null; // *p narrowed to: null
if (condition) p = &x; // *p widened to:
scope(int)|null
g(p); // called as
g((scope(int)|null)*)
if (condition) p = null;
else p = new int(5); // *p becomes: heap(int)|null
g(p); // called as
g((heap(int)|null)*)
}
```
This is basic flow typing and not too difficult to understand, it
is also more versatile than DIP1000 as it can be used for
tracking other things (like nullable).
The current scheme of only narrowing, but never widening is
overly pessimistic, most likely confusing and difficult to
explain/justify to newcomers.
More information about the Digitalmars-d
mailing list