-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Support declaration and consumption of user-defined Unsigned Right Shift operator. #60616
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -175,7 +175,8 @@ private BoundExpression BindCompoundAssignment(AssignmentExpressionSyntax node, | |
BinaryOperatorSignature bestSignature = best.Signature; | ||
|
||
CheckNativeIntegerFeatureAvailability(bestSignature.Kind, node, diagnostics); | ||
CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, bestSignature.Method, bestSignature.ConstrainedToTypeOpt, diagnostics); | ||
CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, bestSignature.Method, | ||
isUnsignedRightShift: bestSignature.Kind.Operator() == BinaryOperatorKind.UnsignedRightShift, bestSignature.ConstrainedToTypeOpt, diagnostics); | ||
|
||
if (CheckOverflowAtRuntime) | ||
{ | ||
|
@@ -401,7 +402,7 @@ private BoundExpression BindDynamicBinaryOperator( | |
else | ||
{ | ||
Debug.Assert(left.Type is not TypeParameterSymbol); | ||
CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, userDefinedOperator, constrainedToTypeOpt: null, diagnostics); | ||
CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, userDefinedOperator, isUnsignedRightShift: false, constrainedToTypeOpt: null, diagnostics); | ||
} | ||
} | ||
|
||
|
@@ -618,8 +619,12 @@ private BoundExpression BindSimpleBinaryOperator(BinaryExpressionSyntax node, Bi | |
break; | ||
} | ||
|
||
CheckNativeIntegerFeatureAvailability(resultOperatorKind, node, diagnostics); | ||
CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, signature.Method, signature.ConstrainedToTypeOpt, diagnostics); | ||
if (foundOperator) | ||
{ | ||
CheckNativeIntegerFeatureAvailability(resultOperatorKind, node, diagnostics); | ||
CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, signature.Method, | ||
isUnsignedRightShift: resultOperatorKind.Operator() == BinaryOperatorKind.UnsignedRightShift, signature.ConstrainedToTypeOpt, diagnostics); | ||
} | ||
|
||
TypeSymbol resultType = signature.ReturnType; | ||
BoundExpression resultLeft = left; | ||
|
@@ -948,8 +953,9 @@ private BoundExpression BindConditionalLogicalOperator(BinaryExpressionSyntax no | |
{ | ||
Debug.Assert(trueOperator != null && falseOperator != null); | ||
|
||
_ = CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, signature.Method, signature.ConstrainedToTypeOpt, diagnostics) && | ||
CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, kind == BinaryOperatorKind.LogicalAnd ? falseOperator : trueOperator, signature.ConstrainedToTypeOpt, diagnostics); | ||
_ = CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, signature.Method, isUnsignedRightShift: false, signature.ConstrainedToTypeOpt, diagnostics) && | ||
CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, kind == BinaryOperatorKind.LogicalAnd ? falseOperator : trueOperator, | ||
isUnsignedRightShift: false, signature.ConstrainedToTypeOpt, diagnostics); | ||
|
||
return new BoundUserDefinedConditionalLogicalOperator( | ||
node, | ||
|
@@ -2264,7 +2270,7 @@ private BoundExpression BindIncrementOperator(CSharpSyntaxNode node, ExpressionS | |
var signature = best.Signature; | ||
|
||
CheckNativeIntegerFeatureAvailability(signature.Kind, node, diagnostics); | ||
CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, signature.Method, signature.ConstrainedToTypeOpt, diagnostics); | ||
CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, signature.Method, isUnsignedRightShift: false, signature.ConstrainedToTypeOpt, diagnostics); | ||
|
||
var resultPlaceholder = new BoundValuePlaceholder(node, signature.ReturnType).MakeCompilerGenerated(); | ||
|
||
|
@@ -2311,7 +2317,7 @@ private BoundExpression BindIncrementOperator(CSharpSyntaxNode node, ExpressionS | |
/// <summary> | ||
/// Returns false if reported an error, true otherwise. | ||
/// </summary> | ||
private bool CheckConstraintLanguageVersionAndRuntimeSupportForOperator(SyntaxNode node, MethodSymbol? methodOpt, TypeSymbol? constrainedToTypeOpt, BindingDiagnosticBag diagnostics) | ||
private bool CheckConstraintLanguageVersionAndRuntimeSupportForOperator(SyntaxNode node, MethodSymbol? methodOpt, bool isUnsignedRightShift, TypeSymbol? constrainedToTypeOpt, BindingDiagnosticBag diagnostics) | ||
{ | ||
bool result = true; | ||
|
||
|
@@ -2342,10 +2348,28 @@ private bool CheckConstraintLanguageVersionAndRuntimeSupportForOperator(SyntaxNo | |
} | ||
} | ||
|
||
if (methodOpt is not null && SyntaxFacts.IsCheckedOperator(methodOpt.Name) && | ||
Compilation.SourceModule != methodOpt.ContainingModule) | ||
if (methodOpt is null) | ||
{ | ||
if (isUnsignedRightShift) | ||
{ | ||
result &= CheckFeatureAvailability(node, MessageID.IDS_FeatureUnsignedRightShift, diagnostics); | ||
} | ||
} | ||
else | ||
{ | ||
result &= CheckFeatureAvailability(node, MessageID.IDS_FeatureCheckedUserDefinedOperators, diagnostics); | ||
Debug.Assert((methodOpt.Name == WellKnownMemberNames.UnsignedRightShiftOperatorName) == isUnsignedRightShift); | ||
|
||
if (Compilation.SourceModule != methodOpt.ContainingModule) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't understand why the unsigned right shift operator LangVer check is conditioned on resolved method being in source. I would have expected an unconditional LangVer diagnostic for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
{ | ||
if (SyntaxFacts.IsCheckedOperator(methodOpt.Name)) | ||
{ | ||
result &= CheckFeatureAvailability(node, MessageID.IDS_FeatureCheckedUserDefinedOperators, diagnostics); | ||
} | ||
else if (isUnsignedRightShift) | ||
{ | ||
result &= CheckFeatureAvailability(node, MessageID.IDS_FeatureUnsignedRightShift, diagnostics); | ||
} | ||
} | ||
} | ||
|
||
return result; | ||
|
@@ -2686,7 +2710,7 @@ private BoundExpression BindUnaryOperatorCore(CSharpSyntaxNode node, string oper | |
var resultConstant = FoldUnaryOperator(node, resultOperatorKind, resultOperand, resultType, diagnostics); | ||
|
||
CheckNativeIntegerFeatureAvailability(resultOperatorKind, node, diagnostics); | ||
CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, signature.Method, signature.ConstrainedToTypeOpt, diagnostics); | ||
CheckConstraintLanguageVersionAndRuntimeSupportForOperator(node, signature.Method, isUnsignedRightShift: false, signature.ConstrainedToTypeOpt, diagnostics); | ||
|
||
return new BoundUnaryOperator( | ||
node, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1037,6 +1037,8 @@ CurrentToken.Kind is (SyntaxKind.GreaterThanToken or SyntaxKind.GreaterThanEqual | |
operatorToken.Text + operatorToken2.Text + operatorToken3.Text, | ||
operatorToken.ValueText + operatorToken2.ValueText + operatorToken3.ValueText, | ||
operatorToken3.GetTrailingTrivia()); | ||
|
||
operatorToken = CheckFeatureAvailability(operatorToken, MessageID.IDS_FeatureUnsignedRightShift, forceWarning: true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Why do a parser LangVer check as opposed to add check in Binder_Cref? #Closed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Just following the established pattern. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that these are warnings, not errors |
||
} | ||
else | ||
{ | ||
|
@@ -1057,7 +1059,7 @@ CurrentToken.Kind is (SyntaxKind.GreaterThanToken or SyntaxKind.GreaterThanEqual | |
int width = nonOverloadableOperator.Width; | ||
SyntaxDiagnosticInfo rawInfo = new SyntaxDiagnosticInfo(offset, width, ErrorCode.ERR_OvlOperatorExpected); | ||
SyntaxDiagnosticInfo crefInfo = new SyntaxDiagnosticInfo(offset, width, ErrorCode.WRN_ErrorOverride, rawInfo, rawInfo.Code); | ||
operatorToken = WithAdditionalDiagnostics(operatorToken, crefInfo); // PROTOTYPE(UnsignedRightShift): Add a test for this warning | ||
operatorToken = WithAdditionalDiagnostics(operatorToken, crefInfo); | ||
} | ||
} | ||
else | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -358,6 +358,7 @@ private void CheckOperatorSignatures(BindingDiagnosticBag diagnostics) | |
|
||
case WellKnownMemberNames.LeftShiftOperatorName: | ||
case WellKnownMemberNames.RightShiftOperatorName: | ||
case WellKnownMemberNames.UnsignedRightShiftOperatorName: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: consider updating comment in |
||
CheckShiftSignature(diagnostics); | ||
break; | ||
|
||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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.
Consider just passing the operator kind, and letting the "is unsigned right shift" logic be contained within this method, rather than needing to be specified by a caller. #WontFix