-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Disallow ref
to in
/ref readonly
method parameter conversion
#71531
Conversation
src/Compilers/CSharp/Test/Emit2/Semantics/RefReadonlyParameterTests.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Test/Emit2/Semantics/RefReadonlyParameterTests.cs
Outdated
Show resolved
Hide resolved
// In method group conversions, | ||
// - 'in' is allowed to be converted to 'ref', | ||
// - 'ref readonly' is allowed to be converted to 'ref' or 'in', | ||
// - 'in' is allowed to be converted to 'ref readonly'. |
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.
Reading through this chart, occurs to me that out
should be allowed to convert to ref
. I do not want to change the scope of the PR to include this. Just a thought that occured.
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.
Seems safe, but that probably needs a separate proposal, right?
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.
Agree. Not sure it's worth it, just occurred to me when reading this particular part of the change.
@@ -1937,7 +1937,7 @@ internal bool MethodIsCompatibleWithDelegateOrFunctionPointer(BoundExpression? r | |||
// * Every ref or similar parameter has an identity conversion to the corresponding target parameter | |||
// Note the addition of the reference requirement: it means that for delegate type void D(int i), void M(long l) is | |||
// _applicable_, but not _compatible_. | |||
if (!hasConversion(this, delegateType.TypeKind, Conversions, delegateParameter.Type, methodParameter.Type, delegateParameter.RefKind, methodParameter.RefKind, ref useSiteInfo)) | |||
if (!hasConversion(delegateType.TypeKind, Conversions, source: delegateParameter.Type, destination: methodParameter.Type, sourceRefKind: delegateParameter.RefKind, destinationRefKind: methodParameter.RefKind, checkingReturns: false, ref useSiteInfo)) |
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 (!hasConversion(delegateType.TypeKind, Conversions, source: delegateParameter.Type, destination: methodParameter.Type, sourceRefKind: delegateParameter.RefKind, destinationRefKind: methodParameter.RefKind, checkingReturns: false, ref useSiteInfo))
It looks like this line became too long to fit an average screen. Consider splitting it #Closed
@@ -1958,7 +1958,7 @@ internal bool MethodIsCompatibleWithDelegateOrFunctionPointer(BoundExpression? r | |||
bool returnsMatch = delegateOrFuncPtrMethod switch | |||
{ | |||
{ RefKind: RefKind.None, ReturnsVoid: true } => method.ReturnsVoid, | |||
{ RefKind: var destinationRefKind } => hasConversion(this, delegateType.TypeKind, Conversions, methodReturnType, delegateReturnType, method.RefKind, destinationRefKind, ref useSiteInfo), | |||
{ RefKind: var destinationRefKind } => hasConversion(delegateType.TypeKind, Conversions, source: methodReturnType, destination: delegateReturnType, sourceRefKind: method.RefKind, destinationRefKind: destinationRefKind, checkingReturns: true, ref useSiteInfo), |
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.
{ RefKind: var destinationRefKind } => hasConversion(delegateType.TypeKind, Conversions, source: methodReturnType, destination: delegateReturnType, sourceRefKind: method.RefKind, destinationRefKind: destinationRefKind, checkingReturns: true, ref useSiteInfo),
Consider splitting this line too #Closed
// Allowed ref kind mismatches between parameters have already been checked by overload resolution. | ||
if (checkingReturns | ||
? sourceRefKind != destinationRefKind | ||
: (sourceRefKind != RefKind.None) != (destinationRefKind != RefKind.None)) |
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.
@@ -1488,7 +1488,7 @@ private static LambdaConversionResult IsAnonymousFunctionCompatibleWithDelegate( | |||
{ | |||
for (int p = 0; p < delegateParameters.Length; ++p) | |||
{ | |||
if (!OverloadResolution.AreRefsCompatibleForMethodConversion(delegateParameters[p].RefKind, anonymousFunction.RefKind(p), compilation) || | |||
if (!OverloadResolution.AreRefsCompatibleForMethodConversion(source: anonymousFunction.RefKind(p), destination: delegateParameters[p].RefKind, compilation) || |
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.
@@ -3305,7 +3305,7 @@ internal EffectiveParameters(ImmutableArray<TypeWithAnnotations> types, Immutabl | |||
return argRefKind; | |||
} | |||
} | |||
else if (AreRefsCompatibleForMethodConversion(paramRefKind, argRefKind, binder.Compilation)) | |||
else if (AreRefsCompatibleForMethodConversion(source: paramRefKind, destination: argRefKind, binder.Compilation)) |
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.
// In method group conversions, 'in' is allowed to match 'ref' and 'ref readonly' is allowed to match 'ref' or 'in'. | ||
internal static bool AreRefsCompatibleForMethodConversion(RefKind x, RefKind y, CSharpCompilation compilation) | ||
// In method group conversions, | ||
// - 'in' is allowed to be converted to 'ref', |
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.
// - 'in' is allowed to be converted to 'ref', | ||
// - 'ref readonly' is allowed to be converted to 'ref' or 'in', | ||
// - 'in' is allowed to be converted to 'ref readonly'. | ||
internal static bool AreRefsCompatibleForMethodConversion(RefKind source, RefKind destination, CSharpCompilation compilation) |
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 with review pass (commit 4), tests are not looked at |
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 5). I didn't do thorough review of test, relied on @jaredpar sign-off for that.
Primarily reviewed those, made sure they lined up with spec and eexpectations. |
Fixes #71383.
Corresponding speclet update: dotnet/csharplang#7820
Test plan: #68056