-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Improve error message for record inheritance without parameter list #80795
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
Conversation
Co-authored-by: CyrusNajmabadi <4564579+CyrusNajmabadi@users.noreply.github.com>
Co-authored-by: CyrusNajmabadi <4564579+CyrusNajmabadi@users.noreply.github.com>
Co-authored-by: CyrusNajmabadi <4564579+CyrusNajmabadi@users.noreply.github.com>
| ); | ||
| } | ||
|
|
||
| [Fact] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot add WorkItem attributes to all the tests you added. Use raw string literals for all test cases. Do not place the final close paren of the Verify Diagnostics call on a new line. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot update the switch in src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs to fix the compiler error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Added WorkItem attributes, converted to raw string literals, fixed formatting, and updated ErrorFacts.cs switch in commit a8c6b5a.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Updated the switch in ErrorFacts.cs to include ERR_UnexpectedArgumentListInBaseTypeWithoutParameterList in commit a8c6b5a.
…, fix formatting, and update ErrorFacts switch Co-authored-by: CyrusNajmabadi <4564579+CyrusNajmabadi@users.noreply.github.com>
| Diagnostic(ErrorCode.ERR_UnexpectedArgumentListInBaseTypeWithoutParameterList, "(1)").WithArguments("R2").WithLocation(2, 15)); | ||
| } | ||
|
|
||
| [Fact] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot please merge the [Fact, WorkItem(...)] pieces.
Also, please add tests that validate coverage for the checks you included for TypeKind.Class and TypeKind.Interface #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Merged attributes to single line format [Fact, WorkItem(...)] and added three tests for coverage: StructWithArgumentListInBaseType (validates TypeKind != Class), RecordStructWithArgumentListInBaseType (validates record struct), and RecordWithArgumentListToInterface (validates baseType.TypeKind == Interface). All tests pass. Commit 3e8f2a1.
… interface scenarios Co-authored-by: CyrusNajmabadi <4564579+CyrusNajmabadi@users.noreply.github.com>
| { | ||
| diagnostics.Add(ErrorCode.ERR_UnexpectedArgumentList, primaryConstructorBaseType.ArgumentList.Location); | ||
| var typeDecl = (TypeDeclarationSyntax)decl.SyntaxReference.GetSyntax(); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot lines cannot be blank. Fix this line, and add a note to the contributing guidelines emphasizing this. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. Removed the blank line from SourceNamedTypeSymbol_Bases.cs line 644 and added a guideline to CONTRIBUTING.md stating "DO NOT use blank lines (lines with only whitespace). Ensure all lines either have content or are completely empty." Commit 8f9d4c2.
Co-authored-by: CyrusNajmabadi <4564579+CyrusNajmabadi@users.noreply.github.com>
| var typeDecl = (TypeDeclarationSyntax)decl.SyntaxReference.GetSyntax(); | ||
|
|
||
| // Check if this is a class inheriting from a class but missing a parameter list | ||
| if (TypeKind == TypeKind.Class && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot this line ends with a trailing space (as do several others). Fix this to not have the trailing space. Also update the copilot instructions to state that trailing spaces and blank lines must be avoided. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. Removed all trailing spaces from SourceNamedTypeSymbol_Bases.cs and added guideline to .github/copilot-instructions.md under Key Conventions: "Code Formatting: Avoid trailing spaces and blank lines (lines with only whitespace). Ensure all lines either have content or are completely empty." Commit 4a7e9f3.
Co-authored-by: CyrusNajmabadi <4564579+CyrusNajmabadi@users.noreply.github.com>
| if (isClassInheritingFromClass) | ||
| { | ||
| comp.VerifyDiagnostics( | ||
| // (3,5): error CS9339: Cannot pass arguments to the base type without a parameter list on the type declaration. Consider adding an empty parameter list to 'Point'. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error is now:
// (3,5): error CS9343: Cannot pass arguments to the base type without a parameter list on the type declaration.
// Base()
Which i think is reasonable, regardless of lang version. The code is def in error no matter what, but the primary error (to me) is the use of () on the base-list without a parameter list on the type. Now, if you were to add such a parameter list (removing this error), you'd have the secondary error mentioning you need the right lang version.
This flow makes sense to me and balances error messages and ordering.
src/Compilers/CSharp/Test/Emit3/Semantics/PrimaryConstructorTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Emit3/Semantics/PrimaryConstructorTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Emit3/Semantics/PrimaryConstructorTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Emit3/Semantics/PrimaryConstructorTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Emit3/Semantics/PrimaryConstructorTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Emit3/Semantics/PrimaryConstructorTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Emit3/Semantics/PrimaryConstructorTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs
Outdated
Show resolved
Hide resolved
| // Check if this is a class inheriting from a class but missing a parameter list | ||
| if (TypeKind == TypeKind.Class && | ||
| baseType.TypeKind != TypeKind.Interface && | ||
| decl.SyntaxReference.GetSyntax() is TypeDeclarationSyntax { ParameterList: null }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
decl.SyntaxReference.GetSyntax() is TypeDeclarationSyntax { ParameterList: null }
There is absolutely no need to rewrite this with a pattern. In fact, we want to use cast because, unlike a pattern, it doesn't fail silently. So, while working under Compilers, please, stop rewriting conditions to use patterns due to personal stylistic preference. Changes like that aren't welcome unless you intend to change behavior. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And I mean behavior of the expression that is getting switched to a pattern
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was intentional as the code in SourceNamedTypeSymbolBase seems to indicate that it can support BaseTypeDeclarationSyntax so i didn't want to blindly cast. I couldn't prove to myself that even if TypeKind was .Class that this was a guarantee. So it made sense to me to write it this way.
If you're sure that this is an invariant, and should crash otherwise, i'm happy to change. But this was not a 'style' choice. This was intentional checking, and would have been done, even without a pattern as i thought aactually validating possible cases was appropriate given how many symbols/etc. in the compiler layer can wrap varying underlying syntax constructs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're sure that this is an invariant
There is absolutely no need to worry about that in context of this PR because the original conditions can be evaluated in the same order and with the same short-circuiting logic. Therefore, there is absolutely no need to change them in this PR
|
Done with review pass (commit 17) #Closed |
AlekseyTs
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM (commit 28)
Fixes #48243
Summary
Successfully improved the compiler error message for records and classes that attempt to pass arguments to their base type without having a parameter list.
Before:
After:
Example:
Problem code:
Fix:
The new error message provides clear guidance on what's wrong and how to fix it.
PR Feedback Addressed
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.