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: Repeated Attributes in Partial Members #3658

Open
1 of 4 tasks
RikkiGibson opened this issue Jul 9, 2020 · 0 comments
Open
1 of 4 tasks

Proposal: Repeated Attributes in Partial Members #3658

RikkiGibson opened this issue Jul 9, 2020 · 0 comments
Assignees
Labels
Needs Implementation The specification for this issue has been approved, it needs an implementation Proposal champion
Milestone

Comments

@RikkiGibson
Copy link
Contributor

RikkiGibson commented Jul 9, 2020

Repeated Attributes in Partial Members

Summary

Allow each declaration of a partial member to independently apply an attribute not marked with [AttributeUsage(AllowMultiple = true)], as long as the attribute arguments are identical in all applications.

Motivation

When considering what attributes are present on a 'partial' method, the language unions together all the attributes in all corresponding positions on both declarations. For example, the method M below has attributes A and B.

[A]
partial void M();
[B]
partial void M() { }

This means that attributes which are not marked [AttributeUsage(AllowMultiple = true)] cannot be present across both parts:

[A]
partial void M();
[A] // error: duplicate attribute!
partial void M() { }

This presents a usability/readability issue, because some attributes are designed to inform the user and/or maintainer of the method of what pre/postconditions or invariants the method requires. For example:

public partial bool TryGetValue([NotNullWhen(true)] out object? value);
public partial bool TryGetValue(out object? value) { ... }

A partial member typically facilitates the relationship between a code generator and an end user--each party provides one of the declarations of the partial member in order for a code generator to provide functionality to the user, or for the user to access an extension point in generated code. In the situation where only one declaration is allowed to have these single-application attributes, the generator and the user can't effectively communicate their requirements to each other. If a generator produces a defining declaration with a NotNullWhen attribute, for instance, the user cannot write an implementing declaration with that same attribute, even though the postcondition is applicable to the implementation, and checked by the compiler. This creates confusion for users when tracking down the root causes of warnings or when trying to understand the behaviors of a method.

Solution

Allow a non-AllowMultiple attribute to be used once on each symbol (member, return, parameter, etc.) in each partial declaration, as long as the attribute arguments are identical. Since attribute arguments are all constants, the compiler can verify this. When attributes are unioned across declarations, each non-AllowMultiple attribute will be de-duplicated and only one instance of the attribute will be emitted.

public partial bool TryGetValue([NotNullWhen(true)] out object? value);
public partial bool TryGetValue([NotNullWhen(true)] out object? value) { ... } // ok
// equivalent to:
public bool TryGetValue([NotNullWhen(true)] out object value) { ... }
// error when attribute arguments do not match
public partial bool TryGetValue([NotNullWhen(true)] out object? value);
public partial bool TryGetValue([NotNullWhen(false)] out object? value) { ... } // error

Open questions

  1. Should such repetition of attributes be permitted on 'partial' type declarations or only on non-type members (e.g. methods)?
  2. Should attributes which do allow multiple usages on a symbol be permitted to "opt in" to de-duplication of equivalent usages of an attribute?

Design meetings

6th July 2020

The proposal is accepted.

  • Repetition of non-AllowMultiple attributes will be permitted across partial type declarations (open question 1).
  • Repeated application of AllowMultiple attributes will not change in behavior, and an "opt in" mechanism for de-duplication may be considered in a future proposal (open question 2).

https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-09-26.md#ungrouped

@333fred 333fred added this to the 9.0 candidate milestone Jul 20, 2020
@MadsTorgersen MadsTorgersen modified the milestones: 9.0 candidate, 10.0 candidate Sep 9, 2020
@333fred 333fred modified the milestones: 10.0 candidate, 10.0 Working Set Oct 14, 2020
@333fred 333fred modified the milestones: Working Set, Any Time Sep 26, 2022
@333fred 333fred added Needs Approved Specification This issue needs an LDM-approved specification Needs Implementation The specification for this issue has been approved, it needs an implementation and removed Needs Approved Specification This issue needs an LDM-approved specification labels Sep 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Implementation The specification for this issue has been approved, it needs an implementation Proposal champion
Projects
None yet
Development

No branches or pull requests

4 participants