Skip to content
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

Proposal: Preprocessor Directive Attributes #7875

Closed
alrz opened this issue Jan 11, 2016 · 8 comments
Closed

Proposal: Preprocessor Directive Attributes #7875

alrz opened this issue Jan 11, 2016 · 8 comments

Comments

@alrz
Copy link
Member

alrz commented Jan 11, 2016

While using #pragma warning and #pragma restore is very common, there is no guarantee that you actually restore the disabled warning. And more often than not you just want to disable it for a single code construct, like a variable declaration or a block of code.

#pragma warning disable RS0013
var foo = new Foo( ... );
#pragma warning restore RS0013

With source-only attributes (#6671) this can be easily achieved with a dedicated attribute, like

[[disable(RS0013)]]
var foo = new Foo( ... );

This attribute can be applied to any piece of code that source-only attributes are allowed on, like classes, blocks, et cetera.

Another use case is in conditional compilation which can become very complicated over time,

[[if(DEBUG)]]
class C {}
[[if(!DEBUG)]]
class C {}

Note that ConditionalAttribute only works with void-returning methods, while source-only attributes can be used on any language construct.

As a further consideration, I'd like to suggest Rust syntax for source-only attributes to make this clearer to the user,

#[if(DEBUG)]
class C : #[if(FOO)] IFoo { }

is equivalent to

#if DEBUG
class C 
#if FOO
: IFoo 
#endif
{ }
#endif

Although, as you can see, applying these attributes on some places needs additional considerations.

EDIT: Another thing that this makes easier is that you don't need to use #if directive both at the declaration-site and the usage-site, for example,

[Attr] // won't get evaluated in if(!DEBUG)
class C { }
#[if(DEBUG)]
class Attr : Attribute { }

PS: The compiler should not essentially translate these attributes to flat #if and #pragma, instead it should just ignore the target (in case of [[if]]) if condition is not satisfied, or suppress specific warnings when analysing the target (in case of [[disable]]).

@HaloFour
Copy link

Java has the similar @SuppressWarnings annotation which is useful for disabling warnings within a specific scope without having to worry about re-enabling the warning later. I think that could be quite useful.

As for conditionals, I could see that getting weirdly complicated and fast.

@alrz
Copy link
Member Author

alrz commented Jan 11, 2016

@HaloFour I think my last example is "weirdly complicated" but with attributes it ain't IMO. As for limitations of ConditionAttribute, I think conditionals could be also useful. For example,

// you would have no idea that this conditional is specific to the following method or not
#if DEBUG
int F()
{
...
}

// now you know
[[if(DEBUG)]]
int F()
{
 ...
}

This applies to other constructs as well, because attributes are applied to a single atomic language construct, like a class, you can easily tell that this specific conditional is affecting this specific class, not more or less.

@HaloFour
Copy link

@alrz When targeted to the class or member level, sure. But I think that if you start adding in all of the potential targets for source attributes that it could get difficult to read. The current convention of using #if with multiple declarations is certainly verbose, but it's pretty easy to determine what the complete signature will be in each of the circumstances.

@alrz
Copy link
Member Author

alrz commented Jan 11, 2016

@HaloFour That would be considered as "abusing" I think. But this is basically what you gain with source-only attributes aka "attributes everywhere" in the first place. The current #if is painfully flat and don't give a heck about what is being affected but with attributes you are specific about this, because that's the point! you don't use #if just "over" your code, you always do it for a specific chunk of code, so don't you think that it would be better to actually correspond conditionals to that specific meaningful entity rather than start and end of some lines of code?

@HaloFour
Copy link

@alrz I do see that value, I just caution where and how it might be applied. Many current attributes targets have no real scope and in those cases it probably doesn't make sense to allow either of these pseudo-attributes to be applied. I think that your example of applying [[if]] within the interface-type-list is borderline and makes the class declaration hard to read, at least over the current common convention. Applying to targets like parameters or return values or the like make even less sense.

@alrz
Copy link
Member Author

alrz commented Jan 11, 2016

@HaloFour " applying [[if]] within the interface-type-list is borderline and makes the class declaration hard to read" While I believe doing so with current #if makes it almost impossible to read, I agree that it shouldn't be allowed, like, everywhere.

@HaloFour
Copy link

@alrz By the way you had used #if I would completely agree, but the convention is a bit more structured than that, although certainly more verbose. I think that we both agree that something like this would be useful and we probably both agree that there is a line where the syntax would become somewhat abusive or where the targets should probably be limited to make more sense.

@gafter
Copy link
Member

gafter commented Mar 24, 2017

We are now taking language feature discussion in other repositories:

Features that are under active design or development, or which are "championed" by someone on the language design team, have already been moved either as issues or as checked-in design documents. For example, the proposal in this repo "Proposal: Partial interface implementation a.k.a. Traits" (issue 16139 and a few other issues that request the same thing) are now tracked by the language team at issue 52 in https://github.com/dotnet/csharplang/issues, and there is a draft spec at https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md and further discussion at issue 288 in https://github.com/dotnet/csharplang/issues. Prototyping of the compiler portion of language features is still tracked here; see, for example, https://github.com/dotnet/roslyn/tree/features/DefaultInterfaceImplementation and issue 17952.

In order to facilitate that transition, we have started closing language design discussions from the roslyn repo with a note briefly explaining why. When we are aware of an existing discussion for the feature already in the new repo, we are adding a link to that. But we're not adding new issues to the new repos for existing discussions in this repo that the language design team does not currently envision taking on. Our intent is to eventually close the language design issues in the Roslyn repo and encourage discussion in one of the new repos instead.

Our intent is not to shut down discussion on language design - you can still continue discussion on the closed issues if you want - but rather we would like to encourage people to move discussion to where we are more likely to be paying attention (the new repo), or to abandon discussions that are no longer of interest to you.

If you happen to notice that one of the closed issues has a relevant issue in the new repo, and we have not added a link to the new issue, we would appreciate you providing a link from the old to the new discussion. That way people who are still interested in the discussion can start paying attention to the new issue.

Also, we'd welcome any ideas you might have on how we could better manage the transition. Comments and discussion about closing and/or moving issues should be directed to #18002. Comments and discussion about this issue can take place here or on an issue in the relevant repo.

I am not moving this particular issue because I don't have confidence that the LDM would likely consider doing this.

@gafter gafter closed this as completed Mar 24, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants