-
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
Adding IsConst modreq on ref readonly signatures #19658
Adding IsConst modreq on ref readonly signatures #19658
Conversation
internal override bool IsConstModifierType(PEModuleSymbol moduleSymbol, TypeSymbol type) | ||
{ | ||
return type.ToDisplayString() == WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsConst); | ||
} |
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.
Comparing symbols by full name is probably not be the best way to do it. Looking up a better alternative. #Closed
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 a similar scenario like IsVolatileModfifierType
. Can we re-use that approach here? #Resolved
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.
Unfortunately, no. Unless there is something I'm missing, IsConst
is not a special library type :(
In reply to: 117829472 [](ancestors = 117829472)
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.
Perhaps the same approach as SymbolFactory.GetSystemTypeSymbol
. #Resolved
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.
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.
This seems simple enough to fix now vs. needing a PROTOTYPE comment to fix later. #Resolved
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.
Comparing symbols by full name is probably not be the best way to do it. Looking up a better alternative.
Given that this is not a SpecialType, I think name comparison is the only right way to do that. If performance is a concern we can compare type name and namespace names separately, then calling ToDisplayString won't be needed. #Closed
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 going with name comparing, should definitely compare namespace/type name parts separately. I think ToDisplay will concat them every time
In reply to: 118063143 [](ancestors = 118063143)
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.
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.
From what I tracked down, it ends up doing a lookup in NamespaceOrTypeSymbol
based on string comparison as well. Will separate the comparison to namespace/type pair to improve performance.
In reply to: 117866143 [](ancestors = 117866143)
|
||
for (;;) | ||
customModifiers = DecodeModifiersOrThrow(ref signatureReader, out typeCode, acceptRequiredModifier: type => |
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.
DecodeModifiersOrThrow [](start = 34, length = 22)
This was refactored since it shares the same behavior as DecodeModifiersOrThrow(), making use of the additional parameter. #Closed
cc @VSadov @dotnet/roslyn-compiler #Closed |
out _lazyParameters, alsoCopyParamsModifier: true); | ||
} | ||
} | ||
else if (_refKind == RefKind.RefReadOnly && (this.IsVirtual || this.IsAbstract)) | ||
{ | ||
var isConst = withTypeParamsBinder.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_IsConst, diagnostics, syntax); |
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.
What if the type is missing? Consider that custom mscorlibs may not have this type. #ByDesign
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.
Yes. I've a test that specifically looks for that. Check ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable
in IsConstModifierTests.cs
.
The method Binder.GetWellKnownType()
will report such errors to the passed diagnostics bag.
In reply to: 117828511 [](ancestors = 117828511)
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 the name isConstType
vs. isConst
. The former is a bit more descriptive and seems more consistent with other names in the method. The latter can be misread as describing the mutable state of a value. #Resolved
@@ -48,6 +50,25 @@ internal abstract class SourceParameterSymbol : SourceParameterSymbolBase | |||
identifier.Parent.GetLocation()); | |||
} | |||
|
|||
if (shouldPlaceIsConstModifier && refKind == RefKind.RefReadOnly && (owner.IsVirtual || owner.IsAbstract)) | |||
{ | |||
var isConst = context.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_IsConst, declarationDiagnostics, syntax); |
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.
What if the type is missing? consider custom mscorlib may not have this type. #ByDesign
@@ -273,6 +273,14 @@ internal sealed class SourcePropertySymbol : PropertySymbol, IAttributeTargetSym | |||
_lazyParameters = CustomModifierUtils.CopyParameterCustomModifiers(overriddenOrImplementedProperty.Parameters, _lazyParameters, alsoCopyParamsModifier: isOverride); | |||
} | |||
} | |||
else if (_refKind == RefKind.RefReadOnly && (this.IsVirtual || this.IsAbstract)) | |||
{ | |||
var isConst = bodyBinder.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_IsConst, diagnostics, syntax); |
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.
Same #ByDesign
@@ -49,6 +49,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE | |||
Return False | |||
End Function | |||
|
|||
Friend Overrides Function IsConstModifierType(moduleSymbol As PEModuleSymbol, type As TypeSymbol) As Boolean | |||
' VB doesn't deal with ref-readonly parameters or return-types. | |||
Return False |
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.
Don't understand why we are returning False
here. Even if VB doesn't deal with these typse returning False
here still seems wrong. If the function isn't implemented it should throw, not return the (potentially) wrong answer. #ByDesign
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.
This means that if VB MetadataDecoder
tries to read a symbol with a modreq of type IsConst
, it will return False
meaning it doesn't support it, and the symbol will be marked appropriately. Check IsVolatileModifierType()
in the same file.
In reply to: 117828980 [](ancestors = 117828980)
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 that's the case then we should consider renaming both of these methods. The name simply does not match up to the actual implementation. Consider this code
var isConst = IsConstModifierType(type);
99% of developers who look at that line are going to interpret this as determining if type
is the const modifier. In reality it's detecting if a) it's the const modifier and b) the present language supports it. The 1% who will understand the behavior are those who realize the name of the method is wrong.
#Resolved
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.
internal override bool IsConstModifierType(PEModuleSymbol moduleSymbol, TypeSymbol type) | ||
{ | ||
return type.ToDisplayString() == WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsConst); | ||
} |
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 a similar scenario like IsVolatileModfifierType
. Can we re-use that approach here? #Resolved
} | ||
|
||
[Fact] | ||
public void ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable() |
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.
ProperErrorsArePropagatedIfMscorlibIsConstIsNotAvailable [](start = 20, length = 56)
Note to self: duplicate tests for other symbol types and the same error. #Closed
@@ -273,6 +273,14 @@ internal sealed class SourcePropertySymbol : PropertySymbol, IAttributeTargetSym | |||
_lazyParameters = CustomModifierUtils.CopyParameterCustomModifiers(overriddenOrImplementedProperty.Parameters, _lazyParameters, alsoCopyParamsModifier: isOverride); | |||
} | |||
} | |||
else if (_refKind == RefKind.RefReadOnly && (this.IsVirtual || this.IsAbstract)) |
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.
does this work with interface implementations? explicit/implicit? #Resolved
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.
I think we need some tests for interface implementations
In reply to: 117863982 [](ancestors = 117863982)
@@ -249,6 +249,7 @@ private sealed class InvokeMethod : SourceDelegateMethodSymbol | |||
binder, this, syntax.ParameterList, out arglistToken, | |||
allowRefOrOut: true, | |||
allowThis: false, | |||
shouldPlaceIsConstModifier: false, |
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.
I think we want "true" here. Otherwise old compiler may convert methods with regular "ref" to delegate types with "ref readonly". #Resolved
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.
I think we want "true" here. Otherwise old compiler may convert methods with regular "ref" to delegate types with "ref readonly".
Please add VB test for this scenario. #Closed
I am done with a review pass. Mostly good. I had some comments, that I think are actionable. In reply to: 303181737 [](ancestors = 303181737) |
{ | ||
// This cannot be placed on CustomModifiers, just RefCustomModifiers | ||
throw new UnsupportedSignatureContent(); | ||
} |
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.
Is isConstFound
needed or could the check above be replaced by else if (info.CustomModifiers.Length > 0)
? Then the delegate to DecodeModifiersOrThrow
can be simplified to avoid the closure class. Similar comment for isVolatileFound
in DecodeFieldSignature
. #Resolved
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.
Will remove the need for capturing, but we still need that isConstFound
value since we allow optional modifiers, just not required ones.
In reply to: 117907098 [](ancestors = 117907098)
@@ -107,5 +108,188 @@ End Class | |||
|
|||
CompileAndVerify(comp, expectedOutput:=<![CDATA[2]]>) | |||
End Sub | |||
|
|||
<Fact> | |||
Public Sub NonExtensibleReadOnlySignaturesAreRead() |
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.
Perhaps Virtual
rather than Extensible
, here and below. #Resolved
public int this[ref readonly int x] => x; | ||
}"; | ||
|
||
var options = TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All); |
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.
Is MetadataImportOptions.All
needed here, or in tests below? #Resolved
out _lazyParameters, alsoCopyParamsModifier: true); | ||
} | ||
} | ||
else if (_refKind == RefKind.RefReadOnly && (this.IsVirtual || this.IsAbstract)) |
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.
Are we including IsConst
on interface
methods? #Resolved
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.
Yes: virtual method parameters, returns, interface methods in any position and delegates. #Resolved
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.
Parameters handle both parameters and returns. Will add tests for interfaces and delegates.
In reply to: 118018517 [](ancestors = 118018517)
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.
Will add tests to both implicit and explicit interface implementations
In reply to: 118016179 [](ancestors = 118016179)
internal override bool IsConstModifierType(PEModuleSymbol moduleSymbol, TypeSymbol type) | ||
{ | ||
return type.ToDisplayString() == WellKnownTypes.GetMetadataName(WellKnownType.System_Runtime_CompilerServices_IsConst); | ||
} |
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.
This seems simple enough to fix now vs. needing a PROTOTYPE comment to fix later. #Resolved
@@ -20,7 +20,8 @@ internal static class ParameterHelpers | |||
out SyntaxToken arglistToken, | |||
DiagnosticBag diagnostics, | |||
bool allowRefOrOut, | |||
bool allowThis) | |||
bool allowThis, | |||
bool shouldPlaceIsConstModifier) |
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 shoudEmit vs. shouldPlace. #Resolved
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 shoudEmit vs. shouldPlace.
Perhaps simply "addIsConstModifier". #Closed
out _lazyParameters, alsoCopyParamsModifier: true); | ||
} | ||
} | ||
else if (_refKind == RefKind.RefReadOnly && (this.IsVirtual || this.IsAbstract)) |
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.
Yes: virtual method parameters, returns, interface methods in any position and delegates. #Resolved
var isConst = IsConstModifierType(type); | ||
isConstFound |= isConst; | ||
return isConst; | ||
}); |
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.
This lambda is capturing hence is adding two allocations to each call to DecodeModifiersOrThrow
. Is this a sensitive enough area of the code that we should consider a non-allocating solution? #Resolved
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.
Will move to a version that has less allocations, also adding an extra overload for the less-traversed path.
In reply to: 118019729 [](ancestors = 118019729)
@@ -49,6 +49,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE | |||
Return False | |||
End Function | |||
|
|||
Friend Overrides Function IsConstModifierType(moduleSymbol As PEModuleSymbol, type As TypeSymbol) As Boolean | |||
' VB doesn't deal with ref-readonly parameters or return-types. | |||
Return False |
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 that's the case then we should consider renaming both of these methods. The name simply does not match up to the actual implementation. Consider this code
var isConst = IsConstModifierType(type);
99% of developers who look at that line are going to interpret this as determining if type
is the const modifier. In reality it's detecting if a) it's the const modifier and b) the present language supports it. The 1% who will understand the behavior are those who realize the name of the method is wrong.
#Resolved
private ImmutableArray<ModifierInfo<TypeSymbol>> DecodeModifiersOrThrow( | ||
ref BlobReader signatureReader, | ||
out SignatureTypeCode typeCode, | ||
Func<TypeSymbol, bool> acceptRequiredModifier = null) |
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.
Func<TypeSymbol, bool> acceptRequiredModifier = null [](start = 12, length = 52)
This feels too complicated. I think we can simply pas a boolean whether IsConst modifier should be accepted as a mod_req or not. #Closed
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.
Rather than making changes to this function, I would instead modify DecodeParameterOrThrow to specially handle IsConst modifier in the manner DecodeFieldSignature used to do that for IsVolatile and would keep this function and DecodeFieldSignature unchanged.
In reply to: 118052362 [](ancestors = 118052362)
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.
Will try to introduce in the next iteration a simpler version that doesn't use capturing lambdas. I don't like to duplicate the same logic in 3 places (DecodeModifiers, DecodeParameters, DecodeFields).
In reply to: 118055994 [](ancestors = 118055994,118052362)
info.CustomModifiers = DecodeModifiersOrThrow(ref signatureReader, out typeCode); | ||
} | ||
else if (isConstFound) |
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.
else if (isConstFound) [](start = 12, length = 22)
We could simply check for presence of any required modifiers in info.CustomModifiers. #Closed
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.
Will try to refactor it so that we don't need to do the extra enumeration.
In reply to: 118054332 [](ancestors = 118054332)
SignatureTypeCode typeCode; | ||
ArrayBuilder<ModifierInfo<TypeSymbol>> customModifierBuilder = null; |
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.
ArrayBuilder<ModifierInfo> customModifierBuilder = null; [](start = 16, length = 68)
I would revert changes in this function, it doesn't look like we want any behavior change here. #Closed
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.
Will try to introduce in the next iteration a simpler version that doesn't use capturing lambdas. I don't like to duplicate the same logic in 3 places (DecodeModifiers, DecodeParameters, DecodeFields).
In reply to: 118054960 [](ancestors = 118054960)
@@ -273,6 +273,7 @@ public virtual void Visit(IMethodDefinition method) | |||
{ | |||
this.Visit(method.GetReturnValueAttributes(Context)); | |||
this.Visit(method.ReturnValueCustomModifiers); | |||
this.Visit(method.RefCustomModifiers); |
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.
this.Visit(method.RefCustomModifiers); [](start = 12, length = 38)
It feels like RefCustomModifiers should be visited before ReturnValueCustomModifiers. Also, it looks like there are two more places in ReferenceIndexerBase.cs that should be adjusted in a similar way. #Closed
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.
It looks like there is one more place in ReferenceDependencyWalker.cs as well.
In reply to: 118057254 [](ancestors = 118057254)
@@ -412,6 +413,7 @@ public virtual void Visit(IParameterDefinition parameterDefinition) | |||
Debug.Assert((marshalling != null || !parameterDefinition.MarshallingDescriptor.IsDefaultOrEmpty) == parameterDefinition.IsMarshalledExplicitly); | |||
|
|||
this.Visit(parameterDefinition.GetAttributes(Context)); | |||
this.Visit(parameterDefinition.RefCustomModifiers); |
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.
this.Visit(parameterDefinition.RefCustomModifiers); [](start = 12, length = 51)
It looks like there is one more place in ReferenceDependencyWalker.cs that should be adjusted in a similar way. And in public virtual void Visit(IParameterTypeInformation parameterTypeInformation)
in this type as well. #Closed
@@ -63,7 +63,7 @@ public static bool HasRefOrOutParameter(this PropertySymbol property) | |||
{ | |||
foreach (ParameterSymbol param in property.Parameters) | |||
{ | |||
if (param.RefKind != RefKind.None) | |||
if (param.RefKind == RefKind.Ref || param.RefKind == RefKind.Out) |
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 (param.RefKind == RefKind.Ref || param.RefKind == RefKind.Out) [](start = 16, length = 65)
Did you add a test backing this change? Could you point to the test(s)? #Closed
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.
Adding IsConstModReqIsConsumedInRefCustomModifiersPosition_Indexers_ReturnTypes
. This change basically allows to pass ref-readonly arguments to indexer methods. Passing ordinary arguments is the same to properties as ref-readonly arguments.
In reply to: 118061963 [](ancestors = 118061963)
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.
Adding
IsConstModReqIsConsumedInRefCustomModifiersPosition_Indexers_ReturnTypes
. This change basically allows to pass ref-readonly arguments to indexer methods. Passing ordinary arguments is the same to properties as ref-readonly arguments.
I couldn't find the test, what file it should be in?
In reply to: 118609191 [](ancestors = 118609191,118061963)
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.
File IsConstModifierTests.cs
in C# emit tests project. You can look forIsConstModReqIsConsumedInRefCustomModifiersPosition_Code_Indexers_ReturnTypes
now.
In reply to: 119789809 [](ancestors = 119789809,118609191,118061963)
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.
Correction: IsConstModReqIsConsumedInRefCustomModifiersPosition_Code_Indexers_Parameters
*
In reply to: 120218968 [](ancestors = 120218968,119789809,118609191,118061963)
@@ -107,5 +108,188 @@ End Class | |||
|
|||
CompileAndVerify(comp, expectedOutput:=<![CDATA[2]]>) | |||
End Sub | |||
|
|||
<Fact> | |||
Public Sub NonExtensibleReadOnlySignaturesAreRead() |
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.
Public Sub NonExtensibleReadOnlySignaturesAreRead() [](start = 8, length = 51)
Consider moving all these tests into a new file dedicated to ReadonlyRef feature. #Closed
Dim reference = CreateCSharpCompilation(" | ||
public class TestRef | ||
{ | ||
public void M(ref readonly int x) |
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.
public void M(ref readonly int x) [](start = 4, length = 33)
This test covers ref readonly
parameter. Do we have a similar test for return? #Closed
Class Test | ||
Shared Sub Main() | ||
Dim obj = New TestRef() | ||
Dim value = obj.M() |
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.
Dim value = [](start = 8, length = 12)
Consider removing the local, leaving gust the method call. #Closed
public class TestRef | ||
{ | ||
private int value = 0; | ||
public virtual ref readonly int P => ref value; |
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.
public virtual ref readonly int P => ref value; [](start = 4, length = 47)
Do we have a test for a non-virtual property? #Closed
Success scenarios should be executed and runtime behavior should be verified. Applies to all similar tests. #Closed Refers to: src/Compilers/CSharp/Test/Emit/Emit/IsConstModifierTests.cs:2421 in 42a8f4c. [](commit_id = 42a8f4c, deletion_comment = False) |
Consider asserting that this method implements the interface. Applies to all similar tests. #Closed Refers to: src/Compilers/CSharp/Test/Emit/Emit/IsConstModifierTests.cs:2564 in 42a8f4c. [](commit_id = 42a8f4c, deletion_comment = False) |
I think for all "copy modifiers" tests it would be interesting to test flavor when compilation define their own IsConst type. Then we actually can observe the copy happening vs. we just added modifiers based on ref readonly usage. #Closed Refers to: src/Compilers/CSharp/Test/Emit/Emit/IsConstModifierTests.cs:2708 in 42a8f4c. [](commit_id = 42a8f4c, deletion_comment = False) |
Similarly should test scenarios when both compilations define their own IsConst type. #Closed Refers to: src/Compilers/CSharp/Test/Emit/Emit/IsConstModifierTests.cs:3257 in 42a8f4c. [](commit_id = 42a8f4c, deletion_comment = False) |
destinationMethod.ReturnsByRef ? constructedSourceMethod.RefCustomModifiers : ImmutableArray<CustomModifier>.Empty); | ||
customModifiers = CustomModifiersTuple.Create( | ||
constructedSourceMethod.ReturnTypeCustomModifiers, | ||
destinationMethod.ReturnsByRef || destinationMethod.ReturnsByRefReadonly ? constructedSourceMethod.RefCustomModifiers : ImmutableArray<CustomModifier>.Empty); |
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.
destinationMethod.ReturnsByRef || destinationMethod.ReturnsByRefReadonly [](start = 16, length = 73)
Could we simply check if RefKind is None? #Closed
Done with review pass. #Closed |
@@ -167,6 +167,7 @@ private void MethodChecks(MethodDeclarationSyntax syntax, Binder withTypeParamsB | |||
signatureBinder, this, syntax.ParameterList, out arglistToken, | |||
allowRefOrOut: true, | |||
allowThis: true, | |||
addIsConstModifier: IsVirtual || IsAbstract, |
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.
IsVirtual || IsAbst [](start = 36, length = 19)
This should probably include checks for override and explicit implementation, those are virtual (in metadata terms) as well and the difference will be observable for cases when the target method cannot be found, etc. #Closed
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.
@@ -1388,7 +1397,7 @@ private TypeSymbol ComputeType(Binder binder, BasePropertyDeclarationSyntax synt | |||
private ImmutableArray<ParameterSymbol> ComputeParameters(Binder binder, BasePropertyDeclarationSyntax syntax, DiagnosticBag diagnostics) | |||
{ | |||
var parameterSyntaxOpt = GetParameterListSyntax(syntax); | |||
var parameters = MakeParameters(binder, this, parameterSyntaxOpt, diagnostics); | |||
var parameters = MakeParameters(binder, this, parameterSyntaxOpt, diagnostics, addIsConstModifier: IsVirtual || IsAbstract); |
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.
IsVirtual || IsAbstract [](start = 111, length = 23)
Same comment as for methods. #Closed
This is not an explicit implementation. comment misplaced? If the method is virtual, we don't create explicit implementations. Only for non-virtuals. I modified the other tests. In reply to: 305697978 [](ancestors = 305697978) Refers to: src/Compilers/CSharp/Test/Emit/Emit/IsConstModifierTests.cs:2530 in 42a8f4c. [](commit_id = 42a8f4c, deletion_comment = False) |
Please check the tests starting with In reply to: 305699094 [](ancestors = 305699094) Refers to: src/Compilers/CSharp/Test/Emit/Emit/IsConstModifierTests.cs:2708 in 42a8f4c. [](commit_id = 42a8f4c, deletion_comment = False) |
@AlekseyTs comments addressed. #Closed |
if (_refKind == RefKind.RefReadOnly) | ||
{ | ||
var isConstType = binder.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_IsConst, diagnostics, syntax.ReturnType); | ||
_refCustomModifiers = ImmutableArray.Create(CSharpCustomModifier.CreateRequired(isConstType)); |
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.
_refCustomModifiers = ImmutableArray.Create(CSharpCustomModifier.CreateRequired(isConstType)); [](start = 20, length = 94)
It feels like we could simply reuse modifiers from the invoke
. #Closed
@@ -342,15 +356,18 @@ internal override OneOrMany<SyntaxList<AttributeListSyntax>> GetReturnTypeAttrib | |||
|
|||
private sealed class EndInvokeMethod : SourceDelegateMethodSymbol | |||
{ | |||
private readonly RefKind refKind; | |||
private readonly RefKind _refKind; | |||
private readonly ImmutableArray<CustomModifier> _refCustomModifiers; |
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.
private readonly ImmutableArray _refCustomModifiers; [](start = 12, length = 68)
Consider replacing two these members with a reference to invoke
, then implementation of RefKind and RefCustomModifiers could simply delegate to the invoke
. #Closed
I noticed that you cloned the entire unit-test in order to test this scenario against compilation reference. This feel like an overkill to me, both scenarios could easily be tested right here:
This isn't a blocker, but it causes an unnecessary code duplication and work duplication while tests are executed. #Closed Refers to: src/Compilers/CSharp/Test/Emit/Emit/IsConstModifierTests.cs:38 in b32dc89. [](commit_id = b32dc89, deletion_comment = False) |
Please add a call (applies to all similar tests)
|
Done with review pass. #Closed |
@OmarTawfik - I have no actionable comments on this. Except - Can we wait with merging this until after the ref-extension are merged in and there is a build that contains them? This would be the first change that intentionally breaks "compatibility" with old compilers. It would be nice to have a builds before/after - just for comparison reasons. |
Tried to isolate the root cause. If a test fails because of the difference between metadata/image references, then one of them should succeed. In reply to: 307460674 [](ancestors = 307460674) Refers to: src/Compilers/CSharp/Test/Emit/Emit/IsConstModifierTests.cs:38 in b32dc89. [](commit_id = b32dc89, deletion_comment = False) |
@AlekseyTs done with latest set of comments. |
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
Contributes to #17287