-
-
Notifications
You must be signed in to change notification settings - Fork 596
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
Issue 9237 - Add isPOD trait #1421
Conversation
Wait don't pull this yet. Those sanity checks should fail to compile instead of returning false, and the trait should only accept one parameter. Re-working.. |
that was fast! |
@WalterBright: Regarding your opAssing comment in the newsgroups -- The isPOD function comment states:
Should I remove the opassign check and remove the requirement from the docstring? |
I'll move the test-cases to |
Please don't merge before the discussion on what a POD type should be is finished – this makes what mostly is an implementation detail user visible, so it would become harder to change. (typing up a NG post right now) |
OK. In the meantime I've moved the test-cases to where they should be, and also I've removed the |
At the moment, I suggest just matching in the test case what the compiler does. Any reengineering if what isPOD does in the compiler is a separate issue. |
@WalterBright: what is the exact definition according to the compiler? |
// sanity checks | ||
static assert(!__traits(compiles, { __traits(isPOD, C_9273); } )); | ||
static assert(!__traits(compiles, { __traits(isPOD, 123); } )); | ||
static assert(!__traits(compiles, { __traits(isPOD, 123, 456); } )); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these sanity checks are done by incorrect way.
{ __traits(isPOD, 123, 456); }
will always fail to compile, because it will report has no effect in expression
error.
Instead, you should write as: static assert(!__traits(compiles, __traits(isPOD, 123, 456) ));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I've needlessly added the { }
and then the compiler complained about lacking ;
, which distracted me from the real issue.
Shouldn't the language dictate what a POD is? C++ defines it in the spec, and the compilers follow the spec. |
@andralex: As far as the compiler is concerned, this is only relevant as part of implementing the System V x86-64 ABI, which is used on most x86_64 Posixen (but notably not on Windows). See page 19 of the 0.99.6 version of the spec (the official x86-64.org site seems to be down) for the requirements. There is a certain fuzziness involved in applying this to D, but I think the current implementation (disallowing constructors) is overly restrictive – see the NG for more. |
@AndrejMitrovic: There isn't really a reason for defining POD in the D spec, as it doesn't influence the lanugage on a semantic level. isPOD is really just used for deciding whether a type is eligible for being passed in registers or not. But nevertheless, yes, the exact rules for when this passing in registers happens should be defined as part of a x86_64 (and Posix) specific "implementation notes" section of the docs. |
@WalterBright: I agree, but it must be clear from the docs that |
goto Lfalse; | ||
} | ||
error("argument %s must be a struct type", o->toChars()); | ||
goto Lfalse; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All non-structs are POD.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought this trait was meant to be used only with a struct because it's the only D type which may or may not be a POD based on its definition, hence why a trait is necessary. For other types the POD check isn't necessary.
But how are all non-struct types PODs? Classes aren't PODs?
Are we implementing an isPOD
trait for structs, or some kind of isPassedViaRegisters
trait? I'm confused at what your definition of a POD is if all non-structs are PODs..
Just a question: |
All non-struct data is implicitly POD, because only structs have functions that must be called for copying, creation, and destruction. Remember, a class is POD because copying the class reference around is always "trivial". Also consider the use of isPOD. As far as I can see, it will always be used in pairs, as in "!isStruct || isPOD" if isPOD only applies to structs. Might as well fix isPOD. Remember, a POD type can be enregistered, if it also fits in registers and the code gen supports it. A non-POD can never be enregistered. A POD type can also be bit copied around at will without regard to needing to call any functions for any part of that. (This means POD can be spilled into registers, cached in registers, stored half in registers and half in memory, etc.) And besides, I want to emphasize here that this pull request has nothing to do with which structs are PODs and which are not. That is a completely separate issue. I don't think that this pull request should be impaired by trying to redesign POD in the language. |
@WalterBright: You are right, the pull request per se doesn't have anything to do with which structs are POD and which structs are not, and the "PODness" of a type is a pretty irrelevant detail of the target ABI. I'm just afraid that this is not clear without appropriate docs (see e.g. the confusion on the NG surrounding the term POD), people might start to depend on it for completely wrong use cases, and then we are stuck with the current behavior because it is no longer an invisible low-level detail. Also, what should isPOD return on x86 or Win64? The same as for x86_64 Posixen? If so, what if for some non-x86 target there is another ABI with different rules for struct parameter passing? |
POD must match the C ABI of the target system. Therefore, it is possible (though I don't currently know of a case and can't think of a reason for one) that the definition of POD may change from one target to the next. |
I'm not sure what you mean by that, the
I understand all of your points now, however there's really nothing to remember here. There is the terminology of PODs which you define verbally, and then there's the D documentation which mentions PODs several times:
How can you expect people not to be confused when the docs use one terminology and you use a different terminology? We better clearly define what a POD is in the documentation before any pulls like this are merged. |
Also see dlang/dlang.org#222, which at least obliterates the quite obviously wrong statement that D structs are always POD. But in any case, the way in which the term POD comes up in the docs illustrates how it is perceived to be a "high-level" concept, whereas |
The definition of POD does not need to be correct in the documentation (I agree that needs work) in order for this to be pulled. There's a need for it right now to fix a regression: http://d.puremagic.com/issues/show_bug.cgi?id=9099 @AndrejMitrovic, I mean no disrespect, that was just a meta comment that I just don't think this pull request needs to be diverted into a discussion of the fine points of what kinds of structs are PODs and what are not. That's an entirely separate discussion. The only relevance here would be the treatment of non-structs, which should all be regarded as POD. Certainly, the test cases you included with the pull would change with a change in the implementation of isPOD(), but that's still irrelevant to the usefulness of this pull and the point of it. |
That was true originally, but D structs have evolved quite a bit since that was written. |
@WalterBright: Updated, non-structs are now PODs. One final question: should I disallow expressions? I take it the trait should only work on types. |
Type *t = isType(o); | ||
StructDeclaration *sd; | ||
if (t && t->toBasetype()->ty == Tstruct | ||
&& ((sd = (StructDeclaration *)(((TypeStruct *)t->toBasetype())->sym)) != NULL)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the !t case, it should return an error saying that a type is expected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean print an error.
@WalterBright: Fixed. |
Issue 9237 - Add isPOD trait
Issue 9237 - Add isPOD trait
Do you have a good wording for how to document this trait on dpl.org? |
The wording should not attempt to define what POD is, it should just say it accepts a type as an argument and returns a boolean based on if it is POD or not. The POD text should be a link to where it is defined. |
Right, but where is it defined? There's a definition in the glossary but it explicitly talks about structs as PODs and nothing else. |
Just link to that for now. Defining a POD is a separate issue from the traits isPOD and the description of isPOD. |
@WalterBright: What about static arrays of non-POD structs? At least for single-element static arrays, this is going to matter with the current DMD ABI implementation, and when/if you implement your plans of treating static arrays like structs, it will also in the general case. |
Discussion on what a POD is should go into dlang/dlang.org#229 |
@WalterBright: This is not a discussion about what a POD type is, but about the trait implementation – as far as I can see, it is inconsistent with what the argtypes machinery does. |
The argtype implementation relies on isPOD, so it is completely consistent. And, to answer your question, a static array is POD if and only if the array element type is POD. |
@WalterBright: My previous message was not meant as a question about how static arrays should be handled ABI-wise, but rather about your statement that only structs can be non-POD, and intended as a hint that the current implementation of the trait fails to handle static arrays properly. Thus, it is not consistent with the argtypes stuff. |
That should go into bugzilla, then. |
I'll just make a fixup.. |
Wait a minute, I see what you mean, there. You're right, the current implementation of traits is wrong because it doesn't handle the static array issue. |
@WalterBright: Oh, I missed that the pull request has already been merged. |
If the type is a static array, it should iterate along nextOf() until it finds the element type, then do the rest. |
… but only for 1-element static arrays, as the general n-element case is not implemented in argtypes yet. |
0-element and 2+ element static arrays are non-POD then? |
http://d.puremagic.com/issues/show_bug.cgi?id=9237
Initial attempt.