Skip to content

Commit d3350fa

Browse files
authored
Extensions: interceptors (#79010)
1 parent a34972d commit d3350fa

File tree

4 files changed

+1139
-34
lines changed

4 files changed

+1139
-34
lines changed

src/Compilers/CSharp/Portable/Lowering/ExtensionMethodReferenceRewriter.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ public static BoundNode VisitCall(BoundTreeRewriter rewriter, BoundCall node)
7474

7575
static BoundExpression visitArgumentsAndFinishRewrite(BoundTreeRewriter rewriter, BoundCall node, BoundExpression? rewrittenReceiver)
7676
{
77+
Debug.Assert(node.Method.MethodKind == MethodKind.LocalFunction || node.Method.IsStatic || node.ReceiverOpt is not null);
78+
7779
return updateCall(
7880
node,
7981
VisitMethodSymbolWithExtensionRewrite(rewriter, node.Method),

src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Call.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,18 @@ private void InterceptCallAndAdjustArguments(
147147
return;
148148
}
149149

150+
if (interceptor.GetIsNewExtensionMember())
151+
{
152+
if (interceptor.TryGetCorrespondingExtensionImplementationMethod() is { } implementationMethod)
153+
{
154+
interceptor = implementationMethod;
155+
}
156+
else
157+
{
158+
throw ExceptionUtilities.Unreachable();
159+
}
160+
}
161+
150162
Debug.Assert(nameSyntax != null);
151163
Debug.Assert(interceptor.IsDefinition);
152164
Debug.Assert(!interceptor.ContainingType.IsGenericType);
@@ -228,9 +240,12 @@ private void InterceptCallAndAdjustArguments(
228240
this._diagnostics.Add(ErrorCode.WRN_InterceptorSignatureMismatch, attributeLocation, method, interceptor);
229241
}
230242

231-
method.TryGetThisParameter(out var methodThisParameter);
232-
var interceptorThisParameterForCompare = needToReduce ? interceptor.Parameters[0] :
243+
ParameterSymbol? methodThisParameter;
244+
_ = method.TryGetInstanceExtensionParameter(out methodThisParameter) || method.TryGetThisParameter(out methodThisParameter);
245+
246+
ParameterSymbol? interceptorThisParameterForCompare = needToReduce ? interceptor.Parameters[0] :
233247
interceptor.TryGetThisParameter(out var interceptorThisParameter) ? interceptorThisParameter : null;
248+
234249
switch (methodThisParameter, interceptorThisParameterForCompare)
235250
{
236251
case (not null, null):

src/Compilers/CSharp/Portable/Symbols/Source/SourceMethodSymbolWithAttributes.cs

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,23 +1036,9 @@ private void DecodeInterceptsLocationChecksumBased(DecodeWellKnownAttributeArgum
10361036
}
10371037
thisNamespaceNames.Free();
10381038

1039-
if (ContainingType.IsGenericType)
1039+
bool hadError = ReportBadInterceptsLocation(diagnostics, attributeLocation);
1040+
if (hadError)
10401041
{
1041-
diagnostics.Add(ErrorCode.ERR_InterceptorContainingTypeCannotBeGeneric, attributeLocation, this);
1042-
return;
1043-
}
1044-
1045-
if (MethodKind != MethodKind.Ordinary)
1046-
{
1047-
diagnostics.Add(ErrorCode.ERR_InterceptorMethodMustBeOrdinary, attributeLocation);
1048-
return;
1049-
}
1050-
1051-
Debug.Assert(_lazyCustomAttributesBag.IsEarlyDecodedWellKnownAttributeDataComputed);
1052-
var unmanagedCallersOnly = this.GetUnmanagedCallersOnlyAttributeData(forceComplete: false);
1053-
if (unmanagedCallersOnly != null)
1054-
{
1055-
diagnostics.Add(ErrorCode.ERR_InterceptorCannotUseUnmanagedCallersOnly, attributeLocation);
10561042
return;
10571043
}
10581044

@@ -1194,23 +1180,9 @@ private void DecodeInterceptsLocationAttributeExperimentalCompat(
11941180
return;
11951181
}
11961182

1197-
if (ContainingType.IsGenericType)
1183+
bool hadError = ReportBadInterceptsLocation(diagnostics, attributeLocation);
1184+
if (hadError)
11981185
{
1199-
diagnostics.Add(ErrorCode.ERR_InterceptorContainingTypeCannotBeGeneric, attributeLocation, this);
1200-
return;
1201-
}
1202-
1203-
if (MethodKind != MethodKind.Ordinary)
1204-
{
1205-
diagnostics.Add(ErrorCode.ERR_InterceptorMethodMustBeOrdinary, attributeLocation);
1206-
return;
1207-
}
1208-
1209-
Debug.Assert(_lazyCustomAttributesBag.IsEarlyDecodedWellKnownAttributeDataComputed);
1210-
var unmanagedCallersOnly = this.GetUnmanagedCallersOnlyAttributeData(forceComplete: false);
1211-
if (unmanagedCallersOnly != null)
1212-
{
1213-
diagnostics.Add(ErrorCode.ERR_InterceptorCannotUseUnmanagedCallersOnly, attributeLocation);
12141186
return;
12151187
}
12161188

@@ -1374,6 +1346,31 @@ static void reportFeatureNotEnabled(BindingDiagnosticBag diagnostics, AttributeS
13741346
}
13751347
}
13761348

1349+
private bool ReportBadInterceptsLocation(BindingDiagnosticBag diagnostics, Location attributeLocation)
1350+
{
1351+
if (!this.GetIsNewExtensionMember() && ContainingType.IsGenericType)
1352+
{
1353+
diagnostics.Add(ErrorCode.ERR_InterceptorContainingTypeCannotBeGeneric, attributeLocation, this);
1354+
return true;
1355+
}
1356+
1357+
if (MethodKind != MethodKind.Ordinary)
1358+
{
1359+
diagnostics.Add(ErrorCode.ERR_InterceptorMethodMustBeOrdinary, attributeLocation);
1360+
return true;
1361+
}
1362+
1363+
Debug.Assert(_lazyCustomAttributesBag.IsEarlyDecodedWellKnownAttributeDataComputed);
1364+
var unmanagedCallersOnly = this.GetUnmanagedCallersOnlyAttributeData(forceComplete: false);
1365+
if (unmanagedCallersOnly != null)
1366+
{
1367+
diagnostics.Add(ErrorCode.ERR_InterceptorCannotUseUnmanagedCallersOnly, attributeLocation);
1368+
return true;
1369+
}
1370+
1371+
return false;
1372+
}
1373+
13771374
private void DecodeUnmanagedCallersOnlyAttribute(ref DecodeWellKnownAttributeArguments<AttributeSyntax, CSharpAttributeData, AttributeLocation> arguments)
13781375
{
13791376
Debug.Assert(arguments.AttributeSyntaxOpt != null);

0 commit comments

Comments
 (0)