Package-level declarations

Types

Link copied to clipboard
internal class AccessWideningVisitor(mv: MethodVisitor, val declaredHere: (String, String, String) -> Boolean) : MethodVisitor
Link copied to clipboard
private class BodyStripper(next: ClassVisitor) : ClassVisitor

ASM visitor that replaces every CONCRETE method's code with a 2-byte aconst_null; athrow stub, keeping the method's signature, exceptions and declaration annotations (code/type annotations go with the body). Wired as tiny-remapper's extraPreApplyVisitor so the whole pipeline (remap + write) processes stubs, not full bodies — the compiler reads signatures/constants/annotations, never bodies, for a classpath class. The resulting symbol jar is compile-only (never loaded/verified/run), so an under-sized maxLocals or a throwing constructor is harmless. Abstract/native methods (no Code attribute) pass through untouched.

Link copied to clipboard
internal class CpEntry(val file: File, val typeSetKey: String?, val contentKey: String?)

One classpath entry with the two digests a single central-directory walk yields.

Link copied to clipboard
private class FlatRemapper(classMap: Map<String, String>, methodMap: Map<String, String>, fieldMap: Map<String, String>, val ignoreFieldDesc: Boolean, val symbols: SymbolIndex)

Immutable mapping tables + a lazily-built immutable MC hierarchy; each eval is a plain ASM ClassRemapper. Member lookups climb owner→ancestors (super first, then interfaces) and memoize. All state is immutable or a ConcurrentHashMap memo, so many lanes may remap concurrently.

Link copied to clipboard
private class Graft(val bytes: ByteArray, val shadowed: Set<String>)

One class's grafted bytes, plus the keys an added member took off a member already on the class.

Link copied to clipboard
private class GuardMethodVisitor(mv: MethodVisitor, mn: String, val killIdField: String, val evalId: Int) : MethodVisitor

Inlines the guard at method entry (except <init>/<clinit>), loop back-edges and real catch entries — rationale in the class body below.

Link copied to clipboard
private object HybridTsrg2

Serializer for the hybrid TSRG2 RemapCacheBuilder.assembleForge writes. Its own object because it is pure text emission over a finished mapping tree — no downloads, no jars, no cache layout.

Link copied to clipboard
internal class KmRemap(val r: Remapper)

Rewrites a @Metadata proto so it agrees with the bytecode r just rewrote. One walk serves both directions: the direction is r's business and none of this walk's.

Link copied to clipboard

Masking-owned MaskingBridge: forwards REPL calls to ReplHost and remap-cache calls to RemapCacheBuilder, both object singletons on this same loader.

Link copied to clipboard
internal class McpFir2IrScriptConfigurator(session: FirSession) : Fir2IrScriptConfiguratorExtension

Nothing to add on the IR side; the extension point must exist for scripts to convert at all.

Link copied to clipboard
internal class McpScriptConfigurator(session: FirSession) : FirScriptConfiguratorExtension

Configures an execute_code snippet as a FirScript. KotlinLightParser picks script mode purely on the source file's extension not being .kt, so naming the in-memory source SCRIPT_EXT is the whole switch — and it is what lets a snippet mix top-level statements with object / class declarations, neither of which survives being wrapped in a function.

Link copied to clipboard
internal class McpScriptRegistrar : FirExtensionRegistrar
Link copied to clipboard
internal class MetaCapture : AnnotationVisitor

Captures a @kotlin.Metadata annotation during an ASM read, and re-emits it — verbatim, or as a rewritten replacement. Stores ONLY the fields the original actually carried, which is what makes a verbatim re-emit add nothing: a lambda class (k=3) carries no d1, and an empty one reads back as a deserializable proto, NPEing readFunctionDataFrom deep inside the inliner. Primitive arrays (mv/bv) arrive as one value; string arrays (d1/d2) arrive element-by-element via a nested visitArray visitor.

Link copied to clipboard
internal class MixinPlan(val claimed: Set<String>, val work: Map<File, List<Pair<String, String?>>>, val present: Set<String>, val rename: OverlayRename?, val renameFor: RenameFor)

What the mixin overlay will contain, resolved before any jar is written so this one builds alongside the shards.

Link copied to clipboard
internal class OverlayBuild(val jarEntries: Map<File, List<String>>, val renameFor: RenameFor, val pinned: LanguageVersion?, val failed: MutableSet<File>)

What a shard build reads: the entries to widen, whether each jar's bytes get renamed, the metadata level for the rebuilt kotlin_module, and where to record a jar that would not open.

Link copied to clipboard
internal class OverlayParts(val pinned: LanguageVersion?)

Rebuilds the package -> file facade map that a jar's META-INF kotlin_module carries, from the @Metadata the overlay pass already parses.

Link copied to clipboard
internal class OverlayRename(val table: Map<String, String>) : Remapper

Renames CLASSES only — mapMethodName / mapFieldName stay at ASM's identity, which is also how KmRemap knows to leave member names alone. Correct here regardless: ScriptRemap's flat remapper maps the classes back on the way out and its tables key on mojmap names, so an already-intermediary member name passes it untouched.

Link copied to clipboard
private class OverlayWorker(val jos: JarOutputStream, val renameFor: RenameFor, val parts: OverlayParts)

One shard's writer: the inflate buffer it reuses across that shard's jars (a fresh 1MB each would be pure allocation churn), and the count of classes it contributed. Nothing is synchronized — a shard owns its output file outright, so the lock the single-overlay version needed is gone.

Link copied to clipboard
internal object PlainEngine

Compiles a snippet by driving the compiler directly, holding the expensive state ourselves.

Link copied to clipboard

Masking-loader side of the first-launch remap-bundle build. Lives in repl.impl so the masking loader owns it (child-first) and it can link mapping-io + tiny-remapper, which sit ONLY on the masking urls (off the game/module path). The game-loader side (RemapCache) does version detection + network download + JSON parsing (MC's bundled Gson lives there); this side does the two operations that need those libraries, reached from ReplBridge through the shared MaskingBridge adapter.

Link copied to clipboard
internal typealias RenameFor = (File) -> OverlayRename?

Whether a given jar's bytes get renamed at all, as opposed to the rename TABLE. Per jar because mc-symbols is already mojmap: the table would find nothing to map in it, but only after parsing every method body and rebuilding every constant pool.

Link copied to clipboard
object ReplHost

The REPL host. Loaded BY the masking loader (child-first) and reached from ReplBridge on the game loader through the MaskingBridgeImpl adapter (the one reflective hop) — so it can link the Kotlin compiler that lives on the masking loader's urls even though those jars are NOT on the game runtime classpath. After the hop, everything here is ordinary Kotlin.

Link copied to clipboard
internal sealed class Shard(val name: String, val members: List<CpEntry>)

One jar the overlay writes.

Link copied to clipboard
internal class ShardPlan(val out: Map<Shard, File>, val stale: List<Shard>)

Where each shard's jar is, and which of them have to be written.

Link copied to clipboard
internal class StampRow(val contentKey: String, val shard: String, val source: String)

One mods.stamp line. Named rather than a Triple: three same-typed strings in positional form is an argument order nobody can get wrong at a glance, and getting it wrong here reads back as a valid file.

Link copied to clipboard
private class SymbolIndex(classpath: List<File>)

Byte source over the mc-symbols jars/dirs: internal class name -> class bytes, read on demand. Jars are opened once and kept open (read-only symbols, process lifetime). The whole class file is inflated per read, but only its header (super+interfaces) is parsed, and only for the classes an eval actually touches (memoized in FlatRemapper.superCache).

Link copied to clipboard
internal class YieldTypeExtension(val types: Map<Pair<Int, Int>, String>) : IrGenerationExtension

Writes types into each yield call's typeName argument.

Properties

Link copied to clipboard

Verdict per module name — what to emit for it, with the key itself meaning "already aligned". The answer is a property of the jar, not of the class, so the member scan below runs once per module rather than on each of the thousands of classes that share one.

Link copied to clipboard
private val APPROXIMATION: TypeApproximatorConfiguration.PublicDeclaration.SaveAnonymousTypes

What the frontend itself applies when an inferred type has to become a declared one.

Link copied to clipboard
private const val BLAME: String

Prepended so it lands above the compiler's own Please report this problem https://kotl.in/issue, which is wrong here: this REPL installs its own IR plugins and rewrites snippet bytecode, so a backend fault is the mod's until one of those is ruled out, and upstream cannot act on the report either way.

Link copied to clipboard
internal const val DECLARATIONS_ONLY: Int

Read everything a signature needs and nothing a body does — the flags for every pass here that only edits declarations.

Link copied to clipboard

So snippets say bare Patches / Probe.

Link copied to clipboard
private const val DEFAULT_PACKAGE_LIMIT: Int = 16

How many default-package classes make a jar structurally "the obfuscated vanilla MC jar". One is harmless (a stray top-level class); thousands break the K2 index.

Link copied to clipboard
internal const val ENV_SHARD: String
Link copied to clipboard
internal const val ENV_STAMP: String
Link copied to clipboard
private val flatLock: ReentrantLock
Link copied to clipboard

The mapping tables + hierarchy index built ONCE, reused across every eval — a pure in-memory ASM ClassRemapper in place of tiny-remapper's per-eval readClassPath (~1.5s). Built lazily on first remap (needs mappingsPath + classpath in hand); immutable/concurrent afterward.

Link copied to clipboard
private const val KIND_FILE_FACADE: Int = 2

@Metadata.k for a file facade and for one part of a multi-file one.

Link copied to clipboard
private const val KIND_MULTIFILE_PART: Int = 5
Link copied to clipboard
private const val MAX_DIAGNOSTICS: Int = 8

Diagnostics rendered in full; the rest are left to the count line. Each one costs a source line and a caret line of its own, so it is the count that bounds this report.

Link copied to clipboard
private const val MAX_INLINE: Int = 2000

How much of an oversized payload stays in the message. The rest is in the file.

Link copied to clipboard
private val MC_BYTES: ByteArray

Minecraft's package root, as the bytes mentionsMinecraft scans for. Namespace-independent, unlike the spelling below it: fabric's class_2338, spigot's BlockPosition and mojmap's BlockPos all live here.

Link copied to clipboard

@Metadata's accessors keyed by JvmName (k/mv/bv/d1/d2/xs/pn/xi). Read off the annotation type so the field list — and every field's declared default — is never maintained by hand here.

Link copied to clipboard
internal const val MODS_STAMP: String
Link copied to clipboard
private val OPENABLE: EnumSet<Visibility?>?

What a widen opens: internal is PlainEngine's friend-all job, public needs nothing.

Link copied to clipboard
internal val RESULT_PROPERTY: Name

Holds the snippet's last expression. Read back off the instantiated script object.

Link copied to clipboard
private const val SCOPE: String

sequence { yield(x) } resolves to the stdlib's yield, which carries no typeName to fill.

Link copied to clipboard
internal const val SCRIPT_EXT: String

Any extension but .kt puts KotlinLightParser into script mode; this one is ours so McpScriptConfigurator.accepts can match.

Link copied to clipboard
private const val SCRIPT_SCOPE: String
Link copied to clipboard
private const val TYPE_NAME: String
Link copied to clipboard
private const val YIELD: String

Functions

Link copied to clipboard
private fun alignModuleName(current: String?, fns: List<KmFunction>, props: List<KmProperty>, set: (String) -> Unit): Boolean

Realign moduleName with the $suffix this declaration's own internal members actually carry.

Link copied to clipboard
internal fun alongsideMixinOverlay(plan: MixinPlan?, out: File, main: () -> Unit): Boolean

Run main with the mixin overlay building next to it, and report whether that overlay published.

Link copied to clipboard
internal fun assembleCompileClasspath(cpFiles: List<File>, baseLoader: ClassLoader, pinned: LanguageVersion?): List<File>

Turn the enumerated game classpath into the one the K2 frontend is handed: drop the jars that poison its index, fold duplicate libraries, and prepend an access-widened overlay (widenClasspath).

Link copied to clipboard
private fun buildFlatRemapper(mappingsPath: String, classpath: List<File>, fromNs: String, toNs: String): FlatRemapper

Consume the SAME IMappingProvider tiny-remapper would (identical namespaces/descriptors), dumping its class/method/field mappings into flat tables keyed by "owner name desc". The MC hierarchy is read lazily from classpath (mc-symbols) inside FlatRemapper; the tables are immutable afterward.

Link copied to clipboard
private fun buildShard(shard: Shard, out: File, ctx: OverlayBuild): Int

Write one shard: its members' widened classes, plus the kotlin_module rebuilt from what they carried.

Link copied to clipboard
internal fun buildShards(stale: List<Shard>, out: Map<Shard, File>, ctx: OverlayBuild): Int

Build every stale shard in parallel; returns the classes written across all of them.

Link copied to clipboard
internal fun classRename(): OverlayRename?

Build the rename, or null when this runtime renames no classes.

Link copied to clipboard

Build the stock scripting classloader over our (instrumented, maybe-remapped) bytes, so it keeps the SAME class + resource semantics as the stock scripting loader — only the bytes differ. Crucially the stock loader serves each class's bytes AS A RESOURCE (getResourceAsStream), which kotlin-reflect reads to parse @Metadata; a findClass-only loader silently degrades reflection over script-defined types (::class.members, data-class copy()). The try/catch still falls back to a minimal loader that at least serves class bytes as resources if a LinkageError ever surfaces (e.g. the impl type moved in a future kotlin version — the link is resolved lazily at this call site, so NoClassDefFoundError is catchable here).

Link copied to clipboard
private fun cutDump(e: CompilationException, evalId: Int, sourceName: String, code: String): Throwable

The CompilationException half: its content is the very substring its message getter embedded.

Link copied to clipboard
private fun dedupByTypeSet(cleanCp: List<File>, kotlinFiles: List<File>): List<CpEntry>

Merge the enumerated compile cp with the masking loader's Kotlin jars, deduplicating by the SET OF TYPES each jar defines: the sorted set of its zip .class entry names, hashed. Read from the central directory — no decompression, never the raw bytes, never the filename. That set is exactly what decides whether two jars collide on the K2 index (duplicate classes), so it's the right identity: same type-set ⇒ same library ⇒ keep one. It also folds two builds of one artifact that differ only in packaging (zip timestamps/order), which a byte hash would miss. A null key (no classes, or unreadable) is always kept — it collides with nothing. The two stdlib copies (mcp-kotlin/ staging + our jar-in-jar extraction) share a type-set and collapse to one.

Link copied to clipboard
internal fun dedupeEntries(targets: Map<File, List<String>>): Map<File, List<String>>

Keep the first jar to claim each entry name and drop the rest, in the map's (classpath) order.

Link copied to clipboard
private fun dropIndexPoison(cpFiles: List<File>): List<File>

The enumerated classpath can include the vanilla obfuscated MC jar, with thousands of classes in the default (unnamed) package. Such a jar poisons the Kotlin scripting host's classpath index: with it on the compile cp the K2 frontend silently fails to resolve every other jar's packages (only net.minecraft survives, via mc-symbols). One default-package class is harmless; thousands break it. It's useless here anyway — we compile mojmap names against mc-symbols.jar. Identified by content (unnamed-package class count), never by filename, so it's launcher-independent; a mojmap-named MC jar is left untouched.

Link copied to clipboard
internal fun envRows(env: List<CpEntry>, pinned: LanguageVersion?): List<String>

The environment shard's inputs: pinned first, then one sorted name|contentKey line per member.

Link copied to clipboard
internal fun Metadata.fieldOr(name: String, fallback: Any?): Any?

name's value on this written Metadata, or fallback where the write left the declared default — which means it does not model that field. Arrays come back as List, ready for an ASM visitArray.

Link copied to clipboard
private fun flatRemapperFor(mappingsPath: String, classpath: List<File>, fromNs: String, toNs: String): FlatRemapper
Link copied to clipboard
private fun instrument(cof: Map<String, ByteArray>, killIdField: String, evalId: Int): Map<String, ByteArray>

Instrument every real .class in the compiled script — top-level AND lambda/iterator synthetics (the iterator{} body lives in a synthetic $...invokeSuspend class, so instrumenting only the top-level class would miss the cross-tick loop). Metadata (.kotlin_module) rides along untouched. A failure on any one class fails the whole eval.

Link copied to clipboard
private fun instrumentClass(bytes: ByteArray, killIdField: String, evalId: Int): ByteArray

ASM core pass inlining if(killId == evalId) throw at every method entry EXCEPT <init>/<clinit>, plus every loop back-edge and real catch entry. The inlined branch (skip label) needs a StackMapTable frame, so COMPUTE_FRAMES (can't accept(cr,0)+COMPUTE_MAXS like a stack-neutral call would).

Link copied to clipboard
private fun isClassFile(path: String, bytes: ByteArray): Boolean

A real class entry: a .class name whose bytes actually carry the JVM magic.

Link copied to clipboard
private fun FirProperty.isFromDestructuring(): Boolean

A destructuring is built as a container variable plus entries, accessors made to match, and it rejects visibility modifiers outright — so the whole shape is left as the builder made it.

Link copied to clipboard
private fun String.isReference(): Boolean

Reference, i.e. object or array — Type.ARRAY and Type.OBJECT are the two sorts above every primitive.

Link copied to clipboard
private fun logClasspath(cp: List<File>)
Link copied to clipboard
internal fun mentionsMinecraft(buf: ByteArray, len: Int): Boolean

Whether buf's first len bytes mention Minecraft at all — a raw scan, no parse, to keep every MC-free class off the remap path. Constant-pool UTF8 leaves ASCII verbatim, so the prefix appears literally wherever a type reference does; a false positive (the text sitting in a string constant, or a reference to an MC class this table does not rename) only costs a rename pass that changes nothing.

Link copied to clipboard
internal fun mixinOverlayPlan(jarEntries: Map<File, List<String>>, rename: OverlayRename?, renameFor: RenameFor): MixinPlan?

Resolve what the mixin overlay would contain, or null when there is nothing to build.

Link copied to clipboard
private fun oneMemberToK2(a: String, b: String): Boolean

Whether K2 folds two same-name same-parameter members into one, which is the only reason closing the class-side member is enough on its own. Two reference types read as a covariant override and fold; a primitive or void against anything is two Kotlin types and does not. A primitive against its own box folds too — Kotlin has one type for the pair — but nothing reaches here that way: Mixin puts the boxed member on the INTERFACE as a default, and a default is not copied onto the class, so no key collides.

Link copied to clipboard
private fun openMembers(fns: List<KmFunction>, props: List<KmProperty>, tas: List<KmTypeAlias>, open: (Visibility) -> Visibility)

Run open over every visibility a Kotlin package or class body carries.

Link copied to clipboard
private fun openPackage(p: KmPackage, owner: String, open: (Visibility) -> Visibility, rename: OverlayRename?): Boolean

Open + realign + rename one file facade or multi-file part; returns whether alignModuleName changed it. The two metadata kinds carry the same KmPackage body and differ only in which case matched. owner is the facade class, which a KmPackage does not carry and KmRemap needs to look its members up by.

Link copied to clipboard
private fun ourLoaderJars(baseLoader: ClassLoader): List<File>

The masking loader's own urls: our extracted Kotlin stack, and in production the mod jar repl.impl is loaded from.

Link copied to clipboard
internal fun publishStamps(dir: File, shards: List<Shard>, out: Map<Shard, File>, failed: Set<File>, wantEnv: List<String>): Set<String>

Record what this run produced; returns the file names worth keeping.

Link copied to clipboard
internal fun readEnvRows(f: File): List<String>

env.stamp's own pair, deliberately not the mods.stamp one: the two disagree on line shape, on what column one holds, on whole-file against per-line comparison, and on what a mismatch costs. Either parser would read the other's file without complaint and mean something else.

Link copied to clipboard
internal fun readModsStamp(f: File): Map<String, String>

contentKey -> shard file name for the user shards.

Link copied to clipboard
internal fun remapModule(outputFiles: Map<String, ByteArray>, mappingsPath: String, classpath: List<File>, fromNs: String, toNs: String): Map<String, ByteArray>

Remap the script's compiled classes fromNs->toNs.

Link copied to clipboard
internal fun renderFailure(reports: List<ScriptDiagnostic>, code: String): String

Render diagnostics in the standard compiler format (source:line:col: severity: message, the offending source line, then a caret under the column) — that prefix is what editors make clickable. Locations are relative to the source handed to the compiler, which is the original snippet, so line N maps straight back to what was written.

Link copied to clipboard
private fun renderTail(shown: List<ScriptDiagnostic>, renderedCount: Int): String

What did not fit, then the totals — counted over everything the compiler reported, not over what was shown.

Link copied to clipboard
private fun replacing(t: Throwable, text: String): RuntimeException

Same stack and same cause, different text — the only part of a throwable that cannot be edited in place.

Link copied to clipboard
internal fun resolveShards(dir: File, shards: List<Shard>, wantEnv: List<String>): ShardPlan

Match shards against what dir already holds.

Link copied to clipboard
private fun revealAccess(access: Int, ambiguous: Boolean): Int

widenAccess, plus ACC_SYNTHETIC made to mean exactly one thing on a grafted member: source cannot name it — which is what K2 reads it as when it drops the member from a Java use-site scope. Mixin sets the flag on the @Accessor/@Invoker bodies it generates and not on what it merges from mixin source, and neither tracks whether the name survives the rename, so the graft decides it here instead of inheriting it. An ambiguous member is still reachable through the interface Mixin grafts alongside it; the base member it collided with has no such second name, which is why that one keeps it.

Link copied to clipboard
private fun rewriteMetadata(cap: MetaCapture, owner: String, rename: OverlayRename?): Map<String, Any?>?

Open private/protected/private-to-this → public in a Kotlin class's @Metadata proto, realign its moduleName (see alignModuleName), and — when rename is set — rewrite its runtime classifiers to mojmap so the proto agrees with the bytecode ClassRemapper just rewrote. Returns the fields to re-emit if anything changed, null otherwise. Uses kotlin-metadata-jvm's STRICT read: the lenient read forbids write-back, and strict read/write throw for metadata older than 1.4 or newer than this lib + 1 minor — caught by the caller, leaving that class closed.

Link copied to clipboard
private fun robustClassWriter(cr: ClassReader): ClassWriter

ASM ClassWriter with COMPUTE_FRAMES whose getCommonSuperClass falls back to Object instead of throwing when a frame merge needs a script-defined class not yet loadable during instrumentation. Shared by both bytecode passes below (instrumentClass and widenAccessClass).

Link copied to clipboard
private fun shardName(e: CpEntry): String

A user shard's file name: the loader's id where there is one, so a version bump overwrites the shard instead of orphaning it, and only an uninstall leaves anything for the sweep. Where no id exists (a plugin's bundled library) the file name stands in; it need not be stable, since staleness is looked up by contentKey, not by name.

Link copied to clipboard
internal fun shardsOf(entries: List<CpEntry>): List<Shard>

Cut entries into the environment shard plus one shard per user-space jar.

Link copied to clipboard
private fun spill(payload: String, evalId: Int, where: String, code: String, kind: String): String?

Write payload under <cacheDir>/errors/; canonical path, or null if that failed.

Link copied to clipboard
internal fun spilling(t: Throwable, evalId: Int, sourceName: String, code: String): Throwable

Replace a compile-stage throwable whose message carries an IR dump; anything else is returned untouched.

Link copied to clipboard
private fun spillMarker(payload: String, evalId: Int, where: String, code: String, kind: String): String

What the payload is replaced by: its file, or — if nothing could be written — a note saying so. Worded to read the same whether it is substituted into the message or appended after a truncation.

Link copied to clipboard
internal fun sweepStale(dir: File, keep: Set<String>)

Delete whatever this run did not name — a mod that is gone, or a shard whose name moved. Cheap; a file another instance still holds open just survives to the next sweep.

Link copied to clipboard
internal fun tsrgProvider(mappingsPath: Path, fromNs: String, toNs: String): IMappingProvider

tiny-remapper provider over forge's TSRG2 (srg_to_official.tsrg), direction fromNs ->toNs. Its two namespaces are "left" = Mixed-SRG runtime (class names mojmap, members m_/f_) and "right" = named (all mojmap). Both directions are needed and are the SAME walk: remapModule remaps script bytecode named(right)->srg(left), the symbol-jar build derives mojmap from the runtime jar srg(left)->named(right).

Link copied to clipboard
internal fun weaveClasses(input: Map<String, ByteArray>, killIdField: String, evalId: Int, classpath: List<File>): Map<String, ByteArray>

Post-compile bytecode pipeline. classpath is the compile classpath the snippet was built against, used as the remap reference.

Link copied to clipboard
internal fun widenAccess(access: Int): Int

The ACC edit itself, shared with the members the mixin graft appends — those never pass through widenClassFile, since they are added after it. Anything not public -> public (package-private too: a snippet never shares the target's runtime package), no final removal: the REPL needs access, not inheritance.

Erasure is a MODULE-level decision, so the ownership test spans every class this compilation produced — not just the one being visited. One eval yields several classes (the snippet plus a synthetic per lambda / iterator {} body), and a member erased in its declaring class must read the same from every sibling that references it. Scoped per-class the two disagree, and the mismatch is a link-time NoSuchMethodError/NoSuchFieldError naming the snippet's own class.

Link copied to clipboard
private fun widenAccessClass(bytes: ByteArray, declaredHere: (String, String, String) -> Boolean): ByteArray
Link copied to clipboard
internal fun widenClassFile(buf: ByteArray, len: Int, rename: OverlayRename?, parts: OverlayParts? = null): ByteArray

The overlay's bytes for one class, for every producer of it — the shard writer and the mixin graft alike.

Link copied to clipboard
internal fun widenClasspath(entries: List<CpEntry>, pinned: LanguageVersion?): List<File>

Widen compile classpath: every .class needing an access flag change goes into a STORED (uncompressed) shard — one per user-installed jar, one for everything else — and the shards are prepended in classpath order, so the compiler finds widened versions first and untouched classes fall through to the original jars. Names are deduplicated within a shard, never across them: shards win in classpath order, exactly as the jars behind them do.

Link copied to clipboard
private fun widenPass(buf: ByteArray, len: Int, rename: OverlayRename?, parts: OverlayParts?): ByteArray?

Widen a single class file so the REPL can reach non-public members. Two coordinated edits, one pass:

Link copied to clipboard
private fun widenTargets(files: List<File>, renameFor: RenameFor, failed: MutableSet<File>): Map<File, List<String>>

jar -> the entry names the overlay carries for it, in classpath order, NOT deduplicated — see dedupeEntries for why that is the caller's call. Jars contributing nothing are absent. A jar that fails to open contributes nothing, is logged, and lands in failed, which holds back the stamp of whichever shard was carrying it so the next launch retries that one alone.

Link copied to clipboard
internal fun writeEnvRows(f: File, rows: List<String>)
Link copied to clipboard
internal fun writeModsStamp(f: File, rows: List<StampRow>)

Write rows as contentKey|shard|source, published by atomic rename like every other cache file.

Link copied to clipboard
private fun writeModuleFile(jos: JarOutputStream, parts: OverlayParts, shard: String)

Append the rebuilt kotlin_module. Named per shard: the provider unions package parts across modules, so distinct names simply add up, while one shared name would have shards racing for a single path.

Link copied to clipboard
internal fun yieldTypes(fir: List<FirFile>, session: FirSession): Map<Pair<Int, Int>, String>

Source span -> rendered type, for every SCOPE yield call in fir. Read after resolution: the type argument is inferred from the value, so before it there is nothing to render.