Bug 20706 – `-preview=rvaluerefparam` does not work with copy constructor (and should do NRVO)

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2020-03-29T10:24:58Z
Last change time
2021-01-28T12:28:44Z
Keywords
industry
Assigned to
No Owner
Creator
Mathias LANG

Comments

Comment #0 by pro.mathias.lang — 2020-03-29T10:24:58Z
Consider the following code: ``` struct Foo { int a; @disable this(this); this(int a_) { this.a = a_; } this(const ref typeof(this) other) { this.a = other.a + 1; } } void bar (T) (const ref T arg) { assert(arg.a == 42); } void main () { bar!Foo(Foo(41)); } ``` This will trigger the following error message (DMD 2.091): ``` % dmd -preview=rvaluerefparam autoref.d autoref.d(13): Error: function autoref.bar!(Foo).bar(ref const(Foo) arg) is not callable using argument types (Foo) autoref.d(13): cannot pass rvalue argument Foo(0).this(42) of type Foo to parameter ref const(Foo) arg ``` This has many problems: 1) The error message is bad, because it doesn't explain why it's not possible (namely, because the postblit is disabled) 2) A copy constructor should always have priority over a postblit. If a copy constructor is present and the postblit disabled, the copy constructor should be called. Commenting out disabled postblit declaration will trigger the assert, because the copy ctor is indeed not called. 3) We should not need to have a copy here. What's the point of rvalue ref if it does a copy indiscriminately ?
Comment #1 by razvan.nitu1305 — 2021-01-28T12:28:44Z
PR [1] has fixed this. On git HEAD the original example filed now compiles and triggers the assert (i.e. the copy constructor is not called). Closing as fixed. [1] https://github.com/dlang/dmd/pull/12140