Field | Value |
---|---|
DIP: | (number/id -- assigned by DIP Manager) |
Review Count: | 0 (edited by DIP Manager) |
Author: | Walter Bright walter@walterbright.com |
Implementation: | (links to implementation PR if any) |
Status: | Will be set by the DIP manager (e.g. "Approved" or "Rejected") |
Enable local variables to be declared as ref
.
- Rationale
- Prior Work
- Description
- Breaking Changes and Deprecations
- Reference
- Copyright & License
- Reviews
Ref declarations are a restricted form of pointer declarations. They are restricted in that:
- they cannot reassigned after initialization
- pointer arithmetic cannot be done on them
- they cannot be copied, other than being used to initialize another ref
Decades of successful use have clearly demonstrated the utility of this form of restricted pointer. Ref declarations are a major tool for writing memory safe code, and self-documenting the restricted use of being a ref rather than a pointer.
Currently, ref declarations are only allowed for:
- function parameters
- function return values
- declaration references to element types in a foreach statement
Of particular interest here is the success of item (3). There doesn't appear to
be a downside of using ref
for such declarations, so by extension ordinary
local variables should also benefit from being declared as ref
. Often I've run
across cases where declaring a local as ref
rather than a pointer would have
made the code nicer and safer.
This DIP is for declaring local variables as ref
. Not globals, statics, externs,
__gshareds or fields.
C++ allows variables to be declared as a reference rather than pointer. The same goes for ref struct field declarations, although that is not part of this proposal.
References in C#: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/declarations#reference-variables
ref
is already allowed in the grammar for variable declarations, it is disallowed
in the semantic pass.
https://dlang.org/spec/declaration.html#VarDeclarations
This proposal will "turn it on" so to speak, and its behavior will be the same as
the current behavior for assigning to function ref parameters.
Returning a ref variable from a function that returns a ref is not allowed. I.e. a ref cannot be assigned to a ref with a scope that exceeds the scope of the source.
ref int dark(ref int x, int i, int* q)
{
ref m = *q; // m refers to whatever q points to
ref j = i; // j now points to i
j = 3; // now i is 3 as well
auto k = j; // k is an int with value 3
auto p = &j; // p is a pointer to i
ref int y = x; // ok
if (i)
return x; // ok
else
return y; // nope
}
An example showing the utility of ref
. This is from the DMD code generator:
void pop87(int line, const(char)* file)
{
if (NDPP)
printf("pop87(%s(%d): stackused=%d)\n", file, line, global87.stackused);
--global87.stackused;
assert(global87.stackused >= 0);
foreach (i; 0 .. global87.stack.length - 1)
global87.stack[i] = global87.stack[i + 1];
// end of stack is nothing
global87.stack[$ - 1] = NDP();
}
becomes:
void pop87(int line, const(char)* file)
{
ref g = global87;
if (NDPP)
printf("pop87(%s(%d): stackused=%d)\n", file, line, g.stackused);
--g.stackused;
assert(g.stackused >= 0);
foreach (i; 0 .. g.stack.length - 1)
g.stack[i] = g.stack[i + 1];
// end of stack is nothing
g.stack[$ - 1] = NDP();
}
which reduces the complexity of the code, as long-winded global names get a shorthand.
C++ rvalue references are not part of this proposal.
No breaking changes are anticipated.
References in D: https://dlang.org/spec/declaration.html#ref-storage
Foreach ref parameters: https://dlang.org/spec/statement.html#foreach_ref_parameters
References in C++: https://en.cppreference.com/w/cpp/language/reference
Copyright (c) 2024 by the D Language Foundation
Licensed under Creative Commons Zero 1.0