-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Extensions: pattern-based constructs #78480
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
Changes from 10 commits
7f23afa
2c211ce
7674a00
75aa581
f5025cf
5a332c4
b6cc211
dc8d7c7
86da11d
623b9d7
d97a116
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 |
---|---|---|
|
@@ -137,11 +137,11 @@ internal BoundExpression MakeInvocationExpression( | |
} | ||
|
||
BoundExpression result = BindInvocationExpression( | ||
node, node, methodName, boundExpression, analyzedArguments, diagnostics, queryClause, | ||
ignoreNormalFormIfHasValidParamsParameter: ignoreNormalFormIfHasValidParamsParameter, | ||
node, node, methodName, boundExpression, analyzedArguments, diagnostics, acceptOnlyMethods: !allowFieldsAndProperties, | ||
queryClause, ignoreNormalFormIfHasValidParamsParameter: ignoreNormalFormIfHasValidParamsParameter, | ||
disallowExpandedNonArrayParams: disallowExpandedNonArrayParams); | ||
|
||
// Query operator can't be called dynamically. | ||
// Query operator can't be called dynamically. | ||
if (queryClause != null && result.Kind == BoundKind.DynamicInvocation) | ||
{ | ||
// the error has already been reported by BindInvocationExpression | ||
|
@@ -245,7 +245,7 @@ BoundExpression bindArgumentsAndInvocation(InvocationExpressionSyntax node, Boun | |
boundExpression = CheckValue(boundExpression, BindValueKind.RValueOrMethodGroup, diagnostics); | ||
string name = boundExpression.Kind == BoundKind.MethodGroup ? GetName(node.Expression) : null; | ||
BindArgumentsAndNames(node.ArgumentList, diagnostics, analyzedArguments, allowArglist: true); | ||
return BindInvocationExpression(node, node.Expression, name, boundExpression, analyzedArguments, diagnostics); | ||
return BindInvocationExpression(node, node.Expression, name, boundExpression, analyzedArguments, diagnostics, acceptOnlyMethods: false); | ||
} | ||
|
||
static bool receiverIsInvocation(InvocationExpressionSyntax node, out InvocationExpressionSyntax nested) | ||
|
@@ -324,6 +324,7 @@ private BoundExpression BindInvocationExpression( | |
BoundExpression boundExpression, | ||
AnalyzedArguments analyzedArguments, | ||
BindingDiagnosticBag diagnostics, | ||
bool acceptOnlyMethods, | ||
CSharpSyntaxNode queryClause = null, | ||
bool ignoreNormalFormIfHasValidParamsParameter = false, | ||
bool disallowExpandedNonArrayParams = false) | ||
|
@@ -356,7 +357,7 @@ private BoundExpression BindInvocationExpression( | |
ignoreNormalFormIfHasValidParamsParameter: ignoreNormalFormIfHasValidParamsParameter, | ||
disallowExpandedNonArrayParams: disallowExpandedNonArrayParams, | ||
anyApplicableCandidates: out _, | ||
acceptOnlyMethods: false); | ||
acceptOnlyMethods: acceptOnlyMethods); | ||
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. |
||
} | ||
else if ((object)(delegateType = GetDelegateType(boundExpression)) != null) | ||
{ | ||
|
@@ -727,7 +728,7 @@ private BoundExpression BindMethodGroupInvocation( | |
Debug.Assert(extensionMemberAccess.Kind != BoundKind.MethodGroup); | ||
|
||
extensionMemberAccess = CheckValue(extensionMemberAccess, BindValueKind.RValue, diagnostics); | ||
BoundExpression extensionMemberInvocation = BindInvocationExpression(syntax, expression, methodName: null, extensionMemberAccess, analyzedArguments, diagnostics); | ||
BoundExpression extensionMemberInvocation = BindInvocationExpression(syntax, expression, methodName: null, extensionMemberAccess, analyzedArguments, diagnostics, acceptOnlyMethods: false); | ||
anyApplicableCandidates = !extensionMemberInvocation.HasAnyErrors; | ||
return extensionMemberInvocation; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1058,7 +1058,7 @@ deconstructMethod is null && | |
if (deconstructMethod is null) | ||
hasErrors = true; | ||
|
||
int skippedExtensionParameters = deconstructMethod?.IsExtensionMethod == true ? 1 : 0; // Tracked by https://github.com/dotnet/roslyn/issues/76130: Test this code path with new extensions | ||
int skippedExtensionParameters = deconstructMethod?.IsExtensionMethod == true ? 1 : 0; | ||
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. 📝 Covered by |
||
for (int i = 0; i < node.Subpatterns.Count; i++) | ||
{ | ||
var subPattern = node.Subpatterns[i]; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -627,7 +627,7 @@ static SafeContext getDeclarationValEscape(BoundTypeExpression typeExpression, S | |
// and so the ref safety of the pattern is equivalent to a `Deconstruct(out var ...)` invocation | ||
// where "safe-context inference of declaration expressions" would have the same effect. | ||
if (node.DeconstructMethod is { } m && | ||
tryGetThisParameter(m)?.EffectiveScope == ScopedKind.None) | ||
tryGetReceiverParameter(m)?.EffectiveScope == ScopedKind.None) | ||
{ | ||
using (new PatternInput(this, _localScopeDepth)) | ||
{ | ||
|
@@ -637,12 +637,16 @@ static SafeContext getDeclarationValEscape(BoundTypeExpression typeExpression, S | |
|
||
return base.VisitRecursivePattern(node); | ||
|
||
static ParameterSymbol? tryGetThisParameter(MethodSymbol method) | ||
static ParameterSymbol? tryGetReceiverParameter(MethodSymbol method) | ||
{ | ||
if (method.IsExtensionMethod) // Tracked by https://github.com/dotnet/roslyn/issues/76130: Test this code path with new extensions | ||
if (method.IsExtensionMethod) | ||
{ | ||
return method.Parameters is [{ } firstParameter, ..] ? firstParameter : null; | ||
} | ||
else if (method.GetIsNewExtensionMember()) | ||
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. 📝 Covered by |
||
{ | ||
return method.ContainingType.ExtensionParameter; | ||
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. 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'm not sure I understand the question. |
||
} | ||
|
||
return method.TryGetThisParameter(out var thisParameter) ? thisParameter : null; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -652,7 +652,7 @@ private void MakeExplicitParameterTypeInferences(Binder binder, BoundExpression | |
} | ||
else if (IsUnfixedTypeParameter(target) && !target.NullableAnnotation.IsAnnotated() && kind is ExactOrBoundsKind.LowerBound) | ||
{ | ||
var ordinal = GetOrdinal((TypeParameterSymbol)target.Type); // Tracked by https://github.com/dotnet/roslyn/issues/76130 : test nullability scenario where the override of ordinals matters | ||
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. 📝 Covered by |
||
var ordinal = GetOrdinal((TypeParameterSymbol)target.Type); | ||
_nullableAnnotationLowerBounds[ordinal] = _nullableAnnotationLowerBounds[ordinal].Join(argumentType.NullableAnnotation); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -431,6 +431,24 @@ public BoundExpression AssignmentExpression(BoundExpression left, BoundExpressio | |
return AssignmentExpression(Syntax, left, right, isRef: isRef, wasCompilerGenerated: true); | ||
} | ||
|
||
public BoundExpression ConvertReceiverForExtensionMemberIfNeeded(Symbol member, BoundExpression receiver) | ||
{ | ||
if (member.GetIsNewExtensionMember()) | ||
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. |
||
{ | ||
Debug.Assert(!member.IsStatic); | ||
ParameterSymbol? extensionParameter = member.ContainingType.ExtensionParameter; | ||
Debug.Assert(extensionParameter is not null); | ||
#if DEBUG | ||
var discardedUseSiteInfo = CompoundUseSiteInfo<AssemblySymbol>.Discarded; | ||
Debug.Assert(Conversions.IsValidExtensionMethodThisArgConversion(this.Compilation.Conversions.ClassifyConversionFromType(receiver.Type, extensionParameter.Type, isChecked: false, ref discardedUseSiteInfo))); | ||
#endif | ||
|
||
return this.Convert(extensionParameter.Type, receiver); | ||
} | ||
|
||
return receiver; | ||
} | ||
|
||
/// <summary> | ||
/// Creates a general assignment that might be instrumented. | ||
/// </summary> | ||
|
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.
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.
📝 Covered by
Deconstruct_01
andDeconstruct_02