-
-
Notifications
You must be signed in to change notification settings - Fork 411
Replace in with const scope for object.d rt/dmain2.d and rt/typeinfo
#2685
Conversation
|
Thanks for your pull request and interest in making D better, @JinShil! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
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 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 + druntime#2685" |
| private void* _aaGetY(AA* paa, const TypeInfo_AssociativeArray ti, const size_t valsz, const scope void* pkey) pure nothrow; | ||
| private void* _aaGetX(AA* paa, const TypeInfo_AssociativeArray ti, const size_t valsz, const scope void* pkey, out bool found) pure nothrow; | ||
| // inout(void)* _aaGetRvalueX(inout AA aa, const scope TypeInfo keyti, const size_t valsz, const scope void* pkey); | ||
| inout(void[]) _aaValues(inout AA aa, const size_t keysz, const size_t valsz, const TypeInfo tiValueArray) pure nothrow; |
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 only used const for size_t as I believe scope is not applicable to value types.
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.
Yes, it is ignored to make generic code agnostic to valueness.
|
PetarKirov
left a comment
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.
There are various places where I think it's incorrect to assume const/scope correctness:
TypeInfo_Enum, TypeInfo_Array, TypeInfo_StaticArray, TypeInfo_AssociativeArray, TypeInfo_Class, TypeInfo_Interface, TypeInfo_Struct, TypeInfo_Const
and ultimately because of that I think we can't assume this for the base TypeInfo class as well.
That is because all these classes call directly or indirectly other code through a function pointer or virtual function interface, which we can't know if is const/scope correct. Perhaps we can ignore this for now, but if we want to migrate to a fully template-driven TypeInfo generation, we're going to have a lot of trouble then, when the compiler would be able to verify the true signatures of opEquals and opCmp.
| } | ||
|
|
||
| override bool equals(in void* p1, in void* p2) | ||
| override bool equals(const scope void* p1, const scope void* p2) |
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.
This calls object.opEquals, which in turn calls object.Object.opEquals (if both p1 and p2 are different and != null) on arbitrary object of an arbitrary class type, whose opEquals(Object o) implementation may store a reference to o (however unlikely this may be).
| } | ||
|
|
||
| override int compare(in void* p1, in void* p2) | ||
| override int compare(const scope void* p1, const scope void* p2) |
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.
Ditto - potentially calls object.Object.opCmp(Object o) and can't be scope.
| * toString) method to customize the error message. | ||
| */ | ||
| void toString(scope void delegate(in char[]) sink) const | ||
| void toString(scope void delegate(const scope char[]) sink) const |
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.
Could be a breaking change for callers, but that should only affect their @safe code, when they compile with -preview=dip1000.
| override bool equals(in void *p1, in void *p2) const { return base.equals(p1, p2); } | ||
| override int compare(in void *p1, in void *p2) const { return base.compare(p1, p2); } | ||
| override bool equals(const scope void *p1, const scope void *p2) const { return base.equals(p1, p2); } | ||
| override int compare(const scope void *p1, const scope void *p2) const { return base.compare(p1, p2); } |
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.
base can be the TypeInfo for a class or struct which implements opEquals|opCompare without having the scope attribute on the parameter.
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.
What do you recommend?
| size_t function(const scope void*) xtoHash; | ||
| bool function(const scope void*, const scope void*) xopEquals; | ||
| int function(const scope void*, const scope void*) xopCmp; | ||
| string function(const scope void*) xtoString; |
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.
Pedantically speaking, I don't think those function parameters can be neither scope nor const :(
Only when the TypeInfo generation is fully template-driven we can have true guarantees about const/scope/insert your favorite function attribute here correctness.
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.
What do you recommend?
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.
There are two options:
-
Use honest function signature and change those parameters to
void*as in reality even theconst-ness can't be guaranteed. This means thatTypeInfo_Struct.{equals,compare}must also takevoid*parameters which is likely a breaking change. -
Continue with the deceit and deal with problems somehow later down the line, when we can be technically honest.
@jmdavis @schveiguy @atilaneves What's your point of view?
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.
Not sure. I agree we can't make them scope or const though.
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.
@ZombineDev Why can't these be const? They shouldn't be modifying p.
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.
@JinShil Because they are function pointers to arbitrary user code. The pointer itself may not be modified (as it will be copied), but the object pointed by p may be. And it can also escape p without any issues.
Here's the sort of techniques that we need to use in order to be type safe:
https://gist.github.com/ZombineDev/ac19e93dff4f7b251be0c7af8e8d150d#file-proper_type_info-d-L62-L73
Live demo: https://run.dlang.io/gist/ZombineDev/ac19e93dff4f7b251be0c7af8e8d150d?compiler=dmd&args=-dip1000
|
A decision about |
About This PR
Followup to
#2676
dlang/phobos#7110
#2680
#2684
This one of several PRs I intend to submit, breaking up #2677 into multiple PRs.
This PR only addresses object.d, rt/dmain2.d, and files in the rt/typeinfo folder.
Background
This PR is in support of dlang/dmd#10179
inas a parameter storage class is defined asscope const. Howeverinhas not yetbeen properly implemented so its current implementation is equivalent to
const. Properlyimplementing
innow will likely break code, so it is recommended to avoid usingin, andexplicitly use
constorscope constinstead, untilinis properly implemented.The use of
inas a parameter storage class is already discouraged in the documentation. See https://dlang.org/spec/function.html#parameters