Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue 20704 - -preview=rvaluerefparam does not work with init as default parameter #12413

Merged
merged 9 commits into from
Apr 12, 2021

Conversation

nordlow
Copy link
Contributor

@nordlow nordlow commented Apr 9, 2021

This PR fixes build errors with defaulted ref parameters in general, not just the ref parameters defaulted to T.init.

@dlang-bot
Copy link
Contributor

Thanks for your pull request and interest in making D better, @nordlow! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Auto-close Bugzilla Severity Description
20704 normal \-preview=rvaluerefparam does not work with init as default parameter

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + dmd#12413"

@thewilsonator
Copy link
Contributor

tests?

@nordlow
Copy link
Contributor Author

nordlow commented Apr 9, 2021

tests?

Done

@thewilsonator thewilsonator changed the title Fix issue 20704 Fix issue 20704 - -preview=rvaluerefparam does not work with init as default parameter Apr 9, 2021
@thewilsonator
Copy link
Contributor

please include the description of the issue in the commit message so it shows up in the log

@nordlow
Copy link
Contributor Author

nordlow commented Apr 9, 2021

please include the description of the issue in the commit message so it shows up in the log

In this case the title doesn't quite match what is being corrected. The correction in this PR involves default parameters in general.

@thewilsonator
Copy link
Contributor

In which case the test case should test for more that just T.init

@nordlow
Copy link
Contributor Author

nordlow commented Apr 9, 2021

In which case the test case should test for more that just T.init

Are you satisfied with compilable tests now, @thewilsonator?

Comment on lines 1301 to 1304
if (isRefOrOut && !isAuto &&
!(global.params.previewIn && (fparam.storageClass & STC.in_)))
!(global.params.previewIn && (fparam.storageClass & STC.in_)) &&
!(global.params.rvalueRefParam))
e = e.toLvalue(sc, e);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually could you change this to

if (isRefOrOut && !isAuto &&)
{
     if ((!(global.params.previewIn && (fparam.storageClass & STC.in_))) ||
                 !(global.params.rvalueRefParam))
    {
        e = e.toLvalue(sc, e);
        if (e.op == TOK.error)
          errorSupplimental(e.loc, "use `-preview=in` or `preview=rvaluerefparam`"
    }
}

note || not &&

Copy link
Contributor Author

@nordlow nordlow Apr 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the logic in using || instead of &&. Using || makes my compilable test fail.

Copy link
Contributor Author

@nordlow nordlow Apr 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the condition accordingly with the exception of leaving the above mentioned && unchanged. Along with and updated expected message for fail_compilation.

@thewilsonator
Copy link
Contributor

also cc @Geod24 as this touches -preview=in to double check

@nordlow
Copy link
Contributor Author

nordlow commented Apr 11, 2021

When this is merged what's keeping us from activating -preview=rvaluerefparam by default?

@thewilsonator
Copy link
Contributor

Note you will also have to update the error messages in

- fail_compilation/fail7603a.d
- fail_compilation/fail7603b.d
- fail_compilation/fail7603c.d
- fail_compilation/fail9773.d
- fail_compilation/fail9891.d
- ```

@nordlow
Copy link
Contributor Author

nordlow commented Apr 11, 2021

Note you will also have to update the error messages in

- fail_compilation/fail7603a.d
- fail_compilation/fail7603b.d
- fail_compilation/fail7603c.d
- fail_compilation/fail9773.d
- fail_compilation/fail9891.d
- ```

Thanks. Done.

@nordlow
Copy link
Contributor Author

nordlow commented Apr 11, 2021

Are we satisfied with error message struct and class types being

`S(0)` is not an lvalue and cannot be modified
`null` is not an lvalue and cannot be modified

respectively?

If so, ok to modify error message

cannot modify constant `0`

to

`0` is not an lvalue and cannot be modified

?

If we do this I believe we should modify all other messages beginning with "cannot modify aswell for consistency. I'm not sure whether that's a good idea or not. Maybe the message needs to be adjusted just in the context of being passed as a default value to a const ref parameter.

@Geod24
Copy link
Member

Geod24 commented Apr 12, 2021

When this is merged what's keeping us from activating -preview=rvaluerefparam by default?

Probably the fact that the DIP was rejected. IMO this switch should be removed but ALAS @TurkeyMan uses it.

Comment on lines +1307 to +1308
if (e.op == TOK.error)
errorSupplemental(e.loc, "use `-preview=in` or `preview=rvaluerefparam`");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think we should recommend those -preview switch as neither have been approved by our BDFLs.

Copy link
Contributor Author

@nordlow nordlow Apr 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok with me to remove it. What's the DIP-number for it? And why was this added to dmd if it was rejected? Is there a plan for a substitute DIP?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather leave this in.

https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1016.md

reject because

void fun(ref int x);
fun(10);

which is disallowed by the current implementation. The current implementation was done because @TurkeyMan quite rightly complained that the review process was not good and that there is utility in the feature.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thewilsonator : I would appreciate if you gave me the time to reply to this. Whether or not you or someone else feels the review process wasn't good doesn't change the fact that the BDFLs decision have been expressed clearly and this is somewhat going against it.

And regarding -preview=in, as much as I want to recommend it to people I will not do it through the compiler as long as we haven't reached a consensus on it.

Copy link
Contributor Author

@nordlow nordlow Apr 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the problem the fact that mutable references also can be passed rvalues? Like in

struct S {}

void e(const ref int x) {}
void f(ref int x) {}
void fS(ref S x) {}
void g(const ref shared long x) {}

unittest {
    e(10); // ok
    f(10); // ok with -preview=rvaluerefparam, error otherwise
    fS(S()); // ok with -preview=rvaluerefparam, error otherwise
    g(10L); // always error
}

. Why not, for now, disallow a mutable reference parameter from being passed an r-value? C++ does this; for instance

void f(int& x) { x = 3; }
int main() { f(3); }

fails as

<stdin>:2:16: error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’
<stdin>:1:13: note:   initializing argument 1 of ‘void f(int&)’

Ping, @Geod24

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nordlow : I submitted #12425
As I explain there, we shouldn't recommend preview any switches which were completely broken until last release, nor should we start recommending switches for which there is no clear plan.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. It doesn't seem to be that difficult to adjust the corrnercases for -refvaluerefparam and make it activate by default. This is such a cornercase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants