Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive

Conversation

@JinShil
Copy link
Contributor

@JinShil JinShil commented Jul 17, 2019

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

in as a parameter storage class is defined as scope const. However in has not yet
been properly implemented so its current implementation is equivalent to const. Properly
implementing in now will likely break code, so it is recommended to avoid using in, and
explicitly use const or scope const instead, until in is properly implemented.

The use of in as a parameter storage class is already discouraged in the documentation. See https://dlang.org/spec/function.html#parameters

@dlang-bot
Copy link
Contributor

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 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

Your 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 locally

If 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;
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 only used const for size_t as I believe scope is not applicable to value types.

Copy link
Contributor

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.

@thewilsonator
Copy link
Contributor

src/object.d(2515): Error: none of the overloads of `toString` are callable using argument types `(void)`, candidates are:
src/object.d(2512):        `object.Throwable.toString()`
src/object.d(2525):        `object.Throwable.toString(scope void delegate(scope const(char[])) sink)`

Copy link
Member

@PetarKirov PetarKirov left a 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)
Copy link
Member

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)
Copy link
Member

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
Copy link
Member

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); }
Copy link
Member

@PetarKirov PetarKirov Jul 17, 2019

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.

Copy link
Contributor Author

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;
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What do you recommend?

Copy link
Member

Choose a reason for hiding this comment

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

There are two options:

  1. Use honest function signature and change those parameters to void* as in reality even the const-ness can't be guaranteed. This means that TypeInfo_Struct.{equals,compare} must also take void* parameters which is likely a breaking change.

  2. 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?

Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Member

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

@JinShil
Copy link
Contributor Author

JinShil commented Sep 2, 2019

A decision about in has finally been made: dlang/dmd#10382 (comment)

@JinShil JinShil closed this Sep 2, 2019
@JinShil JinShil deleted the discourage_in_2c branch September 2, 2019 09:59
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants