Skip to content

Commit 79400d2

Browse files
authored
Merge pull request #46573 from dotnet/features/extension-foreach
Merge Extension GetEnumerator into master
2 parents 7c6cbea + 6361005 commit 79400d2

45 files changed

Lines changed: 10820 additions & 1613 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/contributing/Compiler Test Plan.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ This document provides guidance for thinking about language interactions and tes
9696
- Nullability annotations (`?`, attributes) and analysis
9797
- If you add a place an expression can appear in code, make sure `SpillSequenceSpiller` handles it. Test with a `switch` expression or `stackalloc` in that place.
9898
- If you add a new expression form that requires spilling, test it in the catch filter.
99+
- extension based Dispose, DisposeAsync, GetEnumerator, GetAsyncEnumerator, Deconstruct, GetAwaiter etc.
99100

100101
# Misc
101102
- reserved keywords (sometimes contextual)

src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6613,7 +6613,7 @@ private BoundExpression BindMemberOfType(
66136613
return result;
66146614
}
66156615

6616-
private MethodGroupResolution BindExtensionMethod(
6616+
protected MethodGroupResolution BindExtensionMethod(
66176617
SyntaxNode expression,
66186618
string methodName,
66196619
AnalyzedArguments analyzedArguments,

src/Compilers/CSharp/Portable/Binder/ForEachEnumeratorInfo.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ internal sealed class ForEachEnumeratorInfo
4545

4646
public readonly BinderFlags Location;
4747

48+
public readonly Binder Binder;
49+
4850
private ForEachEnumeratorInfo(
4951
TypeSymbol collectionType,
5052
TypeWithAnnotations elementType,
@@ -58,13 +60,15 @@ private ForEachEnumeratorInfo(
5860
Conversion collectionConversion,
5961
Conversion currentConversion,
6062
Conversion enumeratorConversion,
61-
BinderFlags location)
63+
BinderFlags location,
64+
Binder binder)
6265
{
6366
Debug.Assert((object)collectionType != null, "Field 'collectionType' cannot be null");
6467
Debug.Assert(elementType.HasType, "Field 'elementType' cannot be null");
6568
Debug.Assert((object)getEnumeratorMethod != null, "Field 'getEnumeratorMethod' cannot be null");
6669
Debug.Assert((object)currentPropertyGetter != null, "Field 'currentPropertyGetter' cannot be null");
6770
Debug.Assert((object)moveNextMethod != null, "Field 'moveNextMethod' cannot be null");
71+
Debug.Assert(binder != null, "Field 'binder' cannot be null");
6872

6973
this.CollectionType = collectionType;
7074
this.ElementTypeWithAnnotations = elementType;
@@ -79,6 +83,7 @@ private ForEachEnumeratorInfo(
7983
this.CurrentConversion = currentConversion;
8084
this.EnumeratorConversion = enumeratorConversion;
8185
this.Location = location;
86+
this.Binder = binder;
8287
}
8388

8489
// Mutable version of ForEachEnumeratorInfo. Convert to immutable using Build.
@@ -101,6 +106,8 @@ internal struct Builder
101106
public Conversion CurrentConversion;
102107
public Conversion EnumeratorConversion;
103108

109+
public Binder Binder;
110+
104111
public ForEachEnumeratorInfo Build(BinderFlags location)
105112
{
106113
Debug.Assert((object)CollectionType != null, "'CollectionType' cannot be null");
@@ -109,6 +116,7 @@ public ForEachEnumeratorInfo Build(BinderFlags location)
109116

110117
Debug.Assert(MoveNextMethod != null);
111118
Debug.Assert(CurrentPropertyGetter != null);
119+
Debug.Assert(Binder != null);
112120

113121
return new ForEachEnumeratorInfo(
114122
CollectionType,
@@ -123,7 +131,8 @@ public ForEachEnumeratorInfo Build(BinderFlags location)
123131
CollectionConversion,
124132
CurrentConversion,
125133
EnumeratorConversion,
126-
location);
134+
location,
135+
Binder);
127136
}
128137

129138
public bool IsIncomplete

src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs

Lines changed: 180 additions & 55 deletions
Large diffs are not rendered by default.

src/Compilers/CSharp/Portable/CSharpResources.resx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,11 +1185,11 @@
11851185
<data name="WRN_PatternIsAmbiguous_Title" xml:space="preserve">
11861186
<value>Type does not implement the collection pattern; members are ambiguous</value>
11871187
</data>
1188-
<data name="WRN_PatternStaticOrInaccessible" xml:space="preserve">
1189-
<value>'{0}' does not implement the '{1}' pattern. '{2}' is either static or not public.</value>
1188+
<data name="WRN_PatternNotPublicOrNotInstance" xml:space="preserve">
1189+
<value>'{0}' does not implement the '{1}' pattern. '{2}' is not a public instance or extension method.</value>
11901190
</data>
1191-
<data name="WRN_PatternStaticOrInaccessible_Title" xml:space="preserve">
1192-
<value>Type does not implement the collection pattern; member is either static or not public</value>
1191+
<data name="WRN_PatternNotPublicOrNotInstance_Title" xml:space="preserve">
1192+
<value>Type does not implement the collection pattern; member is is not a public instance or extension method.</value>
11931193
</data>
11941194
<data name="WRN_PatternBadSignature" xml:space="preserve">
11951195
<value>'{0}' does not implement the '{1}' pattern. '{2}' has the wrong signature.</value>
@@ -2699,16 +2699,16 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep
26992699
<value>#r is only allowed in scripts</value>
27002700
</data>
27012701
<data name="ERR_ForEachMissingMember" xml:space="preserve">
2702-
<value>foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'</value>
2702+
<value>foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}'</value>
27032703
</data>
27042704
<data name="ERR_AwaitForEachMissingMember" xml:space="preserve">
2705-
<value>Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance definition for '{1}'</value>
2705+
<value>Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a suitable public instance or extension definition for '{1}'</value>
27062706
</data>
27072707
<data name="ERR_ForEachMissingMemberWrongAsync" xml:space="preserve">
2708-
<value>foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'?</value>
2708+
<value>foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}'. Did you mean 'await foreach' rather than 'foreach'?</value>
27092709
</data>
27102710
<data name="ERR_AwaitForEachMissingMemberWrongAsync" xml:space="preserve">
2711-
<value>Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'?</value>
2711+
<value>Asynchronous foreach statement cannot operate on variables of type '{0}' because '{0}' does not contain a public instance or extension definition for '{1}'. Did you mean 'foreach' rather than 'await foreach'?</value>
27122712
</data>
27132713
<data name="ERR_PossibleAsyncIteratorWithoutYield" xml:space="preserve">
27142714
<value>The body of an async-iterator method must contain a 'yield' statement.</value>
@@ -6430,4 +6430,10 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
64306430
<data name="ERR_ModuleInitializerMethodMustBeOrdinary" xml:space="preserve">
64316431
<value>A module initializer must be an ordinary member method</value>
64326432
</data>
6433-
</root>
6433+
<data name="IDS_FeatureExtensionGetAsyncEnumerator" xml:space="preserve">
6434+
<value>extension GetAsyncEnumerator</value>
6435+
</data>
6436+
<data name="IDS_FeatureExtensionGetEnumerator" xml:space="preserve">
6437+
<value>extension GetEnumerator</value>
6438+
</data>
6439+
</root>

src/Compilers/CSharp/Portable/Errors/ErrorCode.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ internal enum ErrorCode
239239
ERR_AccessModMissingAccessor = 276,
240240
ERR_UnimplementedInterfaceAccessor = 277,
241241
WRN_PatternIsAmbiguous = 278,
242-
WRN_PatternStaticOrInaccessible = 279,
242+
WRN_PatternNotPublicOrNotInstance = 279,
243243
WRN_PatternBadSignature = 280,
244244
ERR_FriendRefNotEqualToThis = 281,
245245
WRN_SequentialOnPartialClass = 282,

src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ internal static int GetWarningLevel(ErrorCode code)
274274
case ErrorCode.WRN_BadRefCompareLeft:
275275
case ErrorCode.WRN_BadRefCompareRight:
276276
case ErrorCode.WRN_PatternIsAmbiguous:
277-
case ErrorCode.WRN_PatternStaticOrInaccessible:
277+
case ErrorCode.WRN_PatternNotPublicOrNotInstance:
278278
case ErrorCode.WRN_PatternBadSignature:
279279
case ErrorCode.WRN_SameFullNameThisNsAgg:
280280
case ErrorCode.WRN_SameFullNameThisAggAgg:

src/Compilers/CSharp/Portable/Errors/MessageID.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ internal enum MessageID
211211
IDS_FeatureModuleInitializers = MessageBase + 12784,
212212
IDS_FeatureTargetTypedConditional = MessageBase + 12785,
213213
IDS_FeatureCovariantReturnsForOverrides = MessageBase + 12786,
214+
IDS_FeatureExtensionGetEnumerator = MessageBase + 12787,
215+
IDS_FeatureExtensionGetAsyncEnumerator = MessageBase + 12788,
214216
}
215217

216218
// Message IDs may refer to strings that need to be localized.
@@ -330,6 +332,8 @@ internal static LanguageVersion RequiredVersion(this MessageID feature)
330332
case MessageID.IDS_FeatureParenthesizedPattern:
331333
case MessageID.IDS_FeatureTypePattern:
332334
case MessageID.IDS_FeatureRelationalPattern:
335+
case MessageID.IDS_FeatureExtensionGetEnumerator: // semantic check
336+
case MessageID.IDS_FeatureExtensionGetAsyncEnumerator: // semantic check
333337
case MessageID.IDS_FeatureNativeInt:
334338
case MessageID.IDS_FeatureExtendedPartialMethods: // semantic check
335339
case MessageID.IDS_TopLevelStatements:

0 commit comments

Comments
 (0)