Skip to content

Fix Issue 9701 - allow UDAs to be attached to enum values#8319

Closed
JinShil wants to merge 1 commit intodlang:masterfrom
JinShil:fix_9701
Closed

Fix Issue 9701 - allow UDAs to be attached to enum values#8319
JinShil wants to merge 1 commit intodlang:masterfrom
JinShil:fix_9701

Conversation

@JinShil
Copy link
Contributor

@JinShil JinShil commented Jun 1, 2018

This is a reboot of #6161

I've also added the ability to mark enum members as deprecated and @disabled.

It was decided a while ago that a proper implementation would be accepted without a DIP. Here's the forum announcement: https://forum.dlang.org/post/gcgtotrhuirhcvvbxrfm@forum.dlang.org

This only implements the feature for enum members. For function arguments, see #7576

@JinShil JinShil requested a review from RazvanN7 as a code owner June 1, 2018 08:16
@dlang-bot
Copy link
Contributor

Thanks for your pull request, @JinShil!

Bugzilla references

Auto-close Bugzilla Severity Description
9701 normal UDAs cannot be attached to enum values.

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#8319"

@JinShil JinShil added the Review:WIP Work In Progress - not ready for review or pulling label Jun 1, 2018
{
value0,
@("uda1") value1,
@("uda2") @("uda3") value2,
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be a test with the @uda syntax as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

super(loc, TOK.variable, __traits(classInstanceSize, VarExp), var, hasOverloads);
//printf("VarExp(this = %p, '%s', loc = %s)\n", this, var.toChars(), loc.toChars());
//if (strcmp(var.ident.toChars(), "func") == 0) assert(0);
this.type = var.type;
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 was needed to prevent semantic from printing a deprecation multiple times. I used the common pattern to check for type to see if semantic has already been run. This also required some refactoring of the expression semantic visitor for VarExp.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this really the correct fix?

Copy link
Contributor Author

@JinShil JinShil Jun 2, 2018

Choose a reason for hiding this comment

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

I'm not 100% sure, but if you search expressionsem.d for if (e.type) you will see it is a common idiom. The expression classes don't seem to have a flag indicating whether or not semantic has been run, so it looks like the type property is (ab)used for that.

It doesn't work at the moment anyway because there are other places in the code that don't call expressionSemantic on the VarExp class, so I need to submit a separate PR to remedy that. I worked on it all day today, and it's proving to be quite difficult.

If I don't do this, then a deprecation message is printed every type VarExp.expressionSemantic is run, and that's suboptimal. I need some way to know whether or it has already been run, and the dominating idiom for that seems to be if (e.type) in the semantic visitor functions.

VarDeclaration v = ve.var.isVarDeclaration();
if (v && ve.checkPurity(sc, v))
return setError();
exp.e1 = ve.expressionSemantic(sc);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because we removed setting type in VarExp's constructor. See https://github.com/dlang/dmd/pull/8319/files#r192327829

@JinShil
Copy link
Contributor Author

JinShil commented Jun 2, 2018

This is currently held up on a problem with the VarExp semantic visitor. It seems to be needlessly called multiple times. So if I put a deprecation message there, it gets printed multiple times. I'm trying to resolve that in a separate PR, but I'm having a hell of a time getting it right.

@uda5 @uda6 value4,
@("uda7") @uda8 value5,
@uda9 @("uda10") value6,
deprecated value7
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add a test for deprecated with a message as well, i.e. deprecated("foo").

@JinShil
Copy link
Contributor Author

JinShil commented Jun 7, 2018

I'm closing this. My frustration with D has hit a new high, and I need to walk away for a while.

@JinShil JinShil closed this Jun 7, 2018
@IgorStepanov
Copy link
Contributor

@JinShil Hi. Why do you closed this PR? Are there any troubles in implementation?

@IgorStepanov
Copy link
Contributor

You may call e.checkDeprecated(sc, e.var); only if e.type is null. (before the first semantic of VarExp)
Or you may return from visit if e.type is not null (if you are sure that there should be only one semantic for VarExp).

@JinShil
Copy link
Contributor Author

JinShil commented Jun 25, 2018

Are there any troubles in implementation?

Hi @IgorStepanov, Yes, there is one fundamental issue that I can't find a solution for. The semantic pass for VarExp is called multiple times. Therefore, when I add the code to display an error message for the disable/deprecated attributes, the error message prints at least 3 times for each VarExp. I tried to solve that by checking if the type property is null to determine if semantic had already been run (that pattern exists elsewhere for other derived Expression types), but while it solved the multiple error message problem, it caused a cascade of other failures. I tried to work through it little-by-little solving each failure, but the problem was so systematic, it became hopeless.

I asked for help on the forum but never received a response.

Edit: If you think you can fix this, please adopt this PR and let's bring it to completion.

@IgorStepanov
Copy link
Contributor

@JinShil we may add the field with flag only for attribute errors. Ensure that this field properly copies in copy syntaxCopy functions. This is an ugly solution, but it doesnt block a very useful feature.
And why do you check deprecation in VarExp semantic, not in EnumMember semantic?
I'll try to fix it in a week, I hope.

@JinShil
Copy link
Contributor Author

JinShil commented Jun 25, 2018

And why do you check deprecation in VarExp semantic, not in EnumMember semantic?

Because we want the error message at the usage site, not the declaration site.

I'll try to fix it in a week, I hope.

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Review:WIP Work In Progress - not ready for review or pulling Severity:Bug Fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants