Skip to main content

MEP-68 research bundle

This bundle is the informative companion to MEP-68. It documents the design space the bridge sits in: prior art, the choices considered and rejected, the trade-offs accepted, and the open risks. The bundle is meant to be read alongside the spec, not in place of it.

Notes​

NoteSubject
01. Language surfaceThe import dotnet "..." import shape, the mochi.toml [dotnet-dependencies] + [dotnet] tables, the CLI surface (mochi pkg add dotnet, mochi pkg publish --to=nuget.org), and the per-import alias semantics.
02. Design philosophyWhy a bidirectional bridge, why assembly metadata over C# source parsing, why a C# shim with [UnmanagedCallersOnly] over direct P/Invoke, why CLR hosting over NativeAOT as default, why NuGet trusted publishing is the only publish path, why the type-mapping table is closed not open.
03. Prior-art bridgespythonnet, IKVM.NET, CsWin32, ClangSharp, uniffi, GraalVM polyglot, JNI-style manual bridging, SwiftUI + C headers, diplomat. What each gets right, what each requires the user to write, and what MEP-68 borrows or diverges from.
04. Assembly metadata ingestThe ECMA-335 metadata schema, System.Reflection.Metadata.MetadataReader, the mochi-dotnet-meta CLI tool design, the JSON output schema, the Go-side parser shape, and the per-package ingest fixtures.
05. Type mapping tableThe complete closed CLR-to-Mochi type translation table, the refusal cases, the generic monomorphisation rule, the nullable and Task<T> handling, and the SkipReport format.
06. NuGet publish flowThe nuget.org upload protocol, the .nupkg / .nuspec shape, the per-package metadata requirements, the NuGet v3 API, the TargetDotNetLibrary emit path, and the mochi pkg publish end-to-end flow.
07. NuGet trusted publishingThe NuGet trusted publishing OIDC flow (GA March 2024), the GitHub Actions id-token: write permission, the nuget.org publisher configuration, the verification path at install time, and the comparison to PyPI PEP 740 / Cargo RFC #3724.
08. Async bridgeThe Task<T> synchronous dispatch via .GetAwaiter().GetResult(), CLR thread pool semantics, the deadlock prevention ConfigureAwait(false) pattern, the async-mode = "task-parallel" opt-in, and cancellation semantics.
09. ABI stability[UnmanagedCallersOnly] guarantees, the CLR hosting function-pointer load path, the MochiMarshal type conventions, string and list round-trip encoding, opaque handle strategy for interface types, and the NativeAOT vs CLR hosting ABI difference.
10. Generics and reificationHow .NET reified generics (List<int> vs List<string> as distinct CLR types) differ from Java's type-erased generics and Rust's monomorphised generics; the [dotnet.monomorphise] explicit instantiation model; and the combinatorial explosion risk.
11. NativeAOT and trimmingThe NativeAOT compile path (PublishAot=true), the IL trimmer and AOT-compatibility metadata, the IsAotCompatible NuGet property, the packages in the 20-package corpus that pass and fail AOT trimming (April 2026 analysis), and the CLR startup cost trade-off.
12. Risks and alternativesThe risk register (CLR hosting versioning, TFM mismatch, shim compile time, startup overhead, NuGet offline restore, NativeAOT compat, Windows-only packages, trusted publishing config, generic explosion, GetAwaiter deadlock, package signing, version conflicts) and the rejected alternatives (C# source parsing, XML documentation, NativeAOT default, direct P/Invoke, COM interop, GraalVM, IKVM, dotnet-embed, long-lived API keys, WIT, auto-monomorphise, TFM verbatim mirror).

Cross-references​

  • MEP-68 spec — the normative document.
  • MEP-53 — the Rust transpiler this bridge builds the emit pipeline analogue on.
  • MEP-57 — the source-level package system whose manifest and lockfile the bridge extends.
  • MEP-73 — the Rust package bridge, whose architectural shape MEP-68 follows.
  • Implementation tracking — the per-phase delivery status.