-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Loosen compiler restriction which was not required by the spec #71110
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 4 commits
5ae35bd
677aa72
42a7098
7dabde7
a37167f
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 |
|---|---|---|
|
|
@@ -29,12 +29,16 @@ internal sealed class SynthesizedReadOnlyListTypeSymbol : NamedTypeSymbol | |
| { | ||
| SpecialType.System_Collections_IEnumerable, | ||
| SpecialType.System_Collections_Generic_IEnumerable_T, | ||
| SpecialType.System_Collections_Generic_IReadOnlyCollection_T, | ||
| SpecialType.System_Collections_Generic_IReadOnlyList_T, | ||
| SpecialType.System_Collections_Generic_ICollection_T, | ||
| SpecialType.System_Collections_Generic_IList_T, | ||
| }; | ||
|
|
||
| private static readonly SpecialType[] s_readOnlyInterfacesSpecialTypes = new[] | ||
| { | ||
| SpecialType.System_Collections_Generic_IReadOnlyCollection_T, | ||
| SpecialType.System_Collections_Generic_IReadOnlyList_T, | ||
| }; | ||
|
|
||
| private static readonly WellKnownType[] s_requiredWellKnownTypes = new[] | ||
| { | ||
| WellKnownType.System_Collections_ICollection, | ||
|
|
@@ -63,8 +67,6 @@ internal sealed class SynthesizedReadOnlyListTypeSymbol : NamedTypeSymbol | |
| WellKnownMember.System_Collections_IList__Insert, | ||
| WellKnownMember.System_Collections_IList__Remove, | ||
| WellKnownMember.System_Collections_IList__RemoveAt, | ||
| WellKnownMember.System_Collections_Generic_IReadOnlyCollection_T__Count, | ||
| WellKnownMember.System_Collections_Generic_IReadOnlyList_T__get_Item, | ||
| WellKnownMember.System_Collections_Generic_ICollection_T__Count, | ||
| WellKnownMember.System_Collections_Generic_ICollection_T__IsReadOnly, | ||
| WellKnownMember.System_Collections_Generic_ICollection_T__Add, | ||
|
|
@@ -79,6 +81,12 @@ internal sealed class SynthesizedReadOnlyListTypeSymbol : NamedTypeSymbol | |
| WellKnownMember.System_NotSupportedException__ctor, | ||
| }; | ||
|
|
||
| private static readonly WellKnownMember[] s_readOnlyInterfacesWellKnownMembers = new[] | ||
| { | ||
| WellKnownMember.System_Collections_Generic_IReadOnlyCollection_T__Count, | ||
| WellKnownMember.System_Collections_Generic_IReadOnlyList_T__get_Item, | ||
| }; | ||
|
|
||
| private static readonly WellKnownMember[] s_requiredWellKnownMembersUnknownLength = new[] | ||
| { | ||
| WellKnownMember.System_Collections_Generic_List_T__Count, | ||
|
|
@@ -93,6 +101,10 @@ internal static NamedTypeSymbol Create(SourceModuleSymbol containingModule, stri | |
| var compilation = containingModule.DeclaringCompilation; | ||
| DiagnosticInfo? diagnosticInfo = null; | ||
|
|
||
| var hasReadOnlyInterfaces = | ||
| !compilation.IsTypeMissing(SpecialType.System_Collections_Generic_IReadOnlyCollection_T) | ||
| && !compilation.IsTypeMissing(SpecialType.System_Collections_Generic_IReadOnlyList_T); | ||
|
Member
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. It feels like this should be initialized in terms of the contents of I think something like
Member
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. It's possible that I missed some reason that existence of the types should be checked here, but not existence of the members. @cston in case you had already given some advice here that I missed, I want to make sure we're in agreement about what to do for this.
Contributor
Author
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. @RikkiGibson In an earlier form, it would implement the interfaces if present, and then implement each member if the member was present. Does that sound interesting?
Contributor
Author
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. (Basically, the first commit in the branch)
Member
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 think that would be fine, although I would suggest checking the members independently, we can simply implement the interfaces and members that happen to exist and don't implement the ones that don't exist. (though if the well known interfaces have extra members that we didn't expect, it would also be reasonable to skip implementing the interface entirely or possibly to report an error. Is there already some precedent in this synthesized type already for this case?) However, I don't want to lead you around in a circle if Cyrus or Chuck have already steered you away from that path. So let's make sure we have consensus on how that should work.
Contributor
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 have zero opinion here. IT's up to compiler side how you'd like this code to be structured :)
Contributor
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. These are well-known interfaces with well-known members. Given that, I think we should handle the two likely cases - where the interfaces are available, and where the interfaces are not - to limit the test matrix today and in the future.
Comment on lines
+105
to
+106
Member
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.
This helper doesn't seem to be actually checking if the type is missing. It's rather "IsTypeMarkedAsMissing" and therefore is not suitable for non-test code. The proper way to do this I think is to check if the return value is of type
Contributor
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. |
||
|
|
||
| foreach (var type in s_requiredSpecialTypes) | ||
| { | ||
| diagnosticInfo = compilation.GetSpecialType(type).GetUseSiteInfo().DiagnosticInfo; | ||
|
|
@@ -102,6 +114,18 @@ internal static NamedTypeSymbol Create(SourceModuleSymbol containingModule, stri | |
| } | ||
| } | ||
|
|
||
| if (hasReadOnlyInterfaces && diagnosticInfo is null) | ||
| { | ||
| foreach (var type in s_readOnlyInterfacesSpecialTypes) | ||
| { | ||
| diagnosticInfo = compilation.GetSpecialType(type).GetUseSiteInfo().DiagnosticInfo; | ||
| if (diagnosticInfo is { }) | ||
| { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (diagnosticInfo is null) | ||
| { | ||
| foreach (var type in s_requiredWellKnownTypes) | ||
|
|
@@ -138,6 +162,18 @@ internal static NamedTypeSymbol Create(SourceModuleSymbol containingModule, stri | |
| } | ||
| } | ||
|
|
||
| if (hasReadOnlyInterfaces && diagnosticInfo is null) | ||
| { | ||
| foreach (var member in s_readOnlyInterfacesWellKnownMembers) | ||
| { | ||
| diagnosticInfo = getWellKnownTypeMemberDiagnosticInfo(compilation, member); | ||
| if (diagnosticInfo is { }) | ||
| { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (!hasKnownLength) | ||
| { | ||
| if (diagnosticInfo is null) | ||
|
|
@@ -163,7 +199,7 @@ internal static NamedTypeSymbol Create(SourceModuleSymbol containingModule, stri | |
| return new ExtendedErrorTypeSymbol(compilation, name, arity: 1, diagnosticInfo, unreported: true); | ||
| } | ||
|
|
||
| return new SynthesizedReadOnlyListTypeSymbol(containingModule, name, hasKnownLength); | ||
| return new SynthesizedReadOnlyListTypeSymbol(containingModule, name, hasKnownLength, hasReadOnlyInterfaces); | ||
|
|
||
| static DiagnosticInfo? getSpecialTypeMemberDiagnosticInfo(CSharpCompilation compilation, SpecialMember member) | ||
| { | ||
|
|
@@ -194,7 +230,7 @@ internal static NamedTypeSymbol Create(SourceModuleSymbol containingModule, stri | |
| private readonly ImmutableArray<Symbol> _members; | ||
| private readonly FieldSymbol _field; | ||
|
|
||
| private SynthesizedReadOnlyListTypeSymbol(SourceModuleSymbol containingModule, string name, bool hasKnownLength) | ||
| private SynthesizedReadOnlyListTypeSymbol(SourceModuleSymbol containingModule, string name, bool hasKnownLength, bool hasReadOnlyInterfaces) | ||
| { | ||
| var compilation = containingModule.DeclaringCompilation; | ||
|
|
||
|
|
@@ -218,15 +254,23 @@ private SynthesizedReadOnlyListTypeSymbol(SourceModuleSymbol containingModule, s | |
| var iCollectionT = compilation.GetSpecialType(SpecialType.System_Collections_Generic_ICollection_T).Construct(typeArgs); | ||
| var iListT = compilation.GetSpecialType(SpecialType.System_Collections_Generic_IList_T).Construct(typeArgs); | ||
|
|
||
| _interfaces = ImmutableArray.Create( | ||
| iEnumerable, | ||
| iCollection, | ||
| iList, | ||
| iEnumerableT, | ||
| iReadOnlyCollectionT, | ||
| iReadOnlyListT, | ||
| iCollectionT, | ||
| iListT); | ||
| _interfaces = hasReadOnlyInterfaces | ||
| ? ImmutableArray.Create( | ||
| iEnumerable, | ||
| iCollection, | ||
| iList, | ||
| iEnumerableT, | ||
| iReadOnlyCollectionT, | ||
| iReadOnlyListT, | ||
| iCollectionT, | ||
| iListT) | ||
| : ImmutableArray.Create( | ||
| iEnumerable, | ||
| iCollection, | ||
| iList, | ||
| iEnumerableT, | ||
| iCollectionT, | ||
| iListT); | ||
|
|
||
| var membersBuilder = ArrayBuilder<Symbol>.GetInstance(); | ||
| membersBuilder.Add( | ||
|
|
@@ -314,16 +358,19 @@ private SynthesizedReadOnlyListTypeSymbol(SourceModuleSymbol containingModule, s | |
| this, | ||
| ((MethodSymbol)compilation.GetSpecialTypeMember(SpecialMember.System_Collections_Generic_IEnumerable_T__GetEnumerator)!).AsMember(iEnumerableT), | ||
| generateGetEnumeratorT)); | ||
| addProperty(membersBuilder, | ||
| new SynthesizedReadOnlyListProperty( | ||
| this, | ||
| ((PropertySymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_IReadOnlyCollection_T__Count)!).AsMember(iReadOnlyCollectionT), | ||
|
jnm2 marked this conversation as resolved.
|
||
| generateCount)); | ||
| addProperty(membersBuilder, | ||
| new SynthesizedReadOnlyListProperty( | ||
| this, | ||
| ((PropertySymbol)((MethodSymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_IReadOnlyList_T__get_Item)!).AssociatedSymbol).AsMember(iReadOnlyListT), | ||
| generateIndexer)); | ||
| if (hasReadOnlyInterfaces) | ||
| { | ||
| addProperty(membersBuilder, | ||
| new SynthesizedReadOnlyListProperty( | ||
| this, | ||
| ((PropertySymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_IReadOnlyCollection_T__Count)!).AsMember(iReadOnlyCollectionT), | ||
| generateCount)); | ||
| addProperty(membersBuilder, | ||
| new SynthesizedReadOnlyListProperty( | ||
| this, | ||
| ((PropertySymbol)((MethodSymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_IReadOnlyList_T__get_Item)!).AssociatedSymbol).AsMember(iReadOnlyListT), | ||
| generateIndexer)); | ||
| } | ||
| addProperty(membersBuilder, | ||
| new SynthesizedReadOnlyListProperty( | ||
| this, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.