[revived] Make std.typecons.Rebindable work with structs#6136
[revived] Make std.typecons.Rebindable work with structs#6136wilzbach wants to merge 8 commits intodlang:masterfrom
Conversation
|
Thanks for your pull request, @wilzbach! Bugzilla referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub fetch digger
dub run digger -- build "master + phobos#6136" |
static if (!is(S == immutable))
private ref S Rebindable_getRef() @property
{
// payload exposed as const ref when S is const
return trustedPayload;
}
static if (is(S == immutable))
private S Rebindable_get() @property
{
// we return a copy for immutable S
return trustedPayload;
}Could you explain why this is necessary? |
|
Note that I just revived this PR from the dead because I think it's useful - I'm not the original author (@ntrel is). However, from what I understand, the problem without the However, if the Maybe @ntrel can explain this better? |
|
|
||
| /// ditto | ||
| Rebindable!S rebindable(S)(S s) | ||
| if (is(S == struct) && !isInstanceOf!(Rebindable, S)) |
There was a problem hiding this comment.
If S is already Rebindable!struct this can just return s.
There was a problem hiding this comment.
There's already the existing overload Rebindable!T rebindable(T)(Rebindable!T obj) - though they should probably be unified/combined into overload, but that's something that will increase the diff and thus I would prefer to do at the end or in a quick follow-up.
| * temporary copy of `S` in order to enforce _true immutability. | ||
| */ | ||
| template Rebindable(S) | ||
| if (is(S == struct)) |
There was a problem hiding this comment.
By that same token, what if S is already a Rebindable?
| void emplace(ref S s) | ||
| { | ||
| import std.conv : emplace; | ||
| static if (__traits(compiles, () @safe {S tmp = s;})) |
There was a problem hiding this comment.
Why not check S's constructor directly for @safe/@trusted?
There was a problem hiding this comment.
import std.traits;
struct Test
{
this(Test other) @safe {}
}
void main()
{
pragma(msg, isSafe!(__traits(getMember, Test, "__ctor")));
}
https://run.dlang.io/is/hgusNS
Note that isSafe returns true if an @safe or @trusted constructor exists, so even if the type in question has an @system constructor, this will work. It will only return false in the case that you can't safely construct an S from another S.
std/typecons.d
Outdated
| // mutPayload's pointers must be treated as tail const | ||
| void[S.sizeof] mutPayload; | ||
|
|
||
| void emplace(ref S s) |
There was a problem hiding this comment.
What do you think about renaming this emplacePayload, or something similar?
std/typecons.d
Outdated
|
|
||
| static if (!is(S == immutable)) | ||
| ref S Rebindable_getRef() @property | ||
| private ref S Rebindable_getRef() @property |
There was a problem hiding this comment.
You can't use private for an alias this symbol, because it won't be accessible outside this module. Ditto below.
std/typecons.d
Outdated
| static if (is(S == immutable)) | ||
| private S Rebindable_get() @property | ||
| { | ||
| // we return a copy for immutable S |
There was a problem hiding this comment.
However, if the getRef code is used for immutable, no temporary variable would be created and thus resulting in i.e. the postblit not being called
I phrased my question unclearly. Why is this necessary when S == immutable if it's not necessary when S == const?
|
Honestly, my reaction is that this really doesn't make sense. The whole point of |
|
@jmdavis Here's the motivation for this pull: T maxElement(R, T = typeof(R.init.front))(R r)
{
Rebindable!T max = r.front;
foreach (e; r.dropOne)
if (e > max)
max = e;
return max;
}Suppose The idea is that with this pull as a prerequisite, we can make |
|
@wilzbach I made a pull to improve the doc wording & fix private alias this getters: wilzbach#14 |
Yep, funnily enough I even have a PR to fix |
|
@n8sh Escaping a |
|
I've discovered an immutable violation: struct S
{
immutable int i;
}
Rebindable!(const S) r = const S(1);
immutable int* p = &r.i;
r = S(5);
assert(*p == 1); //failsI have a fix ready, just need to finish the tests and docs. For structs with head immutable fields, we require |
See wilzbach#15 |
Otherwise alias this would not work outside std.typecons.
Wording was backward: `const S = S` is fine, `S = const S` disallowed.
Example of previous failing code:
struct S
{
immutable int i;
}
Rebindable!(const S) r = const S(1);
immutable int* p = &r.i;
r = S(5);
assert(*p == 1); //fails
|
I came here to review it and hopefully move this along, but given that the CI was red at the time maybe a new PR? |
Revival of #4363
CC @ntrel
I think only the
opAssignproblem needs to be resolved, apart from that it looks good.