Skip to content

Commit c70ea07

Browse files
[automated] Merge branch 'main' => 'main-vs-deps' (#79229)
I detected changes in the main branch which have not been merged yet to main-vs-deps. I'm a robot and am configured to help you automatically keep main-vs-deps up to date, so I've opened this PR. This PR merges commits made on main by the following committers: * AlekseyTs ## Instructions for merging from UI This PR will not be auto-merged. When pull request checks pass, complete this PR by creating a merge commit, *not* a squash or rebase commit. <img alt="merge button instructions" src="https://i.imgur.com/GepcNJV.png" width="300" /> If this repo does not allow creating merge commits from the GitHub UI, use command line instructions. ## Instructions for merging via command line Run these commands to merge this pull request from the command line. ``` sh git fetch git checkout main git pull --ff-only git checkout main-vs-deps git pull --ff-only git merge --no-ff main # If there are merge conflicts, resolve them and then run git merge --continue to complete the merge # Pushing the changes to the PR branch will re-trigger PR validation. git push https://github.com/dotnet/roslyn HEAD:merge/main-to-main-vs-deps ``` <details> <summary>or if you are using SSH</summary> ``` git push git@github.com:dotnet/roslyn HEAD:merge/main-to-main-vs-deps ``` </details> After PR checks are complete push the branch ``` git push ``` ## Instructions for resolving conflicts :warning: If there are merge conflicts, you will need to resolve them manually before merging. You can do this [using GitHub][resolve-github] or using the [command line][resolve-cli]. [resolve-github]: https://help.github.com/articles/resolving-a-merge-conflict-on-github/ [resolve-cli]: https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/ ## Instructions for updating this pull request Contributors to this repo have permission update this pull request by pushing to the branch 'merge/main-to-main-vs-deps'. This can be done to resolve conflicts or make other changes to this pull request before it is merged. The provided examples assume that the remote is named 'origin'. If you have a different remote name, please replace 'origin' with the name of your remote. ``` git fetch git checkout -b merge/main-to-main-vs-deps origin/main-vs-deps git pull https://github.com/dotnet/roslyn merge/main-to-main-vs-deps (make changes) git commit -m "Updated PR with my changes" git push https://github.com/dotnet/roslyn HEAD:merge/main-to-main-vs-deps ``` <details> <summary>or if you are using SSH</summary> ``` git fetch git checkout -b merge/main-to-main-vs-deps origin/main-vs-deps git pull git@github.com:dotnet/roslyn merge/main-to-main-vs-deps (make changes) git commit -m "Updated PR with my changes" git push git@github.com:dotnet/roslyn HEAD:merge/main-to-main-vs-deps ``` </details> Contact .NET Core Engineering (dotnet/dnceng) if you have questions or issues. Also, if this PR was generated incorrectly, help us fix it. See https://github.com/dotnet/arcade/blob/main/.github/workflows/scripts/inter-branch-merge.ps1.
2 parents c2633e2 + 73de482 commit c70ea07

File tree

4 files changed

+2299
-319
lines changed

4 files changed

+2299
-319
lines changed

src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs

Lines changed: 111 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,33 +1092,49 @@ private bool BindSimpleBinaryOperatorParts(BinaryExpressionSyntax node, BindingD
10921092
out LookupResultKind resultKind, out ImmutableArray<MethodSymbol> originalUserDefinedOperators,
10931093
out BinaryOperatorSignature resultSignature, out BinaryOperatorAnalysisResult best)
10941094
{
1095-
bool foundOperator;
1096-
10971095
if (!IsTypelessExpressionAllowedInBinaryOperator(kind, left, right))
10981096
{
10991097
resultKind = LookupResultKind.OverloadResolutionFailure;
11001098
originalUserDefinedOperators = default(ImmutableArray<MethodSymbol>);
11011099
best = default(BinaryOperatorAnalysisResult);
1100+
resultSignature = new BinaryOperatorSignature(kind, leftType: null, rightType: null, CreateErrorType());
1101+
return false;
11021102
}
1103-
else
1104-
{
1105-
best = this.BinaryOperatorOverloadResolution(kind, isChecked: CheckOverflowAtRuntime, left, right, node, diagnostics, out resultKind, out originalUserDefinedOperators);
1106-
}
11071103

1108-
// However, as an implementation detail, we never "fail to find an applicable
1109-
// operator" during overload resolution if we have x == null, x == default, etc. We always
1110-
// find at least the reference conversion object == object; the overload resolution
1111-
// code does not reject that. Therefore what we should do is only bind
1112-
// "x == null" as a nullable-to-null comparison if overload resolution chooses
1113-
// the reference conversion.
1104+
bool isChecked = CheckOverflowAtRuntime;
1105+
OverloadResolution.GetStaticUserDefinedBinaryOperatorMethodNames(kind, isChecked, out string name1, out string name2Opt);
1106+
best = this.BinaryOperatorOverloadResolution(kind, isChecked, name1, name2Opt, left, right, node, diagnostics, out resultKind, out originalUserDefinedOperators);
1107+
1108+
return bindSimpleBinaryOperatorPartsContinue(node, diagnostics, left, right, kind, ref resultKind, ref originalUserDefinedOperators, out resultSignature, ref best, isChecked, name1, name2Opt);
11141109

1115-
if (!best.HasValue)
1116-
{
1117-
resultSignature = new BinaryOperatorSignature(kind, leftType: null, rightType: null, CreateErrorType());
1118-
foundOperator = false;
1119-
}
1120-
else
1110+
bool bindSimpleBinaryOperatorPartsContinue(
1111+
BinaryExpressionSyntax node,
1112+
BindingDiagnosticBag diagnostics,
1113+
BoundExpression left,
1114+
BoundExpression right,
1115+
BinaryOperatorKind kind,
1116+
ref LookupResultKind resultKind,
1117+
ref ImmutableArray<MethodSymbol> originalUserDefinedOperators,
1118+
out BinaryOperatorSignature resultSignature,
1119+
ref BinaryOperatorAnalysisResult best,
1120+
bool isChecked,
1121+
string name1,
1122+
string name2Opt)
11211123
{
1124+
// However, as an implementation detail, we never "fail to find an applicable
1125+
// operator" during overload resolution if we have x == null, x == default, etc. We always
1126+
// find at least the reference conversion object == object; the overload resolution
1127+
// code does not reject that. Therefore what we should do is only bind
1128+
// "x == null" as a nullable-to-null comparison if overload resolution chooses
1129+
// the reference conversion.
1130+
1131+
if (!best.HasValue)
1132+
{
1133+
resultSignature = new BinaryOperatorSignature(kind, leftType: null, rightType: null, CreateErrorType());
1134+
return false;
1135+
}
1136+
1137+
bool foundOperator;
11221138
var signature = best.Signature;
11231139

11241140
if (signature.Method is { } bestMethod)
@@ -1155,9 +1171,27 @@ private bool BindSimpleBinaryOperatorParts(BinaryExpressionSyntax node, BindingD
11551171
bool rightDefault = right.IsLiteralDefault();
11561172
foundOperator = !isObjectEquality || BuiltInOperators.IsValidObjectEquality(Conversions, leftType, leftNull, leftDefault, rightType, rightNull, rightDefault, ref useSiteInfo);
11571173
diagnostics.Add(node, useSiteInfo);
1174+
1175+
if (!foundOperator)
1176+
{
1177+
Debug.Assert(isObjectEquality);
1178+
1179+
// Try extension operators since predefined object equality was not applicable
1180+
LookupResultKind extensionResultKind;
1181+
ImmutableArray<MethodSymbol> extensionOriginalUserDefinedOperators;
1182+
BinaryOperatorAnalysisResult? extensionBest = BinaryOperatorExtensionOverloadResolution(kind, isChecked, name1, name2Opt, left, right, node, diagnostics, out extensionResultKind, out extensionOriginalUserDefinedOperators);
1183+
1184+
if (extensionBest.HasValue)
1185+
{
1186+
best = extensionBest.GetValueOrDefault();
1187+
resultKind = extensionResultKind;
1188+
originalUserDefinedOperators = extensionOriginalUserDefinedOperators;
1189+
foundOperator = bindSimpleBinaryOperatorPartsContinue(node, diagnostics, left, right, kind, ref resultKind, ref originalUserDefinedOperators, out resultSignature, ref best, isChecked, name1, name2Opt);
1190+
}
1191+
}
11581192
}
1193+
return foundOperator;
11591194
}
1160-
return foundOperator;
11611195
}
11621196

11631197
#nullable enable
@@ -1914,13 +1948,28 @@ private BinaryOperatorAnalysisResult BinaryOperatorOverloadResolution(
19141948
{
19151949
OverloadResolution.GetStaticUserDefinedBinaryOperatorMethodNames(kind, isChecked, out string name1, out string name2Opt);
19161950

1951+
return BinaryOperatorOverloadResolution(kind, isChecked, name1, name2Opt, left, right, node, diagnostics, out resultKind, out originalUserDefinedOperators);
1952+
}
1953+
1954+
private BinaryOperatorAnalysisResult BinaryOperatorOverloadResolution(
1955+
BinaryOperatorKind kind,
1956+
bool isChecked,
1957+
string name1,
1958+
string name2Opt,
1959+
BoundExpression left,
1960+
BoundExpression right,
1961+
CSharpSyntaxNode node,
1962+
BindingDiagnosticBag diagnostics,
1963+
out LookupResultKind resultKind,
1964+
out ImmutableArray<MethodSymbol> originalUserDefinedOperators)
1965+
{
19171966
BinaryOperatorAnalysisResult possiblyBest = BinaryOperatorNonExtensionOverloadResolution(kind, isChecked, name1, name2Opt, left, right, node, diagnostics, out resultKind, out originalUserDefinedOperators);
19181967

19191968
if (!possiblyBest.HasValue && resultKind != LookupResultKind.Ambiguous)
19201969
{
19211970
LookupResultKind extensionResultKind;
19221971
ImmutableArray<MethodSymbol> extensionOriginalUserDefinedOperators;
1923-
BinaryOperatorAnalysisResult? extensionBest = extensionOverloadResolution(kind, isChecked, name1, name2Opt, left, right, node, diagnostics, out extensionResultKind, out extensionOriginalUserDefinedOperators);
1972+
BinaryOperatorAnalysisResult? extensionBest = BinaryOperatorExtensionOverloadResolution(kind, isChecked, name1, name2Opt, left, right, node, diagnostics, out extensionResultKind, out extensionOriginalUserDefinedOperators);
19241973

19251974
if (extensionBest.HasValue && (extensionBest.GetValueOrDefault().HasValue || (originalUserDefinedOperators.IsEmpty && !extensionOriginalUserDefinedOperators.IsEmpty)))
19261975
{
@@ -1931,55 +1980,55 @@ private BinaryOperatorAnalysisResult BinaryOperatorOverloadResolution(
19311980
}
19321981

19331982
return possiblyBest;
1983+
}
19341984

1935-
#nullable enable
1985+
#nullable enable
19361986

1937-
BinaryOperatorAnalysisResult? extensionOverloadResolution(
1938-
BinaryOperatorKind kind,
1939-
bool isChecked,
1940-
string name1,
1941-
string name2Opt,
1942-
BoundExpression left,
1943-
BoundExpression right,
1944-
CSharpSyntaxNode node,
1945-
BindingDiagnosticBag diagnostics,
1946-
out LookupResultKind resultKind,
1947-
out ImmutableArray<MethodSymbol> originalUserDefinedOperators)
1987+
private BinaryOperatorAnalysisResult? BinaryOperatorExtensionOverloadResolution(
1988+
BinaryOperatorKind kind,
1989+
bool isChecked,
1990+
string name1,
1991+
string name2Opt,
1992+
BoundExpression left,
1993+
BoundExpression right,
1994+
CSharpSyntaxNode node,
1995+
BindingDiagnosticBag diagnostics,
1996+
out LookupResultKind resultKind,
1997+
out ImmutableArray<MethodSymbol> originalUserDefinedOperators)
1998+
{
1999+
resultKind = LookupResultKind.Empty;
2000+
originalUserDefinedOperators = [];
2001+
2002+
if (left.Type is null && right.Type is null)
19482003
{
1949-
resultKind = LookupResultKind.Empty;
1950-
originalUserDefinedOperators = [];
2004+
return null;
2005+
}
19512006

1952-
if (left.Type is null && right.Type is null)
1953-
{
1954-
return null;
1955-
}
2007+
var result = BinaryOperatorOverloadResolutionResult.GetInstance();
2008+
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
2009+
var extensionDeclarationsInSingleScope = ArrayBuilder<NamedTypeSymbol>.GetInstance();
2010+
BinaryOperatorAnalysisResult? possiblyBest = null;
19562011

1957-
var result = BinaryOperatorOverloadResolutionResult.GetInstance();
1958-
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
1959-
var extensionDeclarationsInSingleScope = ArrayBuilder<NamedTypeSymbol>.GetInstance();
1960-
BinaryOperatorAnalysisResult? possiblyBest = null;
2012+
foreach (var scope in new ExtensionScopes(this))
2013+
{
2014+
extensionDeclarationsInSingleScope.Clear();
2015+
scope.Binder.GetExtensionDeclarations(extensionDeclarationsInSingleScope, this);
19612016

1962-
foreach (var scope in new ExtensionScopes(this))
2017+
if (this.OverloadResolution.BinaryOperatorExtensionOverloadResolutionInSingleScope(extensionDeclarationsInSingleScope, kind, isChecked, name1, name2Opt, left, right, result, ref useSiteInfo))
19632018
{
1964-
extensionDeclarationsInSingleScope.Clear();
1965-
scope.Binder.GetExtensionDeclarations(extensionDeclarationsInSingleScope, this);
1966-
1967-
if (this.OverloadResolution.BinaryOperatorExtensionOverloadResolutionInSingleScope(extensionDeclarationsInSingleScope, kind, isChecked, name1, name2Opt, left, right, result, ref useSiteInfo))
1968-
{
1969-
possiblyBest = BinaryOperatorAnalyzeOverloadResolutionResult(result, out resultKind, out originalUserDefinedOperators);
1970-
break;
1971-
}
2019+
possiblyBest = BinaryOperatorAnalyzeOverloadResolutionResult(result, out resultKind, out originalUserDefinedOperators);
2020+
break;
19722021
}
2022+
}
19732023

1974-
diagnostics.Add(node, useSiteInfo);
2024+
diagnostics.Add(node, useSiteInfo);
19752025

1976-
extensionDeclarationsInSingleScope.Free();
1977-
result.Free();
1978-
return possiblyBest;
1979-
}
2026+
extensionDeclarationsInSingleScope.Free();
2027+
result.Free();
2028+
return possiblyBest;
2029+
}
19802030

19812031
#nullable disable
1982-
}
19832032

19842033
private BinaryOperatorAnalysisResult BinaryOperatorNonExtensionOverloadResolution(
19852034
BinaryOperatorKind kind,
@@ -3758,18 +3807,18 @@ private bool CheckConstraintLanguageVersionAndRuntimeSupportForOperator(SyntaxNo
37583807

37593808
if (Compilation.SourceModule != methodOpt.ContainingModule)
37603809
{
3761-
if (SyntaxFacts.IsCheckedOperator(methodOpt.Name))
3810+
if (methodOpt.GetIsNewExtensionMember())
3811+
{
3812+
result &= CheckFeatureAvailability(node, MessageID.IDS_FeatureExtensions, diagnostics);
3813+
}
3814+
else if (SyntaxFacts.IsCheckedOperator(methodOpt.Name))
37623815
{
37633816
result &= CheckFeatureAvailability(node, MessageID.IDS_FeatureCheckedUserDefinedOperators, diagnostics);
37643817
}
37653818
else if (isUnsignedRightShift)
37663819
{
37673820
result &= CheckFeatureAvailability(node, MessageID.IDS_FeatureUnsignedRightShift, diagnostics);
37683821
}
3769-
else if (methodOpt.GetIsNewExtensionMember())
3770-
{
3771-
result &= CheckFeatureAvailability(node, MessageID.IDS_FeatureExtensions, diagnostics);
3772-
}
37733822
}
37743823
}
37753824

src/Compilers/CSharp/Portable/Binder/Binder_TupleOperators.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,6 @@ private TupleBinaryOperatorInfo BindTupleBinaryOperatorInfo(BinaryExpressionSynt
9595
return BindTupleBinaryOperatorNestedInfo(node, kind, left, right, diagnostics);
9696
}
9797

98-
// https://github.com/dotnet/roslyn/issues/76130: Add test coverage for this code path
99-
10098
BoundExpression comparison = BindSimpleBinaryOperator(node, diagnostics, left, right, leaveUnconvertedIfInterpolatedString: false);
10199
switch (comparison)
102100
{

src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,18 +179,13 @@ protected static DeclarationModifiers MakeDeclarationModifiers(bool isCompoundAs
179179
bool isExplicitInterfaceImplementation = methodKind == MethodKind.ExplicitInterfaceImplementation;
180180
var defaultAccess = inInterface && !isExplicitInterfaceImplementation ? DeclarationModifiers.Public : DeclarationModifiers.Private;
181181
var allowedModifiers =
182-
DeclarationModifiers.Unsafe;
182+
DeclarationModifiers.Unsafe | DeclarationModifiers.Extern;
183183

184184
if (!isCompoundAssignmentOrIncrementAssignment)
185185
{
186186
allowedModifiers |= DeclarationModifiers.Static;
187187
}
188188

189-
if (!inExtension)
190-
{
191-
allowedModifiers |= DeclarationModifiers.Extern;
192-
}
193-
194189
if (!isExplicitInterfaceImplementation)
195190
{
196191
allowedModifiers |= DeclarationModifiers.AccessibilityMask;

0 commit comments

Comments
 (0)