Skip to content

Commit d9a48df

Browse files
author
Julien Couvreur
authored
Extensions: bind unconditionally of LangVer (#78947)
1 parent 97445ba commit d9a48df

File tree

8 files changed

+280
-83
lines changed

8 files changed

+280
-83
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,19 @@ internal static void ReportDiagnosticsIfObsoleteInternal(BindingDiagnosticBag di
749749
}
750750
}
751751

752+
internal static bool IsDisallowedExtensionInOlderLangVer(MethodSymbol symbol)
753+
{
754+
return symbol.GetIsNewExtensionMember() && (symbol.IsStatic || symbol.MethodKind != MethodKind.Ordinary);
755+
}
756+
757+
internal static void ReportDiagnosticsIfDisallowedExtension(BindingDiagnosticBag diagnostics, MethodSymbol method, SyntaxNode syntax)
758+
{
759+
if (IsDisallowedExtensionInOlderLangVer(method))
760+
{
761+
MessageID.IDS_FeatureExtensions.CheckFeatureAvailability(diagnostics, syntax);
762+
}
763+
}
764+
752765
internal static void ReportDiagnosticsIfUnmanagedCallersOnly(BindingDiagnosticBag diagnostics, MethodSymbol symbol, SyntaxNodeOrToken syntax, bool isDelegateConversion)
753766
{
754767
var unmanagedCallersOnlyAttributeData = symbol.GetUnmanagedCallersOnlyAttributeData(forceComplete: false);

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,7 @@ private bool HasCollectionInitializerTypeInProgress(SyntaxNode syntax, TypeSymbo
10691069
ReportDiagnosticsIfObsolete(diagnostics, collectionBuilderMethod.ContainingType, syntax, hasBaseReceiver: false);
10701070
ReportDiagnosticsIfObsolete(diagnostics, collectionBuilderMethod, syntax, hasBaseReceiver: false);
10711071
ReportDiagnosticsIfUnmanagedCallersOnly(diagnostics, collectionBuilderMethod, syntax, isDelegateConversion: false);
1072+
Debug.Assert(!collectionBuilderMethod.GetIsNewExtensionMember());
10721073

10731074
return collectionBuilderMethod;
10741075
}
@@ -1430,11 +1431,14 @@ static bool bindMethodGroupInvocation(
14301431
{
14311432
addMethodBinder.ReportDiagnosticsIfObsolete(diagnostics, addMethods[0], syntax, hasBaseReceiver: false);
14321433
ReportDiagnosticsIfUnmanagedCallersOnly(diagnostics, addMethods[0], syntax, isDelegateConversion: false);
1434+
Debug.Assert(!IsDisallowedExtensionInOlderLangVer(addMethods[0]));
14331435
}
14341436
}
14351437
}
14361438
else
14371439
{
1440+
Debug.Assert(!resolution.OverloadResolutionResult.Succeeded);
1441+
14381442
result = bindInvocationExpressionContinued(
14391443
addMethodBinder, syntax, expression, resolution.OverloadResolutionResult, resolution.AnalyzedArguments,
14401444
resolution.MethodGroup, diagnostics: diagnostics, out var addMethod);
@@ -1622,6 +1626,7 @@ static bool bindInvocationExpressionContinued(
16221626

16231627
addMethodBinder.ReportDiagnosticsIfObsolete(diagnostics, method, node, hasBaseReceiver: false);
16241628
ReportDiagnosticsIfUnmanagedCallersOnly(diagnostics, method, node, isDelegateConversion: false);
1629+
ReportDiagnosticsIfDisallowedExtension(diagnostics, method, node);
16251630

16261631
// No use site errors, but there could be use site warnings.
16271632
// If there are any use site warnings, they have already been reported by overload resolution.
@@ -3051,6 +3056,7 @@ private bool MethodGroupConversionHasErrors(
30513056
ReportDiagnosticsIfUnmanagedCallersOnly(diagnostics, selectedMethod, syntax, isDelegateConversion: true);
30523057
}
30533058
ReportDiagnosticsIfObsolete(diagnostics, selectedMethod, syntax, hasBaseReceiver: false);
3059+
ReportDiagnosticsIfDisallowedExtension(diagnostics, selectedMethod, syntax);
30543060

30553061
// No use site errors, but there could be use site warnings.
30563062
// If there are use site warnings, they were reported during the overload resolution process

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8030,6 +8030,7 @@ private BoundExpression MakeMemberAccessValue(BoundExpression expr, BindingDiagn
80308030

80318031
private BoundExpression GetExtensionMemberAccess(SyntaxNode syntax, BoundExpression? receiver, Symbol extensionMember, BindingDiagnosticBag diagnostics)
80328032
{
8033+
MessageID.IDS_FeatureExtensions.CheckFeatureAvailability(diagnostics, syntax);
80338034
receiver = ReplaceTypeOrValueReceiver(receiver, useType: extensionMember.IsStatic, diagnostics);
80348035

80358036
switch (extensionMember)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,7 @@ private BoundCall BindInvocationExpressionContinued(
13251325

13261326
ReportDiagnosticsIfObsolete(diagnostics, method, node, hasBaseReceiver);
13271327
ReportDiagnosticsIfUnmanagedCallersOnly(diagnostics, method, node, isDelegateConversion: false);
1328+
ReportDiagnosticsIfDisallowedExtension(diagnostics, method, node);
13281329

13291330
// No use site errors, but there could be use site warnings.
13301331
// If there are any use site warnings, they have already been reported by overload resolution.

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

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -202,37 +202,34 @@ internal void EnumerateAllExtensionMembersInSingleBinder(ArrayBuilder<SingleLook
202202
PooledHashSet<MethodSymbol>? implementationsToShadow = null;
203203

204204
// 1. Collect new extension members
205-
if (this.Compilation.LanguageVersion.AllowNewExtensions())
206-
{
207-
var extensionDeclarations = ArrayBuilder<NamedTypeSymbol>.GetInstance();
208-
this.GetExtensionDeclarations(extensionDeclarations, originalBinder);
205+
var extensionDeclarations = ArrayBuilder<NamedTypeSymbol>.GetInstance();
206+
this.GetExtensionDeclarations(extensionDeclarations, originalBinder);
209207

210-
foreach (NamedTypeSymbol extensionDeclaration in extensionDeclarations)
208+
foreach (NamedTypeSymbol extensionDeclaration in extensionDeclarations)
209+
{
210+
if (extensionDeclaration.ExtensionParameter is null)
211211
{
212-
if (extensionDeclaration.ExtensionParameter is null)
213-
{
214-
continue;
215-
}
212+
continue;
213+
}
216214

217-
var candidates = name is null ? extensionDeclaration.GetMembers() : extensionDeclaration.GetMembers(name);
215+
var candidates = name is null ? extensionDeclaration.GetMembers() : extensionDeclaration.GetMembers(name);
218216

219-
foreach (var candidate in candidates)
220-
{
221-
SingleLookupResult resultOfThisMember = originalBinder.CheckViability(candidate, arity, options, null, diagnose: true, useSiteInfo: ref useSiteInfo);
222-
result.Add(resultOfThisMember);
217+
foreach (var candidate in candidates)
218+
{
219+
SingleLookupResult resultOfThisMember = originalBinder.CheckViability(candidate, arity, options, null, diagnose: true, useSiteInfo: ref useSiteInfo);
220+
result.Add(resultOfThisMember);
223221

224-
if (candidate is MethodSymbol { IsStatic: false } shadows &&
225-
shadows.OriginalDefinition.TryGetCorrespondingExtensionImplementationMethod() is { } toShadow)
226-
{
227-
implementationsToShadow ??= PooledHashSet<MethodSymbol>.GetInstance();
228-
implementationsToShadow.Add(toShadow);
229-
}
222+
if (candidate is MethodSymbol { IsStatic: false } shadows &&
223+
shadows.OriginalDefinition.TryGetCorrespondingExtensionImplementationMethod() is { } toShadow)
224+
{
225+
implementationsToShadow ??= PooledHashSet<MethodSymbol>.GetInstance();
226+
implementationsToShadow.Add(toShadow);
230227
}
231228
}
232-
233-
extensionDeclarations.Free();
234229
}
235230

231+
extensionDeclarations.Free();
232+
236233
// 2. Collect classic extension methods
237234
var extensionMethods = ArrayBuilder<MethodSymbol>.GetInstance();
238235
this.GetCandidateExtensionMethods(extensionMethods, name, arity, options, originalBinder: originalBinder);

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,12 +465,16 @@ private BoundForEachStatement BindForEachPartsWorker(BindingDiagnosticBag diagno
465465
var foreachKeyword = _syntax.ForEachKeyword;
466466
ReportDiagnosticsIfObsolete(diagnostics, getEnumeratorMethod, foreachKeyword, hasBaseReceiver: false);
467467
ReportDiagnosticsIfUnmanagedCallersOnly(diagnostics, getEnumeratorMethod, foreachKeyword, isDelegateConversion: false);
468+
Debug.Assert(!IsDisallowedExtensionInOlderLangVer(getEnumeratorMethod));
469+
468470
// MoveNext is an instance method, so it does not need to have unmanaged callers only diagnostics reported.
469471
// Either a diagnostic was reported at the declaration of the method (for the invalid attribute), or MoveNext
470472
// is marked as not supported and we won't get here in the first place (for metadata import).
471473
ReportDiagnosticsIfObsolete(diagnostics, builder.MoveNextInfo.Method, foreachKeyword, hasBaseReceiver: false);
472474
ReportDiagnosticsIfObsolete(diagnostics, builder.CurrentPropertyGetter, foreachKeyword, hasBaseReceiver: false);
473475
ReportDiagnosticsIfObsolete(diagnostics, builder.CurrentPropertyGetter.AssociatedSymbol, foreachKeyword, hasBaseReceiver: false);
476+
Debug.Assert(!IsDisallowedExtensionInOlderLangVer(builder.MoveNextInfo.Method));
477+
Debug.Assert(!IsDisallowedExtensionInOlderLangVer(builder.CurrentPropertyGetter));
474478

475479
// We want to convert from inferredType in the array/string case and builder.ElementType in the enumerator case,
476480
// but it turns out that these are equivalent (when both are available).

src/Compilers/CSharp/Portable/LanguageVersion.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -572,10 +572,5 @@ internal static bool AllowImprovedOverloadCandidates(this LanguageVersion self)
572572
{
573573
return self >= MessageID.IDS_FeatureImprovedOverloadCandidates.RequiredVersion();
574574
}
575-
576-
internal static bool AllowNewExtensions(this LanguageVersion self)
577-
{
578-
return self >= MessageID.IDS_FeatureExtensions.RequiredVersion();
579-
}
580575
}
581576
}

0 commit comments

Comments
 (0)