From 5ae35bd8db74f5283a559f325462d6f19e75fe44 Mon Sep 17 00:00:00 2001 From: jnm2 Date: Tue, 5 Dec 2023 18:06:07 -0500 Subject: [PATCH 1/5] The compiler isn't required by the spec to implement IReadOnly interfaces when targeting IEnumerable --- .../SynthesizedReadOnlyListTypeSymbol.cs | 54 +++++++++++-------- .../Semantics/CollectionExpressionTests.cs | 46 +++++++++------- 2 files changed, 57 insertions(+), 43 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs index 3c05db15f7c2d..33c08ec8ec885 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs @@ -29,8 +29,6 @@ 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, }; @@ -63,8 +61,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, @@ -218,15 +214,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 = iReadOnlyCollectionT.IsErrorType() || iReadOnlyListT.IsErrorType() + ? ImmutableArray.Create( + iEnumerable, + iCollection, + iList, + iEnumerableT, + iCollectionT, + iListT) + : ImmutableArray.Create( + iEnumerable, + iCollection, + iList, + iEnumerableT, + iReadOnlyCollectionT, + iReadOnlyListT, + iCollectionT, + iListT); var membersBuilder = ArrayBuilder.GetInstance(); membersBuilder.Add( @@ -314,16 +318,20 @@ 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), - generateCount)); - addProperty(membersBuilder, - new SynthesizedReadOnlyListProperty( - this, - ((PropertySymbol)((MethodSymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_IReadOnlyList_T__get_Item)!).AssociatedSymbol).AsMember(iReadOnlyListT), - generateIndexer)); + if ((PropertySymbol?)compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_IReadOnlyCollection_T__Count) is { } wellKnownReadOnlyCollectionCount + && (MethodSymbol?)compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_IReadOnlyList_T__get_Item) is { } wellKnownReadOnlyListIndexer) + { + addProperty(membersBuilder, + new SynthesizedReadOnlyListProperty( + this, + wellKnownReadOnlyCollectionCount.AsMember(iReadOnlyCollectionT), + generateCount)); + addProperty(membersBuilder, + new SynthesizedReadOnlyListProperty( + this, + ((PropertySymbol)wellKnownReadOnlyListIndexer.AssociatedSymbol).AsMember(iReadOnlyListT), + generateIndexer)); + } addProperty(membersBuilder, new SynthesizedReadOnlyListProperty( this, diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index cf432dc6ac66e..7700fefb84a1c 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -9468,11 +9468,11 @@ static void compareMembers(NamedTypeSymbol sourceType, NamedTypeSymbol synthesiz [Theory] [InlineData(SpecialType.System_Collections_IEnumerable, "System.Collections.IEnumerable")] [InlineData(SpecialType.System_Collections_Generic_IEnumerable_T, "System.Collections.Generic.IEnumerable`1")] - [InlineData(SpecialType.System_Collections_Generic_IReadOnlyCollection_T, "System.Collections.Generic.IReadOnlyCollection`1")] - [InlineData(SpecialType.System_Collections_Generic_IReadOnlyList_T, "System.Collections.Generic.IReadOnlyList`1")] + [InlineData(SpecialType.System_Collections_Generic_IReadOnlyCollection_T, "System.Collections.Generic.IReadOnlyCollection`1", true)] + [InlineData(SpecialType.System_Collections_Generic_IReadOnlyList_T, "System.Collections.Generic.IReadOnlyList`1", true)] [InlineData(SpecialType.System_Collections_Generic_ICollection_T, "System.Collections.Generic.ICollection`1")] [InlineData(SpecialType.System_Collections_Generic_IList_T, "System.Collections.Generic.IList`1")] - public void SynthesizedReadOnlyList_MissingSpecialTypes(SpecialType missingType, string missingTypeName) + public void SynthesizedReadOnlyList_MissingSpecialTypes(SpecialType missingType, string missingTypeName, bool isOptional = false) { string source = """ using System.Collections.Generic; @@ -9487,13 +9487,16 @@ static void Main() """; var comp = CreateCompilation(source); comp.MakeTypeMissing(missingType); - comp.VerifyEmitDiagnostics( - // (6,30): error CS0518: Predefined type 'System.Collections.IEnumerable' is not defined or imported - // IEnumerable x = [0]; - Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "[0]").WithArguments(missingTypeName).WithLocation(6, 30), - // (7,30): error CS0518: Predefined type 'System.Collections.IEnumerable' is not defined or imported - // IEnumerable y = [..x]; - Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "[..x]").WithArguments(missingTypeName).WithLocation(7, 30)); + comp.VerifyEmitDiagnostics(isOptional + ? [] + : [ + // (6,30): error CS0518: Predefined type 'System.Collections.IEnumerable' is not defined or imported + // IEnumerable x = [0]; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "[0]").WithArguments(missingTypeName).WithLocation(6, 30), + // (7,30): error CS0518: Predefined type 'System.Collections.IEnumerable' is not defined or imported + // IEnumerable y = [..x]; + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "[..x]").WithArguments(missingTypeName).WithLocation(7, 30), + ]); } [Theory] @@ -9608,8 +9611,8 @@ static void Main() [InlineData((int)WellKnownMember.System_Collections_IList__Insert, "System.Collections.IList", "Insert")] [InlineData((int)WellKnownMember.System_Collections_IList__Remove, "System.Collections.IList", "Remove")] [InlineData((int)WellKnownMember.System_Collections_IList__RemoveAt, "System.Collections.IList", "RemoveAt")] - [InlineData((int)WellKnownMember.System_Collections_Generic_IReadOnlyCollection_T__Count, "System.Collections.Generic.IReadOnlyCollection`1", "Count")] - [InlineData((int)WellKnownMember.System_Collections_Generic_IReadOnlyList_T__get_Item, "System.Collections.Generic.IReadOnlyList`1", "get_Item")] + [InlineData((int)WellKnownMember.System_Collections_Generic_IReadOnlyCollection_T__Count, "System.Collections.Generic.IReadOnlyCollection`1", "Count", true)] + [InlineData((int)WellKnownMember.System_Collections_Generic_IReadOnlyList_T__get_Item, "System.Collections.Generic.IReadOnlyList`1", "get_Item", true)] [InlineData((int)WellKnownMember.System_Collections_Generic_ICollection_T__Count, "System.Collections.Generic.ICollection`1", "Count")] [InlineData((int)WellKnownMember.System_Collections_Generic_ICollection_T__IsReadOnly, "System.Collections.Generic.ICollection`1", "IsReadOnly")] [InlineData((int)WellKnownMember.System_Collections_Generic_ICollection_T__Add, "System.Collections.Generic.ICollection`1", "Add")] @@ -9622,7 +9625,7 @@ static void Main() [InlineData((int)WellKnownMember.System_Collections_Generic_IList_T__Insert, "System.Collections.Generic.IList`1", "Insert")] [InlineData((int)WellKnownMember.System_Collections_Generic_IList_T__RemoveAt, "System.Collections.Generic.IList`1", "RemoveAt")] [InlineData((int)WellKnownMember.System_NotSupportedException__ctor, "System.NotSupportedException", ".ctor")] - public void SynthesizedReadOnlyList_MissingWellKnownMembers(int missingMember, string missingMemberTypeName, string missingMemberName) + public void SynthesizedReadOnlyList_MissingWellKnownMembers(int missingMember, string missingMemberTypeName, string missingMemberName, bool isOptional = false) { string source = """ using System.Collections.Generic; @@ -9637,13 +9640,16 @@ static void Main() """; var comp = CreateCompilation(source); comp.MakeMemberMissing((WellKnownMember)missingMember); - comp.VerifyEmitDiagnostics( - // (6,30): error CS0656: Missing compiler required member 'System.Collections.Generic.IReadOnlyCollection`1.Count' - // IEnumerable x = [0]; - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[0]").WithArguments(missingMemberTypeName, missingMemberName).WithLocation(6, 30), - // (7,30): error CS0656: Missing compiler required member 'System.Collections.Generic.IReadOnlyCollection`1.Count' - // IEnumerable y = [..x]; - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[..x]").WithArguments(missingMemberTypeName, missingMemberName).WithLocation(7, 30)); + comp.VerifyEmitDiagnostics(isOptional + ? [] + : [ + // (6,30): error CS0656: Missing compiler required member 'System.Collections.Generic.IReadOnlyCollection`1.Count' + // IEnumerable x = [0]; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[0]").WithArguments(missingMemberTypeName, missingMemberName).WithLocation(6, 30), + // (7,30): error CS0656: Missing compiler required member 'System.Collections.Generic.IReadOnlyCollection`1.Count' + // IEnumerable y = [..x]; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[..x]").WithArguments(missingMemberTypeName, missingMemberName).WithLocation(7, 30) + ]); } [Theory] From 677aa72d9f6f50b12565e74bf076daf76b30d70a Mon Sep 17 00:00:00 2001 From: jnm2 Date: Thu, 7 Dec 2023 16:29:37 -0500 Subject: [PATCH 2/5] Apply suggestions from review --- .../SynthesizedReadOnlyListTypeSymbol.cs | 59 ++++++++++++++++--- .../Semantics/CollectionExpressionTests.cs | 23 ++++---- 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs index 33c08ec8ec885..b7188b6f3fc65 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs @@ -32,6 +32,12 @@ internal sealed class SynthesizedReadOnlyListTypeSymbol : NamedTypeSymbol 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[] { @@ -75,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, @@ -89,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); + foreach (var type in s_requiredSpecialTypes) { diagnosticInfo = compilation.GetSpecialType(type).GetUseSiteInfo().DiagnosticInfo; @@ -98,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) @@ -134,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) @@ -159,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) { @@ -186,16 +226,18 @@ internal static NamedTypeSymbol Create(SourceModuleSymbol containingModule, stri } private readonly ModuleSymbol _containingModule; + private readonly bool _hasReadOnlyInterfaces; private readonly ImmutableArray _interfaces; private readonly ImmutableArray _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; _containingModule = containingModule; Name = name; + _hasReadOnlyInterfaces = hasReadOnlyInterfaces; var typeParameter = new SynthesizedReadOnlyListTypeParameterSymbol(this); TypeParameters = ImmutableArray.Create(typeParameter); var typeArgs = TypeArgumentsWithAnnotationsNoUseSiteDiagnostics; @@ -214,12 +256,14 @@ 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 = iReadOnlyCollectionT.IsErrorType() || iReadOnlyListT.IsErrorType() + _interfaces = _hasReadOnlyInterfaces ? ImmutableArray.Create( iEnumerable, iCollection, iList, iEnumerableT, + iReadOnlyCollectionT, + iReadOnlyListT, iCollectionT, iListT) : ImmutableArray.Create( @@ -227,8 +271,6 @@ private SynthesizedReadOnlyListTypeSymbol(SourceModuleSymbol containingModule, s iCollection, iList, iEnumerableT, - iReadOnlyCollectionT, - iReadOnlyListT, iCollectionT, iListT); @@ -318,18 +360,17 @@ private SynthesizedReadOnlyListTypeSymbol(SourceModuleSymbol containingModule, s this, ((MethodSymbol)compilation.GetSpecialTypeMember(SpecialMember.System_Collections_Generic_IEnumerable_T__GetEnumerator)!).AsMember(iEnumerableT), generateGetEnumeratorT)); - if ((PropertySymbol?)compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_IReadOnlyCollection_T__Count) is { } wellKnownReadOnlyCollectionCount - && (MethodSymbol?)compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_IReadOnlyList_T__get_Item) is { } wellKnownReadOnlyListIndexer) + if (_hasReadOnlyInterfaces) { addProperty(membersBuilder, new SynthesizedReadOnlyListProperty( this, - wellKnownReadOnlyCollectionCount.AsMember(iReadOnlyCollectionT), + ((PropertySymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_IReadOnlyCollection_T__Count)).AsMember(iReadOnlyCollectionT), generateCount)); addProperty(membersBuilder, new SynthesizedReadOnlyListProperty( this, - ((PropertySymbol)wellKnownReadOnlyListIndexer.AssociatedSymbol).AsMember(iReadOnlyListT), + ((PropertySymbol)((MethodSymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_IReadOnlyList_T__get_Item)).AssociatedSymbol).AsMember(iReadOnlyListT), generateIndexer)); } addProperty(membersBuilder, diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index 7700fefb84a1c..e862398fc12e3 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -9611,8 +9611,8 @@ static void Main() [InlineData((int)WellKnownMember.System_Collections_IList__Insert, "System.Collections.IList", "Insert")] [InlineData((int)WellKnownMember.System_Collections_IList__Remove, "System.Collections.IList", "Remove")] [InlineData((int)WellKnownMember.System_Collections_IList__RemoveAt, "System.Collections.IList", "RemoveAt")] - [InlineData((int)WellKnownMember.System_Collections_Generic_IReadOnlyCollection_T__Count, "System.Collections.Generic.IReadOnlyCollection`1", "Count", true)] - [InlineData((int)WellKnownMember.System_Collections_Generic_IReadOnlyList_T__get_Item, "System.Collections.Generic.IReadOnlyList`1", "get_Item", true)] + [InlineData((int)WellKnownMember.System_Collections_Generic_IReadOnlyCollection_T__Count, "System.Collections.Generic.IReadOnlyCollection`1", "Count")] + [InlineData((int)WellKnownMember.System_Collections_Generic_IReadOnlyList_T__get_Item, "System.Collections.Generic.IReadOnlyList`1", "get_Item")] [InlineData((int)WellKnownMember.System_Collections_Generic_ICollection_T__Count, "System.Collections.Generic.ICollection`1", "Count")] [InlineData((int)WellKnownMember.System_Collections_Generic_ICollection_T__IsReadOnly, "System.Collections.Generic.ICollection`1", "IsReadOnly")] [InlineData((int)WellKnownMember.System_Collections_Generic_ICollection_T__Add, "System.Collections.Generic.ICollection`1", "Add")] @@ -9625,7 +9625,7 @@ static void Main() [InlineData((int)WellKnownMember.System_Collections_Generic_IList_T__Insert, "System.Collections.Generic.IList`1", "Insert")] [InlineData((int)WellKnownMember.System_Collections_Generic_IList_T__RemoveAt, "System.Collections.Generic.IList`1", "RemoveAt")] [InlineData((int)WellKnownMember.System_NotSupportedException__ctor, "System.NotSupportedException", ".ctor")] - public void SynthesizedReadOnlyList_MissingWellKnownMembers(int missingMember, string missingMemberTypeName, string missingMemberName, bool isOptional = false) + public void SynthesizedReadOnlyList_MissingWellKnownMembers(int missingMember, string missingMemberTypeName, string missingMemberName) { string source = """ using System.Collections.Generic; @@ -9640,16 +9640,13 @@ static void Main() """; var comp = CreateCompilation(source); comp.MakeMemberMissing((WellKnownMember)missingMember); - comp.VerifyEmitDiagnostics(isOptional - ? [] - : [ - // (6,30): error CS0656: Missing compiler required member 'System.Collections.Generic.IReadOnlyCollection`1.Count' - // IEnumerable x = [0]; - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[0]").WithArguments(missingMemberTypeName, missingMemberName).WithLocation(6, 30), - // (7,30): error CS0656: Missing compiler required member 'System.Collections.Generic.IReadOnlyCollection`1.Count' - // IEnumerable y = [..x]; - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[..x]").WithArguments(missingMemberTypeName, missingMemberName).WithLocation(7, 30) - ]); + comp.VerifyEmitDiagnostics( + // (6,30): error CS0656: Missing compiler required member 'System.Collections.Generic.IReadOnlyCollection`1.Count' + // IEnumerable x = [0]; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[0]").WithArguments(missingMemberTypeName, missingMemberName).WithLocation(6, 30), + // (7,30): error CS0656: Missing compiler required member 'System.Collections.Generic.IReadOnlyCollection`1.Count' + // IEnumerable y = [..x]; + Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[..x]").WithArguments(missingMemberTypeName, missingMemberName).WithLocation(7, 30)); } [Theory] From 42a7098b20719ff84936a62e5c8b19ab94a60993 Mon Sep 17 00:00:00 2001 From: jnm2 Date: Thu, 7 Dec 2023 18:19:46 -0500 Subject: [PATCH 3/5] Remove unnecessary field and finish reverting addProperty edits --- .../SynthesizedReadOnlyListTypeSymbol.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs index b7188b6f3fc65..15615c8c756e9 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs @@ -226,7 +226,6 @@ internal static NamedTypeSymbol Create(SourceModuleSymbol containingModule, stri } private readonly ModuleSymbol _containingModule; - private readonly bool _hasReadOnlyInterfaces; private readonly ImmutableArray _interfaces; private readonly ImmutableArray _members; private readonly FieldSymbol _field; @@ -237,7 +236,6 @@ private SynthesizedReadOnlyListTypeSymbol(SourceModuleSymbol containingModule, s _containingModule = containingModule; Name = name; - _hasReadOnlyInterfaces = hasReadOnlyInterfaces; var typeParameter = new SynthesizedReadOnlyListTypeParameterSymbol(this); TypeParameters = ImmutableArray.Create(typeParameter); var typeArgs = TypeArgumentsWithAnnotationsNoUseSiteDiagnostics; @@ -256,7 +254,7 @@ 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 = _hasReadOnlyInterfaces + _interfaces = hasReadOnlyInterfaces ? ImmutableArray.Create( iEnumerable, iCollection, @@ -360,17 +358,17 @@ private SynthesizedReadOnlyListTypeSymbol(SourceModuleSymbol containingModule, s this, ((MethodSymbol)compilation.GetSpecialTypeMember(SpecialMember.System_Collections_Generic_IEnumerable_T__GetEnumerator)!).AsMember(iEnumerableT), generateGetEnumeratorT)); - if (_hasReadOnlyInterfaces) + if (hasReadOnlyInterfaces) { addProperty(membersBuilder, new SynthesizedReadOnlyListProperty( this, - ((PropertySymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_IReadOnlyCollection_T__Count)).AsMember(iReadOnlyCollectionT), + ((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), + ((PropertySymbol)((MethodSymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Collections_Generic_IReadOnlyList_T__get_Item)!).AssociatedSymbol).AsMember(iReadOnlyListT), generateIndexer)); } addProperty(membersBuilder, From 7dabde7bd0748983b02c1d694f0e46d85e47fc04 Mon Sep 17 00:00:00 2001 From: jnm2 Date: Thu, 7 Dec 2023 18:59:43 -0500 Subject: [PATCH 4/5] Whitespace --- .../ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs index 15615c8c756e9..d95a736e0405d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/ReadOnlyListType/SynthesizedReadOnlyListTypeSymbol.cs @@ -32,7 +32,7 @@ internal sealed class SynthesizedReadOnlyListTypeSymbol : NamedTypeSymbol 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, From a37167fda66a24e34fb7a4ffb783bd455d8e1be3 Mon Sep 17 00:00:00 2001 From: jnm2 Date: Mon, 11 Dec 2023 22:39:53 -0500 Subject: [PATCH 5/5] Add suggested test --- .../Semantics/CollectionExpressionTests.cs | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs index e862398fc12e3..5d69e61707763 100644 --- a/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Semantics/CollectionExpressionTests.cs @@ -9499,6 +9499,71 @@ static void Main() ]); } + [Theory] + [InlineData(new SpecialType[0])] + [InlineData(new[] { SpecialType.System_Collections_Generic_IReadOnlyCollection_T })] + [InlineData(new[] { SpecialType.System_Collections_Generic_IReadOnlyList_T })] + [InlineData(new[] { SpecialType.System_Collections_Generic_IReadOnlyCollection_T, + SpecialType.System_Collections_Generic_IReadOnlyList_T })] + public void SynthesizedReadOnlyList_MissingOptionalSpecialTypes(SpecialType[] missingTypes) + { + string source = """ + using System.Collections.Generic; + class Program + { + static void Main() + { + IEnumerable x = [0]; + IEnumerable y = [..x]; + } + } + """; + + var comp = CreateCompilation(source); + foreach (var missingType in missingTypes) + { + comp.MakeTypeMissing(missingType); + } + + var verifier = CompileAndVerify( + comp, + symbolValidator: module => + { + verifyInterfaces(module, "<>z__ReadOnlyArray"); + verifyInterfaces(module, "<>z__ReadOnlyList"); + }); + verifier.VerifyDiagnostics(); + + void verifyInterfaces(ModuleSymbol module, string typeName) + { + var synthesizedType = module.GlobalNamespace.GetTypeMember(typeName); + var interfaces = synthesizedType.InterfacesNoUseSiteDiagnostics(); + AssertEx.Equal( + missingTypes is [] + ? new[] + { + "System.Collections.IEnumerable", + "System.Collections.ICollection", + "System.Collections.IList", + "System.Collections.Generic.IEnumerable", + "System.Collections.Generic.IReadOnlyCollection", + "System.Collections.Generic.IReadOnlyList", + "System.Collections.Generic.ICollection", + "System.Collections.Generic.IList", + } + : new[] + { + "System.Collections.IEnumerable", + "System.Collections.ICollection", + "System.Collections.IList", + "System.Collections.Generic.IEnumerable", + "System.Collections.Generic.ICollection", + "System.Collections.Generic.IList", + }, + interfaces.ToTestDisplayStrings()); + } + } + [Theory] [InlineData((int)SpecialMember.System_Collections_IEnumerable__GetEnumerator, "System.Collections.IEnumerable", "GetEnumerator")] [InlineData((int)SpecialMember.System_Collections_Generic_IEnumerable_T__GetEnumerator, "System.Collections.Generic.IEnumerable`1", "GetEnumerator")]