Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 16, 2025

Plan to Improve Error Reporting for Negative Cast to Enum ✅

  • Understand the problem: When writing (ConsoleColor)-1, the compiler reports both CS0119 ("ConsoleColor is a type, which is not valid") and CS0075 ("To cast a negative value, you must enclose the value in parentheses")
  • Locate the relevant code:
    • CS0075 (ERR_PossibleBadNegCast) is reported in Binder_Operators.cs line 912
    • CS0119 (ERR_BadSKunknown) is reported in Binder.ValueChecks.cs via CheckNotNamespaceOrType
  • Modify the code to suppress CS0119 when CS0075 will be reported
    • REVISED APPROACH: Instead of filtering errors after they're added, prevent ERR_BadSKunknown from being reported in the first place
    • Modified CheckNotNamespaceOrType to check for the (T)-X syntactic pattern before reporting ERR_BadSKunknown
    • Created shared helper method IsParenthesizedExpressionInPossibleBadNegCastContext used by both CheckNotNamespaceOrType and BindSimpleBinaryOperator
    • IMPORTANT: Nested parentheses check only applies to TypeExpression case, not to dynamic identifier case
    • This ensures both places check for the exact same pattern consistently while preserving original semantics
    • Reverted complex diagnostic bag filtering logic in Binder_Operators.cs
    • Added comment noting synchronization requirement with BindSimpleBinaryOperator
  • Update existing tests to reflect the improved error behavior
    • Updated PossibleBadNegCast test to expect only CS0075 errors
    • Added PossibleBadNegCastNestedParentheses test to demonstrate behavior with nested parentheses
    • Updated test formatting to use raw string literals and WorkItem attribute
  • Run broader compiler tests to ensure no regressions
    • All 7 PossibleBadNegCast tests pass
    • Cleaner implementation following code review feedback
  • Run code review and security checks

Summary

Successfully improved error reporting for negative cast to enum with a cleaner approach that prevents the error from being added rather than filtering it out afterward. Both places that need to detect the pattern now share the same helper method to ensure consistency.

Example

Before:

error CS0119: 'ConsoleColor' is a type, which is not valid in the given context
error CS0075: To cast a negative value, you must enclose the value in parentheses.

After:

error CS0075: To cast a negative value, you must enclose the value in parentheses.
Original prompt

This section details on the original issue you should resolve

<issue_title>Improve error for casting negative value to enum</issue_title>
<issue_description>Example:

using System;

public class Program
{
    public void T()
    {
        var value = (ConsoleColor)-1;
    }
}

We get two error messages:

Example.cs(7,22): error CS0119: 'ConsoleColor' is a type, which is not valid in the given context
Example.cs(7,21): error CS0075: To cast a negative value, you must enclose the value in parentheses.

Can we get rid of the first error if the second is present? It's fairly obvious what we're trying to do and I often get this error as I forgot to add the parens</issue_description>

<agent_instructions>@copilot see if we can improve things here. Since we reported: error CS0075: To cast a negative value, you must enclose the value in parentheses. we don't need the message that error CS0119: 'ConsoleColor' is a type, which is not valid in the given context.</agent_instructions>

Comments on the Issue (you are @copilot in this section)


💡 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.

Copilot AI changed the title [WIP] Improve error for casting negative value to enum Suppress CS0119 when CS0075 is reported for negative cast Nov 16, 2025
Copilot AI requested a review from CyrusNajmabadi November 16, 2025 20:15
// For negative cast detection, we need to check if we're going to report ERR_PossibleBadNegCast
// before binding the left operand. If we will report it, we should suppress the ERR_BadSKunknown
// error that would be reported when binding a type name in a value context.
bool mightReportPossibleBadNegCast = node.IsKind(SyntaxKind.SubtractExpression)
Copy link
Member

Choose a reason for hiding this comment

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

@copilot instead of this, where you're adding code to BindSimpleBinaryOperator where you try to undo the error added deeper in, let's instead NOT add the ERR_BadSKunknown if we can see that we'd add it in a (T)-X syntactic cases we check for here where we end up reporting ERR_PossibleBadNegCast.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to check for the (T)-X pattern in CheckNotNamespaceOrType before reporting ERR_BadSKunknown, rather than filtering after. Simpler and cleaner approach. Fixed in c093621.

Error(diagnostics, ErrorCode.ERR_BadSKunknown, expr.Syntax, expr.Type, MessageID.IDS_SK_TYPE.Localize());
// Don't report ERR_BadSKunknown if we're in a (T)-X pattern, as we'll report
// ERR_PossibleBadNegCast instead which is more specific and helpful.
if (!IsInPossibleBadNegCastContext(expr.Syntax))
Copy link
Member

Choose a reason for hiding this comment

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

@copilot mention that this needs to be kept in sync with BindSimpleBinaryOperator

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added comment in 3730db3.

}

private static bool IsInPossibleBadNegCastContext(SyntaxNode syntax)
{
Copy link
Member

Choose a reason for hiding this comment

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

@copilot it would also be good if BindSimpleBinaryOperator and this code shared the same helper function. That way we can be absolutely sure that if this isn't reporting ERR_BadSKunknown that BindSimpleBinaryOperator will report ERR_PossibleBadNegCast in the same case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Refactored to share IsParenthesizedExpressionInPossibleBadNegCastContext between both places. This ensures they check for the exact same pattern consistently. Fixed in 6bbab47.

…BindSimpleBinaryOperator

Co-authored-by: CyrusNajmabadi <[email protected]>
…CheckNotNamespaceOrType

Co-authored-by: CyrusNajmabadi <[email protected]>
…ression, not dynamic

The nested parentheses check should only apply to the TypeExpression case,
not to the dynamic identifier case. This preserves the original behavior
where ((dynamic))-1 would not report CS0075 because the expression inside
is a ParenthesizedExpression, not an IdentifierName.

Added test PossibleBadNegCastNestedParentheses to demonstrate this behavior.

Co-authored-by: CyrusNajmabadi <[email protected]>
[Fact]
public void PossibleBadNegCastNestedParentheses()
{
var source = @"using System;
Copy link
Member

Choose a reason for hiding this comment

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

@copilot use a raw string literal. make the attribute [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/32057")] Also, remove the comment on the test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated in a34f2a8. Changed to use raw string literal, added WorkItem attribute, and removed the comment.

Copilot AI requested a review from CyrusNajmabadi November 16, 2025 21:41
@CyrusNajmabadi CyrusNajmabadi marked this pull request as ready for review November 17, 2025 01:16
@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner November 17, 2025 01:16
@CyrusNajmabadi
Copy link
Member

@dotnet/roslyn-compiler this is ready for review.

@CyrusNajmabadi
Copy link
Member

@jjonescz @jcouv @RikkiGibson ptal.

private static bool IsParenthesizedExpressionInPossibleBadNegCastContext(ParenthesizedExpressionSyntax parenthesized)
{
// Check if it's the left side of a subtraction: (T) - X
return parenthesized.Parent is Syntax.BinaryExpressionSyntax { RawKind: (int)SyntaxKind.SubtractExpression } binary &&
Copy link
Member

@RikkiGibson RikkiGibson Dec 1, 2025

Choose a reason for hiding this comment

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

optional suggestion.

Suggested change
return parenthesized.Parent is Syntax.BinaryExpressionSyntax { RawKind: (int)SyntaxKind.SubtractExpression } binary &&
return parenthesized.Parent is BinaryExpressionSyntax { RawKind: (int)SyntaxKind.SubtractExpression } binary &&

@CyrusNajmabadi CyrusNajmabadi enabled auto-merge (squash) December 1, 2025 23:53
@CyrusNajmabadi CyrusNajmabadi merged commit 04fe0a0 into main Dec 2, 2025
24 of 25 checks passed
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Dec 2, 2025
@CyrusNajmabadi CyrusNajmabadi deleted the copilot/improve-error-messages branch December 2, 2025 11:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve error for casting negative value to enum

4 participants