Repository navigation
Prototype private runtime references with System.Reflection.Metadata (#560) - #568
Draft
jogibear9988 wants to merge 1 commit into
Draft
jogibear9988 wants to merge 1 commit into
jogibear9988 wants to merge 1 commit into
Conversation
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.
Experimental follow-up to #567 / investigation for #560
This draft records a working private-access prototype based on IgnoresAccessChecksToGenerator, replacing its Cecil backend with
System.Reflection.MetadataandSystem.Reflection.PortableExecutable. It is an independent PR based on master734314ed; it does not modify #567 or FEC's production build/source. It does not close #560.The local fork/backend experiment lives under
BuildScripts/IgnoresAccessChecksToGenerator. It retains upstream MIT licensing and source/targets snapshots at revision882b30bf82fbb72f3bee8878ad9fd31f5c93c875. The new generator has no Cecil or NuGet package dependency. It is not a complete drop-in replacement for the upstream package.Findings and implementation
RuntimeILGenerator. A publicizer cannot expose a type absent from its input.net10.0probe, stock package 0.8.0 tried to rewrite the installed .NET 10 implementation and Cecil rejected its non-IL-only image withWriting mixed-mode assemblies is not supported. No .NET Core DLL was added to a .NET Framework project; that error describes the writer's binary-format limitation.IgnoresAccessChecksToauthorizes the compiled consumer's access.PEReader, retain assembly identity and compiler-relevant metadata, and useMetadataBuilder/ManagedPEBuilderto produce a new IL-only reference markedReferenceAssemblyAttribute. Method bodies, native sections, field RVA data and resources are omitted. Verification checks identity, definition tokens/ranges/signatures, visibility and absence of executable method bodies.System.Runtimedefinitions. The prototype therefore compiles against one consistent set of managed implementation references from the selected runtime, replacing CoreLib with the generated reference. Native DLLs are filtered out withHasMetadata. This is runtime-version/OS-specific, not a portable targeting pack; compiler validation against one version does not guarantee compatibility with other consumer runtimes. Windows implementation references also carry Windows platform annotations.PublicizeInternalstask generates the facade and access attribute and supplies the matching compiler references. Generated files stay underobj; the generated CoreLib is not copied into application output or used as the executing CoreLib.Results
Windows ARM64, SDK 10.0.301; executing runtimes are pinned with roll-forward disabled and checked against the selected input path.
IncreaseCapacity, emitted method returns 42GC.StartNoGCRegionStatus25/25 replay checks passed, including the expected-negative cases; these are replay steps, not 25 independent unit tests. Across four FEC configurations, the smoke tests perform 400 repeated expression compilations plus nested captures and eight runtime-contract test cases. A throwaway FEC source snapshot changes only the local-allocation helper to direct typed field access; the production source is untouched. Both installed CoreLib SHA-256 hashes are unchanged before/after and the facade does not appear in consumer output.
The negative cases establish that disabled private exposure fails C# compilation, missing access permission fails at runtime with
TypeAccessException, a nonexistent field fails withCS1061, and a wrong field type fails withCS0029. An exploratoryArray.ArrayAssignTypereference compiled on .NET 10 but failed on .NET 8 because that nested type is absent there; the retained cross-version test uses the private GC enum. This illustrates the versioning concern directly.Reproduce from
BuildScripts/IgnoresAccessChecksToGeneratorwithpython replay.py. See the report and instructions and recorded commands, exit codes and input hashes. Generated binaries/logs are ignored and regenerated locally.Performance and limitations
No performance or allocation benefit has been measured. Direct typed helpers might reduce reflection/generated-method setup at initialization or delegate dispatch during compilation; replacing an already efficient UnsafeAccessor field access is not an established improvement. Specialized/batched emission would be another experiment. Emitted application code would need to change to establish an application-runtime benefit.
The prototype requires .NET 10 MSBuild and supports CoreLib only. General package support, upstream exclusion/legacy options, older hosts, packaging and incremental-generation caching are not implemented. There is no x64, Linux, Framework 4.7.2, preview-runtime or complete FEC regression-suite claim. The metadata verifier is focused, not certification of a general metadata rewriter.
Merge recommendation
Do not merge this follow-up into master in its current form; keep it as an experimental draft. It proves feasibility, but adds runtime-specific reference machinery without demonstrated performance benefit or sufficient portability/metadata validation.
Before considering production integration: measure cold initialization, warm compilation, allocations, generated-delegate runtime and build cost against existing helpers; narrow exposure/reference handling; decide supported runtime-version behavior; and add broader architecture/OS and regression coverage. Review the smaller runtime-contract tests in #567 independently. This draft supplies evidence for the #560 design discussion, rather than replacing those tests or claiming the issue is solved.