Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Fix ASP0016 false positive for nested anonymous functions #64174

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
Copilot wants to merge 2 commits into main
base: main
Choose a base branch
Loading
from copilot/add-test-nested-anonymous-methods

Conversation

Copy link
Contributor

Copilot AI commented Oct 27, 2025
edited
Loading

The ASP0016 analyzer incorrectly flagged Task<T> returns from nested anonymous functions as returns from the parent RequestDelegate. This caused false positives when lambdas returning Task<T> were passed to methods like Assert.ThrowsAsync:

app.Run(async context =>
{
 // This lambda returns Task<Stream>, but it's passed to ThrowsAsync, not returned from the RequestDelegate
 var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => upgradeFeature.UpgradeAsync());
});

Changes

  • Added IsReturnFromNestedAnonymousFunction helper that walks the parent chain to detect returns from nested anonymous functions
  • Modified the analyzer to skip return operations that belong to nested anonymous functions rather than the RequestDelegate itself
  • Added test cases covering both simple nested lambdas and lambdas passed to method calls

The fix uses ReferenceEquals to distinguish between the target RequestDelegate and any nested anonymous functions in its body, ensuring only direct returns from the RequestDelegate are analyzed.

Original prompt

This section details on the original issue you should resolve

<issue_title>ASP0016 False positive for nested anonymous methods</issue_title>
<issue_description>You can add the following test to RequestDelegateReturnTypeAnalyzerTests.cs:

 [Fact]
 public async Task AnonymousDelegate_RequestDelegate_ReturnType_InNestedAynonymousDelegate_DoesNotReportDiagnostics()
 {
 await VerifyCS.VerifyAnalyzerAsync(@"
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
var webApp = WebApplication.Create();
webApp.Run((context) =>
{
 Func<Task<DateTime>> _ = () => Task.FromResult(DateTime.Now);
 return Task.CompletedTask;
});
");
 }

And you'll get the following failure:

 Message: 
System.InvalidOperationException : Mismatch between number of diagnostics returned, expected "0" actual "1"
Diagnostics:
// /0/Test0.cs(6,12): warning ASP0016: The method used to create a RequestDelegate returns Task<System.DateTime>. RequestDelegate discards this value. If this isn't intended then change the return type to non-generic Task or, if the delegate is a route handler, cast it to Delegate so the return value is written to the response.
VerifyCS.Diagnostic().WithSpan(6, 12, 10, 2).WithArguments("System.DateTime"),
 Stack Trace: 
DefaultVerifier.Equal[T](T expected, T actual, String message)
AnalyzerTest`1.VerifyDiagnosticResults(IEnumerable`1 actualResults, ImmutableArray`1 analyzers, DiagnosticResult[] expectedResults, IVerifier verifier)
AnalyzerTest`1.VerifyDiagnosticsAsync(EvaluatedProjectState primaryProject, ImmutableArray`1 additionalProjects, DiagnosticResult[] expected, IVerifier verifier, CancellationToken cancellationToken)
AnalyzerTest`1.RunImplAsync(CancellationToken cancellationToken)
AnalyzerTest`1.RunAsync(CancellationToken cancellationToken)
CSharpAnalyzerVerifier`1.VerifyAnalyzerAsync(String source, DiagnosticResult[] expected) line 46
RequestDelegateReturnTypeAnalyzerTests.AnonymousDelegate_RequestDelegate_ReturnType_InNestedAynonymousDelegate_DoesNotReportDiagnostics() line 73
--- End of stack trace from previous location ---

This is incorrect because the Task<System.DateTime> is not being returned directly from the anonymous RequestDelegate, but instead an inner anonymous method which is not a RequestDelegate. This was uncovered by #64120 which resulted in the following line getting incorrectly flagged by ASP0016 even though the lambda calling UpgradeAsync() and returning a Task<Stream> was being passed to ThrowsAsync as a Func<Task<Stream>> and was never converted to a RequestDelegate.

var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => upgradeFeature.UpgradeAsync());
D:\a\_work1円\s\src\Servers\IIS\IIS\test\testassets\InProcessWebSite\Startup.WebSockets.cs(98,17): error ASP0016: The method used to create a RequestDelegate returns Task<System.IO.Stream>. RequestDelegate discards this value. If this isn't intended then change the return type to non-generic Task or, if the delegate is a route handler, cast it to Delegate so the return value is written to the response. (https://aka.ms/aspnet/analyzers) [D:\a\_work1円\s\src\Servers\IIS\IIS\test\testassets\InProcessNewShimWebSite\InProcessNewShimWebSite.csproj::TargetFramework=net8.0]
##[error]src\Servers\IIS\IIS\test\testassets\InProcessWebSite\Startup.WebSockets.cs(98,17): error ASP0016: (NETCORE_ENGINEERING_TELEMETRY=Build) The method used to create a RequestDelegate returns Task<System.IO.Stream>. RequestDelegate discards this value. If this isn't intended then change the return type to non-generic Task or, if the delegate is a route handler, cast it to Delegate so the return value is written to the response. (https://aka.ms/aspnet/analyzers)

https://dev.azure.com/dnceng-public/public/_build/results?buildId=1186969&view=logs&jobId=1e4c7542-9334-5468-a143-1d4c0c4c3006%3Fpr%3D64120&j=4192b01c-4527-54c8-cf65-dc27f588da45&t=ee2d7ee8-2075-51eb-eb72-626500250fa2&s=d654deb9-056d-50a2-1717-90c08683d50a

@JamesNK </issue_description>

<agent_instructions>Fix RequestDelegateReturnTypeAnalyzer so when it recurses over the operations in anonymousFunction.Body it avoids considering the IReturnOperation that belong to nested IAnonymousFunctionOperation.</agent_instructions>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copy link
Contributor

Greetings human! You've submitted a PR that modifies code that is shared with https://github.com/dotnet/runtime . Please make sure you synchronize this code with the changes in that repo!

Co-authored-by: halter73 <54385+halter73@users.noreply.github.com>
Copilot AI changed the title (削除) [WIP] Add test for nested anonymous methods in RequestDelegateReturnTypeAnalyzerTests (削除ここまで) (追記) Fix ASP0016 false positive for nested anonymous functions (追記ここまで) Oct 27, 2025
Copilot AI requested a review from halter73 October 27, 2025 23:39
Copilot finished work on behalf of halter73 October 27, 2025 23:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@halter73 halter73 Awaiting requested review from halter73

At least 1 approving review is required to merge this pull request.

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

ASP0016 False positive for nested anonymous methods

2 participants

AltStyle によって変換されたページ (->オリジナル) /