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

Final prototype comments and top level statements local adjustments #61551

Merged
merged 3 commits into from
May 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions docs/compilers/CSharp/Compiler Breaking Changes - DotNet 7.md
Original file line number Diff line number Diff line change
Expand Up @@ -391,3 +391,16 @@ Console.WriteLine($"{{{12:X}}}");
The workaround is to remove the extra braces in the format string.

You can learn more about this change in the associated [roslyn issue](https://github.com/dotnet/roslyn/issues/57750).

## Types cannot be named `required`

***Introduced in Visual Studio 2022 version 17.3.*** Starting in C# 11, types cannot be named `required`. The compiler will report an error on all such type names. To work around this, the type name and all usages must be escaped with an `@`:

```csharp
class required {} // Error CS9029
class @required {} // No error
```

This was done as `required` is now a member modifier for properties and fields.

You can learn more about this change in the associated [csharplang issue](https://github.com/dotnet/csharplang/issues/3630).
5 changes: 3 additions & 2 deletions docs/contributing/Compiler Test Plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ This document provides guidance for thinking about language interactions and tes
- Access modifiers (public, protected, internal, protected internal, private protected, private), static, ref
- type declarations (class, record class/struct with or without positional members, struct, interface, type parameter)
- methods
- fields
- properties (including get/set/init accessors)
- fields (required and not)
- properties (including get/set/init accessors, required and not)
- events (including add/remove accessors)
- Parameter modifiers (ref, out, in, params)
- Attributes (including generic attributes and security attributes)
Expand Down Expand Up @@ -110,6 +110,7 @@ This document provides guidance for thinking about language interactions and tes
- pre-processing directives
- COM interop
- modopt and modreq
- CompilerFeatureRequiredAttribute
- ref assemblies
- extern alias
- UnmanagedCallersOnly
Expand Down
34 changes: 16 additions & 18 deletions src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2070,26 +2070,24 @@ internal enum ErrorCode
ERR_ExpressionTreeContainsUTF8StringLiterals = 9027,
ERR_MisplacedUnchecked = 9028,

ERR_RequiredNameDisallowed = 9029,
ERR_OverrideMustHaveRequired = 9030,
ERR_RequiredMemberCannotBeHidden = 9031,
ERR_RequiredMemberCannotBeLessVisibleThanContainingType = 9032,
ERR_ExplicitRequiredMember = 9033,
ERR_RequiredMemberMustBeSettable = 9034,
ERR_RequiredMemberMustBeSet = 9035,
ERR_RequiredMembersMustBeAssignedValue = 9036,
ERR_RequiredMembersInvalid = 9037,
ERR_RequiredMembersBaseTypeInvalid = 9038,
ERR_ChainingToSetsRequiredMembersRequiresSetsRequiredMembers = 9039,
ERR_NewConstraintCannotHaveRequiredMembers = 9040,
ERR_UnsupportedCompilerFeature = 9041,
WRN_ObsoleteMembersShouldNotBeRequired = 9042,
ERR_RefReturningPropertiesCannotBeRequired = 9043,

#endregion

// Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd)

// PROTOTYPE(req): Move above the comment and condense before merge

ERR_RequiredNameDisallowed = 9500,
ERR_OverrideMustHaveRequired = 9501,
ERR_RequiredMemberCannotBeHidden = 9502,
ERR_RequiredMemberCannotBeLessVisibleThanContainingType = 9503,
ERR_ExplicitRequiredMember = 9504,
ERR_RequiredMemberMustBeSettable = 9505,
ERR_RequiredMemberMustBeSet = 9506,
ERR_RequiredMembersMustBeAssignedValue = 9507,
ERR_RequiredMembersInvalid = 9508,
ERR_RequiredMembersBaseTypeInvalid = 9509,
ERR_ChainingToSetsRequiredMembersRequiresSetsRequiredMembers = 9510,
ERR_NewConstraintCannotHaveRequiredMembers = 9511,
ERR_UnsupportedCompilerFeature = 9512,
WRN_ObsoleteMembersShouldNotBeRequired = 9513,
ERR_RefReturningPropertiesCannotBeRequired = 9514,
}
}
4 changes: 1 addition & 3 deletions src/Compilers/CSharp/Portable/Errors/MessageID.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,6 @@ internal enum MessageID

IDS_FeatureGenericAttributes = MessageBase + 12812,

// PROTOTYPE(req): here for avoiding merge conflicts. Move to the end and condense before merge.
IDS_FeatureRequiredMembers = MessageBase + 13000,

IDS_FeatureNewLinesInInterpolations = MessageBase + 12813,
IDS_FeatureListPattern = MessageBase + 12814,
IDS_ParameterNullChecking = MessageBase + 12815,
Expand All @@ -257,6 +254,7 @@ internal enum MessageID
IDS_FeatureUnsignedRightShift = MessageBase + 12823,
IDS_FeatureExtendedNameofScope = MessageBase + 12824,
IDS_FeatureRelaxedShiftOperator = MessageBase + 12825,
IDS_FeatureRequiredMembers = MessageBase + 12826,
}

// Message IDs may refer to strings that need to be localized.
Expand Down
14 changes: 8 additions & 6 deletions src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1173,8 +1173,9 @@ internal static DeclarationModifiers GetModifier(SyntaxKind kind, SyntaxKind con
}
}

private void ParseModifiers(SyntaxListBuilder tokens, bool forAccessors)
private void ParseModifiers(SyntaxListBuilder tokens, bool forAccessors, bool forTopLevelStatements)
{
333fred marked this conversation as resolved.
Show resolved Hide resolved
Debug.Assert(!(forAccessors && forTopLevelStatements));
while (true)
{
var newMod = GetModifier(this.CurrentToken);
Expand Down Expand Up @@ -1258,8 +1259,9 @@ private void ParseModifiers(SyntaxListBuilder tokens, bool forAccessors)
case DeclarationModifiers.Required:
// In C# 11, required in a modifier position is always a keyword if not escaped. Otherwise, we reuse the async detection
// machinery to make a conservative guess as to whether the user meant required to be a keyword, so that they get a good langver
// diagnostic and all the machinery to upgrade their project kicks in.
if (!IsFeatureEnabled(MessageID.IDS_FeatureRequiredMembers) && !ShouldAsyncOrRequiredBeTreatedAsModifier(parsingStatementNotDeclaration: false))
// diagnostic and all the machinery to upgrade their project kicks in. The only exception to this rule is top level statements,
// where the user could conceivably have a local named required. For these locations, we need to disambiguate as well.
if ((!IsFeatureEnabled(MessageID.IDS_FeatureRequiredMembers) || forTopLevelStatements) && !ShouldAsyncOrRequiredBeTreatedAsModifier(parsingStatementNotDeclaration: false))
333fred marked this conversation as resolved.
Show resolved Hide resolved
{
return;
}
Expand Down Expand Up @@ -2373,7 +2375,7 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind
}

// All modifiers that might start an expression are processed above.
this.ParseModifiers(modifiers, forAccessors: false);
this.ParseModifiers(modifiers, forAccessors: false, forTopLevelStatements: true);
bool haveModifiers = (modifiers.Count > 0);
MemberDeclarationSyntax result;

Expand Down Expand Up @@ -2826,7 +2828,7 @@ private MemberDeclarationSyntax ParseMemberDeclarationCore(SyntaxKind parentKind
{
var attributes = this.ParseAttributeDeclarations();

this.ParseModifiers(modifiers, forAccessors: false);
this.ParseModifiers(modifiers, forAccessors: false, forTopLevelStatements: false);

// Check for constructor form
if (this.CurrentToken.Kind == SyntaxKind.IdentifierToken && this.PeekToken(1).Kind == SyntaxKind.OpenParenToken)
Expand Down Expand Up @@ -4120,7 +4122,7 @@ private AccessorDeclarationSyntax ParseAccessorDeclaration(bool isEvent)
try
{
var accAttrs = this.ParseAttributeDeclarations();
this.ParseModifiers(accMods, forAccessors: true);
this.ParseModifiers(accMods, forAccessors: true, forTopLevelStatements: false);

// check availability of readonly members feature for accessors
CheckForVersionSpecificModifiers(accMods, SyntaxKind.ReadOnlyKeyword, MessageID.IDS_FeatureReadOnlyMembers);
Expand Down
Loading