Skip to content

Comments

Fix 15371: Disable access checks for __traits(getMember) and relatives.#9325

Closed
LightBender wants to merge 5 commits intodlang:masterfrom
LightBender:fix_15371
Closed

Fix 15371: Disable access checks for __traits(getMember) and relatives.#9325
LightBender wants to merge 5 commits intodlang:masterfrom
LightBender:fix_15371

Conversation

@LightBender
Copy link
Contributor

@LightBender LightBender commented Feb 4, 2019

Removes access checks for __traits(getMember) and relatives. This should have been done a long time ago. As it stands right now .offsetof is useless because it cannot be used on non-public members and therefore cannot be used to accurately map the type. Indeed there is NO way to accurately map any type that contains private data.

Bug: https://issues.dlang.org/show_bug.cgi?id=15371

@dlang-bot
Copy link
Contributor

Thanks for your pull request and interest in making D better, @LightBender! 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 annotated coverage diff directly on GitHub with CodeCov's browser extension
  • 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 + dmd#9325"

@jacob-carlborg
Copy link
Contributor

Please use a better commit message and PR title. Something else than jus the link, like the title of the issue.

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

Sorry but this bug fix is formally not ok. Also This is is a serious change that requires a DIP, which is all about the new super omnisciencynessment that the change bring.

@LightBender
Copy link
Contributor Author

LightBender commented Feb 4, 2019

Umm, what? How does fixing a genuine bug, which is acknowledge as something that should be fixed in the comment sitting above the code require an entire DIP? Your assertion is going to require a very detailed explanation to convince me of it's correctness.

@LightBender LightBender changed the title Fix 15371: https://issues.dlang.org/show_bug.cgi?id=15371 Fix 15371: Disable access checks for __traits(getMember) and relatives. Feb 4, 2019
@ghost
Copy link

ghost commented Feb 4, 2019

My thoughts on trying to fix this issue:

This is a major step forward in term of metaprogramming. You know everything by using __trait(allMembers), __trait(getMember), i.e the "god omniscience", but you decide on your own to apply __trait(getProtection). That's a major change in the language semantics.

@ghost
Copy link

ghost commented Feb 4, 2019

TBH, this is how i think this issue should be fixed.

@LightBender
Copy link
Contributor Author

LightBender commented Feb 5, 2019

How is it a "major change to language semantics"? __traits(allMembers) is at best confusing, it should really be labelled __traits(publicMembers) because it sure doesn't actually mean "All Members". At best this is fixing a bug in the language by making the language do what it says it's going to do. I can guarantee that nobody who uses __traits(allMembers) without carefully reading the documentation and archaic forum posts on the matter is going to just assume that it really means "Public Members Only". They will justifiably assume it means "All Members".

Futhermore, you did not explain WHY you consider this a major change to the language semantics, only repeated your assertion that it is. At this time I cannot accept your argument.

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

Sorry for the confusing review comments yesterday @LightBender, if the issue can be solved as simply as that then it's nice.

Copy link
Contributor

@jacob-carlborg jacob-carlborg left a comment

Choose a reason for hiding this comment

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

  • The change affects more than just getMember, the tests should include a test for each trait it affects

  • Even though this is fixing a bug, I think a changelog entry should be included. This adds new functionality and therefore should have a changelog entry explaining the new behavior. Have a look in the changelog directory

}
auto field = __traits(getMember, test, "privateField");
printf("Existing private field value: %d\r\n", field);
field = 1;
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't this just update a local variable?

TEST_OUTPUT:
---

---
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't there be any output?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That was the weird part, I could get the output when I placed an failing assert in the code, but without it, I got nothing.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think TEST_OUTPUT is usually used for asserting error messages for failing tests. Is there any difference if you print to stderr?

Copy link
Contributor

Choose a reason for hiding this comment

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

You need to use pragma(msg,...) for TEST_OUTPUT as it only listens to output during compilation.

auto test = new Test15371();
const auto hasMember = __traits(hasMember, test, "privateField");
if (hasMember) {
printf("_traits(hasMember) found privateField\r\n");
Copy link
Contributor

Choose a reason for hiding this comment

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

I've never seen anyone use \r\n when printing to the console.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Without it is just kept printing on the same line. And only with the failing assert.

Copy link
Contributor

Choose a reason for hiding this comment

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

I mean, only \n is usually used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This works correctly on Windows too.

Copy link
Member

Choose a reason for hiding this comment

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

You almost never need \r on Windows, too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's an ingrained habit from the bad old days. I'll remove it.


void main() {
auto test = new Test15371();
const auto hasMember = __traits(hasMember, test, "privateField");
Copy link
Contributor

Choose a reason for hiding this comment

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

auto is not required.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Habit from my C# days where any variable decl would be var if it had the type somewhere in the initializer.

auto virtualMethods = __traits(getVirtualMethods, test, "overload").length;
printf("Found %d virtual methods for private method 'overload'\r\n", virtualMethods);
auto virtualFunctions = __traits(getVirtualFunctions, test, "overload").length;
printf("Found %d virtual functions for private method 'overload'\r\n", virtualFunctions);
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks quite dense, perhaps add some blank lines.


The following traits can now access non-public members:
$(UL
$(LI hasMember)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this worked before this PR. Since this is not try to access the symbol. I'm guessing that what's ignoresymbolvisibility is for.

$(LI getVirtualFunctions)
)

This fixes a long-standing issue in D where the allMembers trait would correctly return non-public members but those non-public members would be inaccessible to other traits.
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest adding backticks (to indicate code) around allMembers.

@@ -0,0 +1,31 @@
// EXTRA_SOURCES: imports/test15371.d

Copy link
Contributor

Choose a reason for hiding this comment

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

Runnable tests are very expensive. Please move this to compilable and use things like static assert or pragma(msg).

@RazvanN7
Copy link
Contributor

@LightBender Will you take this to the finish line or should I adopt it?

@jacob-carlborg
Copy link
Contributor

@RazvanN7 I recommend you take it so it’s completed as soon as possible.

@RazvanN7
Copy link
Contributor

PR submitted: #9585 . Closing this as @LightBender seems to have abandoned it. We can continue the discussion on the new PR.

@RazvanN7 RazvanN7 closed this Apr 10, 2019
@LightBender LightBender deleted the fix_15371 branch August 31, 2023 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants