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

Should the compiler be able to infer implied operations? #17200

Open
mppf opened this issue Feb 19, 2021 · 4 comments
Open

Should the compiler be able to infer implied operations? #17200

mppf opened this issue Feb 19, 2021 · 4 comments

Comments

@mppf
Copy link
Member

mppf commented Feb 19, 2021

This issue is a spin-off from issue #15838.

We have an idea that conversions between types come in 4 levels and a programmer should be able to access any of these 4 levels, but the higher levels imply the lower ones.

  • level 4 (implicit conversion) implies 3,2,1 (assign, initialize, cast)
  • level 3 (assign) implies 2,1 (initialize, cast)
  • level 2 (initialize) implies 1 (cast)
  • level 1 (cast) doesn't imply any of the others

Additionally even for the same type, we have the property that assign implies that an init= is available (because some of the assigns will convert to initialization according to split init).

PR #17092 makes it a compilation error to have an init= function with a different RHS type unless there is also a cast function. PR #14956 made it an error to have an assignment function without a corresponding = function (or vice versa).

We made these cases into compilation errors partly under the argument that inferring any implied operations from the operations provided would not be a breaking change.

Should we relax one or more of these cases?

In particular:

  • the compiler could use init= to implement cast between types
  • the compiler could use default-init/assign to implement init=

It would also be possible for the compiler to infer assign from init= (by deiniting the LHS and then moving in the result of init=). This case is slightly different though because it would not be an error according to the above rules to have init= but not assign and in fact we expect that such a behavior is useful in some cases (possibly with sync variables).

@bradcray
Copy link
Member

My overarching philosophy on this question is that it would be nice for the compiler to help with such cases if it felt sufficiently like a "no brainer". Where I think the criteria for no-brainer are: (1) there isn't any significant overhead or downside introduced via the compiler-provided rewrite; (2) it doesn't increase the confusion for the type author or user; (3) it helps relieve pain on the type author's part by preventing them from thinking "Oh man, I can't believe I'm stamping out this pattern again to achieve all 4 tiers of conversions."

For me, the init= to implement cast case feels like it should satisfy these. I'm less certain about the default-init/assign case and init=, wondering whether it runs afoul of (a) (not as efficient as a user-written init= would likely be?) and/or (b) (would it catch anyone off-guard that it was available / having this behavior?).

@mppf
Copy link
Member Author

mppf commented Feb 22, 2021

thanks @bradcray . I'm just noting here that @bradcray and @lydia-duncan expressed support for automatically using init= to implement cast in one of the issues this is a spin-off from - #16732 (comment) - #16732 (comment) .

@e-kayrakli
Copy link
Contributor

the compiler could use default-init/assign to implement init=

This part came up in the List module review meeting in trying to answer Michael's design question here: https://github.com/Cray/chapel-private/issues/1451

Currently we can write both var l = new list(otherList) and var l: list = otherList, because we have a copy initializer and an initializer that takes a list argument. While the list design can be discussed elsewhere, it'd be nice if the compiler could infer init= in this case. And the list design could be an interesting data point in driving this discussion.

@mppf
Copy link
Member Author

mppf commented Aug 23, 2021

Currently we can write both var l = new list(otherList) and var l: list = otherList, because we have a copy initializer and an initializer that takes a list argument. While the list design can be discussed elsewhere, it'd be nice if the compiler could infer init= in this case. And the list design could be an interesting data point in driving this discussion.

Issue #17199 discusses how we might like to not have to write both proc init and proc init= in these cases. I'll add a link to the above comment there.

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

No branches or pull requests

3 participants