|
7 | 7 | using System.Collections.Immutable; |
8 | 8 | using System.Diagnostics; |
9 | 9 | using System.Diagnostics.CodeAnalysis; |
10 | | -using Microsoft.CodeAnalysis.CSharp.CodeGen; |
11 | 10 | using Microsoft.CodeAnalysis.CSharp.Symbols; |
12 | 11 | using Microsoft.CodeAnalysis.PooledObjects; |
13 | 12 | using Roslyn.Utilities; |
@@ -2253,7 +2252,8 @@ private bool CheckInvocationEscapeWithUpdatedRules( |
2253 | 2252 | // For consistency with C#10 implementation, we don't report an additional error |
2254 | 2253 | // for the receiver. (In both implementations, the call to Check*Escape() above |
2255 | 2254 | // will have reported a specific escape error for the receiver though.) |
2256 | | - if ((object)((argument as BoundCapturedReceiverPlaceholder)?.Receiver ?? argument) != receiver && symbol is not SignatureOnlyMethodSymbol) |
| 2255 | + bool argumentIsReceiver = (object)((argument as BoundCapturedReceiverPlaceholder)?.Receiver ?? argument) == receiver; |
| 2256 | + if ((!argumentIsReceiver || param?.IsExtensionParameter() == true) && symbol is not SignatureOnlyMethodSymbol) |
2257 | 2257 | { |
2258 | 2258 | ReportInvocationEscapeError(syntax, symbol, param, checkingReceiver, diagnostics); |
2259 | 2259 | } |
@@ -2289,25 +2289,46 @@ private void GetInvocationArgumentsForEscape( |
2289 | 2289 | { |
2290 | 2290 | if (receiver is { }) |
2291 | 2291 | { |
2292 | | - Debug.Assert(receiver.Type is { }); |
2293 | | - Debug.Assert(receiverIsSubjectToCloning != ThreeState.Unknown); |
2294 | | - var method = methodInfo.Method; |
2295 | | - if (receiverIsSubjectToCloning == ThreeState.True) |
| 2292 | + MethodSymbol? method = methodInfo.Method; |
| 2293 | + if (method?.GetIsNewExtensionMember() == true) |
2296 | 2294 | { |
2297 | | - Debug.Assert(receiver is not BoundValuePlaceholderBase && method is not null && receiver.Type?.IsReferenceType == false); |
| 2295 | + // Analyze the receiver as an argument |
| 2296 | + var parameter = method.ContainingType.ExtensionParameter; |
| 2297 | + |
| 2298 | + if (mixableArguments is not null |
| 2299 | + && isMixableParameter(parameter) |
| 2300 | + // assume any expression variable is a valid mixing destination, |
| 2301 | + // since we will infer a legal val-escape for it (if it doesn't already have a narrower one). |
| 2302 | + && isMixableArgument(receiver)) |
| 2303 | + { |
| 2304 | + mixableArguments.Add(new MixableDestination(parameter, receiver)); |
| 2305 | + } |
| 2306 | + |
| 2307 | + var refKind = parameter?.RefKind ?? RefKind.None; |
| 2308 | + |
| 2309 | + escapeArguments.Add(new EscapeArgument(parameter, receiver, refKind)); |
| 2310 | + } |
| 2311 | + else |
| 2312 | + { |
| 2313 | + Debug.Assert(receiver.Type is { }); |
| 2314 | + Debug.Assert(receiverIsSubjectToCloning != ThreeState.Unknown); |
| 2315 | + if (receiverIsSubjectToCloning == ThreeState.True) |
| 2316 | + { |
| 2317 | + Debug.Assert(receiver is not BoundValuePlaceholderBase && method is not null && receiver.Type?.IsReferenceType == false); |
2298 | 2318 | #if DEBUG |
2299 | | - AssertVisited(receiver); |
| 2319 | + AssertVisited(receiver); |
2300 | 2320 | #endif |
2301 | | - // Equivalent to a non-ref local with the underlying receiver as an initializer provided at declaration |
2302 | | - receiver = new BoundCapturedReceiverPlaceholder(receiver.Syntax, receiver, _localScopeDepth, receiver.Type).MakeCompilerGenerated(); |
2303 | | - } |
| 2321 | + // Equivalent to a non-ref local with the underlying receiver as an initializer provided at declaration |
| 2322 | + receiver = new BoundCapturedReceiverPlaceholder(receiver.Syntax, receiver, _localScopeDepth, receiver.Type).MakeCompilerGenerated(); |
| 2323 | + } |
2304 | 2324 |
|
2305 | | - var tuple = getReceiver(methodInfo, receiver); |
2306 | | - escapeArguments.Add(tuple); |
| 2325 | + var tuple = getReceiver(methodInfo, receiver); |
| 2326 | + escapeArguments.Add(tuple); |
2307 | 2327 |
|
2308 | | - if (mixableArguments is not null && isMixableParameter(tuple.Parameter)) |
2309 | | - { |
2310 | | - mixableArguments.Add(new MixableDestination(tuple.Parameter, receiver)); |
| 2328 | + if (mixableArguments is not null && isMixableParameter(tuple.Parameter)) |
| 2329 | + { |
| 2330 | + mixableArguments.Add(new MixableDestination(tuple.Parameter, receiver)); |
| 2331 | + } |
2311 | 2332 | } |
2312 | 2333 | } |
2313 | 2334 |
|
|
0 commit comments