Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog/dmd.enable-rvaluerefparam.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Enabled -preview=rvaluerefparam after a long testing period.

You can now supply an rvalue to a ref argument. A temporary will automatically be created for the call.
6 changes: 3 additions & 3 deletions compiler/src/dmd/cli.d
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,9 @@ dmd -cov -unittest myprog.d
"https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md"),
Feature("intpromote", "fix16997", "revert integral promotions for unary + - ~ operators"),
Feature("dtorfields", "dtorFields", "don't destruct fields of partially constructed objects"),
Feature("rvaluerefparam", "rvalueRefParam",
"revert rvalue arguments to ref parameters",
"https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a"),
];

/// Returns all available previews
Expand Down Expand Up @@ -974,9 +977,6 @@ dmd -cov -unittest myprog.d
Feature("dtorfields", "dtorFields",
"destruct fields of partially constructed objects",
"https://dlang.org/changelog/2.098.0.html#dtorfileds", false, false),
Feature("rvaluerefparam", "rvalueRefParam",
"enable rvalue arguments to ref parameters",
"https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a"),
Feature("safer", "safer",
"more safety checks by default",
"https://github.com/WalterBright/documents/blob/38f0a846726b571f8108f6e63e5e217b91421c86/safer.md", true, false),
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dmd/dscope.d
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private struct Previews
this.in_ = params.previewIn;
this.inclusiveInContracts = params.inclusiveInContracts;
this.noSharedAccess = params.noSharedAccess == FeatureState.enabled;
this.rvalueRefParam = params.rvalueRefParam == FeatureState.enabled;
this.rvalueRefParam = params.rvalueRefParam != FeatureState.disabled;
this.safer = params.safer == FeatureState.enabled;
this.systemVariables = params.systemVariables;
this.fieldwise = params.fieldwise == FeatureState.enabled;
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dmd/frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -8507,6 +8507,7 @@ struct Param final
ehnogc(),
useDIP1021(),
fixAliasThis(),
rvalueRefParam((FeatureState)2u),
previewIn(),
inclusiveInContracts(),
shortenedMethods(true),
Expand Down Expand Up @@ -8556,7 +8557,7 @@ struct Param final
timeTraceFile()
{
}
Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting useWarnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState safer = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, CLIIdentifierTable dIdentifierTable = (CLIIdentifierTable)0u, CLIIdentifierTable cIdentifierTable = (CLIIdentifierTable)0u, _d_dynamicArray< const char > argv0 = {}, Array<const char* > modFileAliasStrings = Array<const char* >(), Array<ImportPathInfo > imppath = Array<ImportPathInfo >(), Array<const char* > fileImppath = Array<const char* >(), _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), bool debugEnabled = false, bool run = false, Array<const char* > runargs = Array<const char* >(), Array<const char* > cppswitches = Array<const char* >(), const char* cpp = nullptr, Array<const char* > objfiles = Array<const char* >(), Array<const char* > linkswitches = Array<const char* >(), Array<bool > linkswitchIsForCC = Array<bool >(), Array<const char* > libfiles = Array<const char* >(), Array<const char* > dllfiles = Array<const char* >(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}, bool fullyQualifiedObjectFiles = false, bool timeTrace = false, uint32_t timeTraceGranularityUs = 500u, const char* timeTraceFile = nullptr) :
Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting useWarnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)2u, FeatureState safer = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, CLIIdentifierTable dIdentifierTable = (CLIIdentifierTable)0u, CLIIdentifierTable cIdentifierTable = (CLIIdentifierTable)0u, _d_dynamicArray< const char > argv0 = {}, Array<const char* > modFileAliasStrings = Array<const char* >(), Array<ImportPathInfo > imppath = Array<ImportPathInfo >(), Array<const char* > fileImppath = Array<const char* >(), _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), bool debugEnabled = false, bool run = false, Array<const char* > runargs = Array<const char* >(), Array<const char* > cppswitches = Array<const char* >(), const char* cpp = nullptr, Array<const char* > objfiles = Array<const char* >(), Array<const char* > linkswitches = Array<const char* >(), Array<bool > linkswitchIsForCC = Array<bool >(), Array<const char* > libfiles = Array<const char* >(), Array<const char* > dllfiles = Array<const char* >(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}, bool fullyQualifiedObjectFiles = false, bool timeTrace = false, uint32_t timeTraceGranularityUs = 500u, const char* timeTraceFile = nullptr) :
obj(obj),
multiobj(multiobj),
trace(trace),
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dmd/globals.d
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ extern (C++) struct Param
bool useDIP1021; // implement https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md
FeatureState fieldwise; // do struct equality testing field-wise rather than by memcmp()
bool fixAliasThis; // if the current scope has an alias this, check it before searching upper scopes
FeatureState rvalueRefParam; // allow rvalues to be arguments to ref parameters
FeatureState rvalueRefParam = FeatureState.enabled; // allow rvalues to be arguments to ref parameters
// https://dconf.org/2019/talks/alexandrescu.html
// https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
// https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html
Expand Down
5 changes: 3 additions & 2 deletions compiler/src/dmd/typesem.d
Original file line number Diff line number Diff line change
Expand Up @@ -2335,8 +2335,9 @@ Type typeSemantic(Type type, Loc loc, Scope* sc)

// default arg must be an lvalue
if (isRefOrOut && !isAuto &&
!(fparam.storageClass & STC.constscoperef) && !sc.previews.rvalueRefParam)
e = e.toLvalue(sc, "create default argument for `ref` / `out` parameter from");
!(fparam.storageClass & STC.constscoperef) &&
(!sc.previews.rvalueRefParam || (fparam.storageClass & STC.out_)))
e = e.toLvalue(sc, (global.params.rvalueRefParam != FeatureState.disabled) ? "create default argument for `out` parameter from" : "create default argument for `ref` / `out` parameter from");

fparam.defaultArg = e;
return (e.op != EXP.error);
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/compilable/fix21647.d
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
REQUIRED_ARGS: -preview=rvaluerefparam
REQUIRED_ARGS:
TEST_OUTPUT:
---
cast(void)0
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/compilable/issue20704.d
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
https://issues.dlang.org/show_bug.cgi?id=20704
REQUIRED_ARGS: -preview=rvaluerefparam
REQUIRED_ARGS:
*/

void f1(T)(const auto ref T arg = T.init) {}
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/compilable/issue20705.d
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// REQUIRED_ARGS: -preview=rvaluerefparam
// REQUIRED_ARGS:
struct Foo
{
int[] a;
Expand Down
1 change: 0 additions & 1 deletion compiler/test/compilable/previewhelp.d
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ Upcoming language changes listed by -preview=name:
=bitfields add C-like bitfields (https://github.com/dlang/dlang.org/pull/3190)
=fieldwise use fieldwise comparisons for struct equality (https://dlang.org/changelog/2.085.0.html#no-cmpsb)
=fixAliasThis when a symbol is resolved, check alias this scope before going to upper scopes (https://github.com/dlang/dmd/pull/8885)
=rvaluerefparam enable rvalue arguments to ref parameters (https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a)
=safer more safety checks by default (https://github.com/WalterBright/documents/blob/38f0a846726b571f8108f6e63e5e217b91421c86/safer.md)
=nosharedaccess disable access to shared memory objects (https://dlang.org/spec/const3.html#shared)
=in `in` on parameters means `scope const [ref]` and accepts rvalues (https://dlang.org/spec/function.html#in-params)
Expand Down
1 change: 1 addition & 0 deletions compiler/test/compilable/reverthelp.d
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ Revertable language changes listed by -revert=name:
=dip1000 revert DIP1000 changes (Scoped Pointers) (https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1000.md)
=intpromote revert integral promotions for unary + - ~ operators
=dtorfields don't destruct fields of partially constructed objects
=rvaluerefparam revert rvalue arguments to ref parameters (https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a)
----
*/
2 changes: 1 addition & 1 deletion compiler/test/compilable/rvalue2.d
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* PERMUTE_ARGS: -preview=rvaluerefparam
/* PERMUTE_ARGS: -revert=rvaluerefparam
*/

struct S
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/compilable/rvalueref.d
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* REQUIRED_ARGS: -preview=rvaluerefparam
/* REQUIRED_ARGS:
*/

struct AS
Expand Down
4 changes: 4 additions & 0 deletions compiler/test/compilable/test18216.d
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// TODO: hack, make this test work with rvaluerefparam. With ref parameters, opAssign generation triggers:
// compilable/test18216.d(17): Error: struct `test18216.Node` no size because of forward reference
//
// REQUIRED_ARGS: -revert=rvaluerefparam
// https://issues.dlang.org/show_bug.cgi?id=18216

struct Node
Expand Down
20 changes: 7 additions & 13 deletions compiler/test/fail_compilation/b20011.d
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
/*
TEST_OUTPUT:
---
fail_compilation/b20011.d(28): Error: cannot modify expression `S1(cast(ubyte)0u).member` because it is not an lvalue
fail_compilation/b20011.d(31): Error: cannot modify expression `S2(null).member` because it is not an lvalue
fail_compilation/b20011.d(32): Error: cannot modify expression `S2(null).member` because it is not an lvalue
fail_compilation/b20011.d(35): Error: cannot modify expression `U1(cast(ubyte)0u, ).m2` because it is not an lvalue
fail_compilation/b20011.d(40): Error: function `assignableByRef` is not callable using argument types `(ubyte)`
fail_compilation/b20011.d(40): cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `ref ubyte p`
fail_compilation/b20011.d(37): `b20011.main.assignableByRef(ref ubyte p)` declared here
fail_compilation/b20011.d(41): Error: function `assignableByOut` is not callable using argument types `(ubyte)`
fail_compilation/b20011.d(41): cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `out ubyte p`
fail_compilation/b20011.d(38): `b20011.main.assignableByOut(out ubyte p)` declared here
fail_compilation/b20011.d(42): Error: function `assignableByConstRef` is not callable using argument types `(ubyte)`
fail_compilation/b20011.d(42): cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `ref const(ubyte) p`
fail_compilation/b20011.d(39): `b20011.main.assignableByConstRef(ref const(ubyte) p)` declared here
fail_compilation/b20011.d(22): Error: cannot modify expression `S1(cast(ubyte)0u).member` because it is not an lvalue
fail_compilation/b20011.d(25): Error: cannot modify expression `S2(null).member` because it is not an lvalue
fail_compilation/b20011.d(26): Error: cannot modify expression `S2(null).member` because it is not an lvalue
fail_compilation/b20011.d(29): Error: cannot modify expression `U1(cast(ubyte)0u, ).m2` because it is not an lvalue
fail_compilation/b20011.d(35): Error: function `assignableByOut` is not callable using argument types `(ubyte)`
fail_compilation/b20011.d(35): cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `out ubyte p`
fail_compilation/b20011.d(32): `b20011.main.assignableByOut(out ubyte p)` declared here
---
*/
module b20011;
Expand Down
4 changes: 1 addition & 3 deletions compiler/test/fail_compilation/fail20183.d
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* REQUIRED_ARGS: -preview=dip1000
TEST_OUTPUT:
---
fail_compilation/fail20183.d(1016): Error: function `addr` is not callable using argument types `(int)`
fail_compilation/fail20183.d(1016): cannot pass rvalue argument `S(0).i` of type `int` to parameter `return ref int b`
fail_compilation/fail20183.d(1004): `fail20183.addr(return ref int b)` declared here
fail_compilation/fail20183.d(1016): Error: assigning address of variable `__rvalue2` to `p` with longer lifetime is not allowed in a `@safe` function
---
*/

Expand Down
7 changes: 0 additions & 7 deletions compiler/test/fail_compilation/fail7603a.d

This file was deleted.

2 changes: 1 addition & 1 deletion compiler/test/fail_compilation/fail7603b.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail7603b.d(7): Error: cannot create default argument for `ref` / `out` parameter from constant `true`
fail_compilation/fail7603b.d(7): Error: cannot create default argument for `out` parameter from constant `true`
---
*/
void test(out bool val = true) { }
8 changes: 0 additions & 8 deletions compiler/test/fail_compilation/fail7603c.d

This file was deleted.

10 changes: 0 additions & 10 deletions compiler/test/fail_compilation/fail9773.d

This file was deleted.

10 changes: 2 additions & 8 deletions compiler/test/fail_compilation/fail9891.d
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail9891.d(13): Error: expression `i` of type `immutable(int)` is not implicitly convertible to type `ref int` of parameter `n`
fail_compilation/fail9891.d(18): Error: expression `i` of type `immutable(int)` is not implicitly convertible to type `out int` of parameter `n`
fail_compilation/fail9891.d(23): Error: cannot create default argument for `ref` / `out` parameter from expression `prop()` because it is not an lvalue
fail_compilation/fail9891.d(12): Error: expression `i` of type `immutable(int)` is not implicitly convertible to type `ref int` of parameter `n`
fail_compilation/fail9891.d(17): Error: expression `i` of type `immutable(int)` is not implicitly convertible to type `out int` of parameter `n`
---
*/

Expand All @@ -19,8 +18,3 @@ void f2(out int n = i)
{
++n;
}

void f3(ref int n = prop)
{
++n;
}
39 changes: 0 additions & 39 deletions compiler/test/fail_compilation/issue20704.d

This file was deleted.

30 changes: 0 additions & 30 deletions compiler/test/fail_compilation/test21807.d
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,3 @@ class Foo
ca = getSArray();
}
}

/*
TEST_OUTPUT:
---
fail_compilation/test21807.d(117): Error: function `addr` is not callable using argument types `(int)`
fail_compilation/test21807.d(117): cannot pass rvalue argument `S(0).i` of type `int` to parameter `return ref int b`
fail_compilation/test21807.d(106): `test21807.addr(return ref int b)` declared here
---
*/
#line 100

struct S
{
int i;
}

int* addr(return ref int b)
{
return &b;
}

class Foo2
{
int* ptr;

this()
{
ptr = addr(S().i); // struct temporary
}
}
Loading
Loading