-
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 re-abstraction of interface members in derived interfaces #35756
Conversation
a69ce55
to
471afac
Compare
@dotnet/roslyn-compiler Please review #Closed |
@dotnet/roslyn-compiler Please review #Closed |
I'm looking |
class Test1 : I2 // This type must implement all members of I1 | ||
{ | ||
} | ||
``` |
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.
nit: If I recall, this is getting a non-obvious representation in metadata. Consider documenting too (helps in case of cross-language support). #Closed
SourceEventSymbol.GetAccessorName(@event.Name, isAdder); | ||
} | ||
|
||
public override string Name |
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.
Name [](start = 31, length = 4)
This removal seems surprising, as it means the Name
will be empty (implementation from Symbol
, I think). Wouldn't that at least affect some public APIs (ISymbol.Name
now gives a different answer)?
Sorry. It's moved to a base class. :-S #Closed
|
||
public interface I2 : I1 | ||
{ | ||
abstract void I1.M1(); |
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.
abstract [](start = 4, length = 8)
In an interface, when a body is missing abstract
is implied. So the abstract
keyword is optional here. However I see no tests for that. Please add an example and/or comment here and tests covering this. This is called out explicitly in the specification at https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md#reabstraction and https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-03-21.md#reabstraction #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.
In an interface, when a body is missing abstract is implied.
It is not implied for interface implementations and I am not sure if it is a good idea to do that. The behavior is captured in MethodImplementationInDerived_04 and similar unit-tests. I am not planning to change that in the current PR, instead I'll bring that for discussion to LDM.
In reply to: 285270178 [](ancestors = 285270178)
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.
Added to https://github.com/dotnet/csharplang/blob/master/meetings/2019/README.md under "Schedule ASAP"
In reply to: 285274070 [](ancestors = 285274070,285270178)
@@ -1289,7 +1289,8 @@ internal enum ErrorCode | |||
// available 8041-8049 | |||
ERR_InitializerOnNonAutoProperty = 8050, | |||
ERR_AutoPropertyMustHaveGetAccessor = 8051, | |||
ERR_AutoPropertyInitializerInInterface = 8052, | |||
ERR_AbstractEventHasAccessors = 8052, | |||
// available 8053 |
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.
Please place all new C# 8 diagnostics in the region diagnostics introduced for C# 8.0
#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.
Please place all new C# 8 diagnostics in the region diagnostics introduced for C# 8.0
I am not aware of a requirement to do that.
In reply to: 285274626 [](ancestors = 285274626)
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.
However, I was under impression that ERR_AutoPropertyInitializerInInterface was added as part of the DIM work, but that is not the case. Since we cannot reuse error numbers for errors that were shipped, I will not reuse this number for ERR_AbstractEventHasAccessors.
In reply to: 285274982 [](ancestors = 285274982,285274626)
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.
Placing a C# 8 diagnostic in a region labeled diagnostics introduced in C# 4 and earlier
is misleading, which is why I asked you to move it.
In reply to: 285274982 [](ancestors = 285274982,285274626)
@@ -1059,7 +1059,16 @@ private static Symbol FindMostSpecificImplementation(Symbol interfaceMember, Nam | |||
ref useSiteDiagnostics, | |||
out var _, out var _); |
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 possibly missing use-site diagnostics? #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.
Are we possibly missing use-site diagnostics?
This method is not interested in any diagnostics, it doesn't report any and doesn't return any to its caller.
In reply to: 285291041 [](ancestors = 285291041)
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.
How do we know that any use site diagnostics that are deposited into useSiteDiagnostics
here would have been previously reported so that they are not missed?
In reply to: 285293979 [](ancestors = 285293979,285291041)
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.IsMetadataNewSlot() && (object)_containingType.BaseTypeNoUseSiteDiagnostics != null) || this.IsExplicitClassOverride); | ||
this._containingType.IsInterface ? | ||
false : | ||
(this.IsMetadataVirtual() && !this.IsDestructor && |
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.
Clearer perhaps !_containingType.IsInterface &&
#Closed
else if ((mods & (DeclarationModifiers.Static | DeclarationModifiers.Private | DeclarationModifiers.Partial | DeclarationModifiers.Virtual | DeclarationModifiers.Abstract)) == 0) | ||
{ | ||
Debug.Assert(!isExplicitInterfaceImplementation); | ||
|
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.
Given that this is in the else
of an if (isExplicitInterfaceImplementation)
, the assert seems unnecessary. #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.
Given that this is in the else of an if (isExplicitInterfaceImplementation), the assert seems unnecessary.
It is here for the benefit of the reader and to prevent unintentional break in the future.
In reply to: 285293830 [](ancestors = 285293830)
else if (isInterface) | ||
{ | ||
Debug.Assert(explicitInterfaceImplementation); | ||
allowedModifiers |= DeclarationModifiers.Abstract; |
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 is the else
part of an if (!explicitInterfaceImplementation)
, so this is a bit redundant. #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.
This is the else part of an if (!explicitInterfaceImplementation), so this is a bit redundant.
It is here for the benefit of the reader and to prevent unintentional break in the future.
In reply to: 285294377 [](ancestors = 285294377)
throw ExceptionUtilities.UnexpectedValue(accessor.Kind()); | ||
} | ||
|
||
if (checkBody && !IsAbstract && accessor.Body == null && accessor.ExpressionBody == null && accessor.SemicolonToken.Kind() == SyntaxKind.SemicolonToken) |
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.
accessor.SemicolonToken.Kind() == SyntaxKind.SemicolonToken [](start = 112, length = 59)
This seems to depend on how the parser handles error recovery in a fragile way. Why isn't the previous accessor.Body == null
sufficient? #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.
This seems to depend on how the parser handles error recovery in a fragile way. Why isn't the previous accessor.Body == null sufficient?
This duplicates exact conditions under which the parser used to reported this error before. I do not intend to report it under any new conditions. Different conditions would cause different errors reported in the parser. For example, if semicolon is missing, the parser would complain about missing '''{```.
In reply to: 285299111 [](ancestors = 285299111)
@dotnet/roslyn-compiler, @gafter Please review #Closed |
@@ -15,17 +15,64 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols | |||
internal abstract class SourceEventAccessorSymbol : SourceMemberMethodSymbol | |||
{ | |||
private readonly SourceEventSymbol _event; | |||
private readonly string _name; | |||
private readonly ImmutableArray<MethodSymbol> _explicitInterfaceImplementations; |
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.
ImmutableArray [](start = 25, length = 28)
This appears to be an ImmutableArray
that is either empty (when there is no corresponding implemented event) or contains a single method (when there is a corresponding implemented event). If I am right, for this situation I would expect to see a field of type MethodSymbol
that is either null
or contains the implemented event's accessor. #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.
Ah, I see this implements an API that handles imported symbols as well, which can implement multiple methods.
In reply to: 286220692 [](ancestors = 286220692)
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.
@dotnet/roslyn-compiler Please review, need a second sign-off #Closed |
2 similar comments
@dotnet/roslyn-compiler Please review, need a second sign-off #Closed |
@dotnet/roslyn-compiler Please review, need a second sign-off #Closed |
@dotnet/roslyn-compiler Please review, need a second sign-off #Closed |
{ | ||
} | ||
``` | ||
In metadata, methods representing re-abstraction have all three flags `abstarct`, `virtual`, `sealed` set and do not have `newslot` flag set. |
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.
abstarct [](start = 71, length = 8)
abstract
#Resolved
Not necessary to address in this PR, but considering the number of times we do this general pattern we should probably consider a helper on our compilation extensions to validate these scenarios. Refers to: src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs:44246 in 2b8a937. [](commit_id = 2b8a937, deletion_comment = False) |
Interesting. I can't say I expected this error: neither Refers to: src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs:44689 in 2b8a937. [](commit_id = 2b8a937, deletion_comment = False) |
Is there any way to improve the message for this scenario or perhaps report a different error? In reply to: 495330811 [](ancestors = 495330811) Refers to: src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs:44689 in 2b8a937. [](commit_id = 2b8a937, deletion_comment = False) |
Prior tests already validated re-abstraction declaration. Tests validating various consumption scenarios don't need to do this over and over In reply to: 495330037 [](ancestors = 495330037) Refers to: src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs:44488 in 2b8a937. [](commit_id = 2b8a937, deletion_comment = False) |
Is there any way to improve the message for this scenario or perhaps report a different error? It really doesn't matter if any of them is a re-abstraction. As long as there is more than one, it is an error. Nothing specific to re-abstraction In reply to: 495331020 [](ancestors = 495331020,495330811) Refers to: src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs:44689 in 2b8a937. [](commit_id = 2b8a937, deletion_comment = False) |
Opened #35915 to follow up In reply to: 495332460 [](ancestors = 495332460,495331020,495330811) Refers to: src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs:44689 in 2b8a937. [](commit_id = 2b8a937, deletion_comment = False) |
This error is very unexpected imo. The method is marked Refers to: src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs:45241 in 2b8a937. [](commit_id = 2b8a937, deletion_comment = False) |
I believe there is no behavior change around this scenario. Feel free to open an issue. In reply to: 495354349 [](ancestors = 495354349) Refers to: src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs:45241 in 2b8a937. [](commit_id = 2b8a937, deletion_comment = False) |
They are likely not different, but it doesn't hurt to verify In reply to: 495359062 [](ancestors = 495359062) Refers to: src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs:46394 in 2b8a937. [](commit_id = 2b8a937, deletion_comment = False) |
Consider adding some tests with the additional modifiers on Refers to: src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs:46930 in 2b8a937. [](commit_id = 2b8a937, deletion_comment = False) |
Since there was no change in the accessor's syntax and allowed modifiers on an accessor (which is none) for explicit interface implementation. I do not believe it is worth testing specifically in connection to DIM In reply to: 495363704 [](ancestors = 495363704) Refers to: src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs:46930 in 2b8a937. [](commit_id = 2b8a937, deletion_comment = False) |
BTW, there is an existing test covering this for non-reabstracting scenario PropertyImplementationInDerived_18 In reply to: 495368645 [](ancestors = 495368645,495363704) Refers to: src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs:46930 in 2b8a937. [](commit_id = 2b8a937, deletion_comment = 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.
LGTM (commit 5)
No description provided.