Fix #1411 - NativeAOT proxy accessibility and interceptor fallback#1472
Open
AArnott wants to merge 6 commits into
Open
Fix #1411 - NativeAOT proxy accessibility and interceptor fallback#1472AArnott wants to merge 6 commits into
AArnott wants to merge 6 commits into
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR improves the NativeAOT interceptor pipeline for cross-assembly RPC contracts by explicitly requiring that any reused proxy type be accessible from the calling assembly. Instead of emitting interceptor code that can’t compile (due to an inaccessible proxy), the generator now fails fast with a new diagnostic and the documentation/tests are updated to reflect the required opt-in.
Changes:
- Documented that contract assemblies referenced by NativeAOT interceptor-enabled apps must expose proxies via
[assembly: ExportRpcContractProxies]. - Added
StreamJsonRpc0040(error) and updated interceptor generation to report it when an external proxy mapping points to an inaccessible type. - Updated analyzer suppressor behavior and added/updated regression tests + expected generated outputs for the new error path.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| test/StreamJsonRpc.Analyzer.Tests/Resources/Interceptor_ExternalProxyInaccessible_DifferentProject/ContractsLib.IMyService.g.cs | Adds expected generated output used by the new regression test scenario. |
| test/StreamJsonRpc.Analyzer.Tests/ProxyGeneratorTests.cs | Adds a regression test asserting StreamJsonRpc0040 is produced for inaccessible external proxies in a referenced project. |
| src/StreamJsonRpc.Analyzers/Strings.resx | Adds user-facing strings for the new StreamJsonRpc0040 diagnostic. |
| src/StreamJsonRpc.Analyzers/ProxyGenerator.cs | Threads through invocation location + accessibility info and detects whether mapped proxy types are accessible from the calling assembly. |
| src/StreamJsonRpc.Analyzers/GeneratorModels/FullModel.cs | Filters out inaccessible external proxies from interceptor/proxy generation and reports StreamJsonRpc0040 when interceptors are enabled. |
| src/StreamJsonRpc.Analyzers/GeneratorModels/AttachUse.cs | Extends the attach-use model to carry invocation location + external proxy accessibility status. |
| src/StreamJsonRpc.Analyzers/AttachAOTDiagnosticSuppressor.cs | Avoids suppressing AOT diagnostics when the attach call won’t be intercepted due to an inaccessible external proxy. |
| src/StreamJsonRpc.Analyzers/AnalyzerReleases.Unshipped.md | Documents the new analyzer/generator diagnostic StreamJsonRpc0040. |
| docfx/docs/nativeAOT.md | Documents the new requirement for proxy accessibility via [assembly: ExportRpcContractProxies] for cross-assembly interceptor generation. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
With the reflection-based fallback, ExportRpcContractProxies is no longer required. It is now presented as an optional optimization to avoid reflection overhead when constructing proxies from separate assemblies.
Improve the interceptor reflection fallback exception text with NativeAOT documentation guidance, remove unused InvocationLocation from attach analysis state, and clarify docs that inaccessible external proxies use reflection fallback (with optional export for faster direct construction). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When interceptors are enabled for RPC contracts, proxy types must be accessible from the calling assembly. Issue #1411 identified that the documentation was unclear about this requirement, and the interceptor source generator was emitting code that would not compile for inaccessible proxies.
Solution
This PR addresses the issue with two changes:
Documentation Update - Updated
docfx/docs/nativeAOT.mdto explicitly call out that when interceptors are enabled, external assemblies that declare RPC contracts may export their proxy types via[assembly: ExportRpcContractProxies]to make them more performant.Reflection-Based Fallback - Updated the interceptor source generator to handle inaccessible proxy types gracefully:
ProxyBase.TryCreateProxyfor reflection-based activation.Design Notes
The generator now:
Attachcall at code generation timeProxyBase.TryCreateProxyto activate the proxy via reflection, with proper disposal of the temporaryJsonRpcinstanceThis design maintains NativeAOT compatibility while supporting cross-assembly RPC contract scenarios without requiring all proxy classes to be public.
Testing
Added/updated regression tests verifying: