What's the difference between DIP25 and DIP1000?
Jonathan M Davis
newsgroup.d at jmdavisprog.com
Tue Jun 18 21:57:32 UTC 2019
On Tuesday, June 18, 2019 8:53:31 AM MDT Emmanuelle via Digitalmars-d-learn
wrote:
> Hi, I've been reading about DIP25 and DIP1000 and I'm not quite
> sure if I understand the difference between the two—is DIP1000
> supposed to be a rework of DIP25? And what's the difference
> between `return ref` and `return scope`? Also, will there be any
> compiler version where `-preview=dip25` and/or `-preview=dip1000`
> are the default?
>
> Thanks!
DIP 25 only has to do with making returning ref safe. The basic problem is
something like
ref int foo()
{
int i;
return bar(i);
}
ref int bar(ref int i)
{
return i;
}
When foo returns, it ends up returning a ref to a local variable that then
doesn't exist. That's caught with simpler code such as
ref int foo()
{
int i;
return i;
}
but by passing it to a function like bar, the compiler can no longer see
that what's being returned is a ref of a local variable. And what bar is
doing would be perfectly legitimate if it were given something other than a
local variable or if foo didn't return bar's result. So, DIP 25 was
introduced to fix the problem.
Basically, what DIP 25 does is require that any function that accepts a ref
and returns that same ref needs to have the ref parameter marked with
return. That way, when the compiler is compiling a function like foo, it can
see whether bar is returning a ref to the ref parameter or not and thus
whether it's safe to return the result of bar from foo. DIP 25 only deals
with this one issue and has no effect on the type system. It just allows the
compiler to detect whether a function returns a ref parameter.
DIP 1000, on the other hand, actually affects the type system. When scope is
put on a variable, it's actually part of its type, and scope variables are
not allowed to have any references to them escape, meaning that once
something is scope, it can pretty much only be passed to something else that
takes it as scope. That can apply to ref parameters, but it can also apply
to pointers, class references, dynamic arrays, etc. So, it's much more
general than what DIP 25 is trying to do. Something like
ref int* foo()
{
auto ptr = new int(42);
return bar(ptr);
}
ref int* bar(return ref int* ptr)
{
return ptr;
}
int* baz = foo();
would be perfectly legal with DIP 25, whereas with DIP 1000, something like
scope ref int* foo()
{
auto ptr = new int(42);
return bar(ptr);
}
scope ref int* bar(return scope ref int* ptr)
{
return ptr;
}
int* baz = foo();
wouldn't be. Unfortunately, actually understanding all of the ins and outs
of DIP 1000 is pretty complicated, and I haven't spent enough time with it,
so I probably can't explain it well enough. But it covers a _lot_ more than
DIP 25, and IIRC, DIP 1000 depends on DIP 25.
As for when either of them will become the default? I have no clue. -dip25
has been around for years and AFAIK gets used very little, whereas -dip1000
is quite new. Historically, we've done a poor job of switching to new
behavior like this when it breaks existing code, and the change usually
simply doesn't happen. IIRC, Walter intends to try to make it so that code
compiled with -dip1000 and code compiled without it are compatible (so that
people can actually start using -dip1000 and still have their code interact
with code that doesn't use it) and work towards making -dip1000 the default
behavior, but I wouldn't expect such a change to happen soon. However,
Walter is behind this strongly enough that I expect that it will
_eventually_ become the default behavior.
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list