E08254: MutexLock cannot appear in a generic type parameter — move the lock to a class or component field
What went wrong
MutexLock (or a parameterised MutexLock of T) was used as a type argument to another generic — for example List of MutexLock, Optional of MutexLock of Integer, or Dict of (K, MutexLock).
EK9's compile-time concurrency safety relies on every lock having a stable, field-rooted home. Locks buried inside collections defeat static lock-identity analysis and indicate a misuse of the lock idiom: the natural pattern is one MutexLock per shared payload, held as a field on a class or component.
Rationale
EK9 needs to know, at compile time, *which* physical lock each acquisition operates on. This makes data-race detection (slice 1) and deadlock detection (slice 2) tractable. A collection of locks breaks this:
- Which lock guards which element?
- Does the iteration order match the lock acquisition order?
- Is the collection itself shared (and so its mutations need a separate lock)?
These questions don't have static answers, and runtime tracking would defeat the goal of compile-time guarantees.
In practice, code that reaches for "a list of locks" almost always has a structural problem — usually it should be "one lock guarding a list of payloads" instead.
How to fix it
- Move the MutexLock to a field on a class or component (the [EXAMPLE] section below: a 'LockableText' class holds the lock as its field, and the List holds LockableText objects)
- If you need many independent locks, make a class per protected payload and have the collection hold instances of that class — each instance holds its own lock and its own payload as fields.
- Use the Consumer / async-pipeline patterns for fan-out, where the pipeline runtime handles synchronisation invisibly.
Common causes
- "I want a cache of independently-lockable values" → use a Dict whose value type is a class holding both the lock and the payload, not a Dict whose value type is the lock itself.
- "I have N similar resources each needing their own lock" → wrap each resource in a class that holds its own MutexLock as a field.
Worked examples
- ek9 -q 158 (How do I protect shared data from concurrent access in EK9?)
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E08254: MutexLock cannot appear in a generic type parameter — move the lock to a class or component field
#!ek9 defines module error.e08254.bad defines function badListOfLocks() locks <- List() of MutexLock of String require locks? badOptionalLock() maybeLock <- Optional() of MutexLock of Integer require maybeLock?
Fixed: Hold each lock in a field of a type, and collect that type
#!ek9 defines module error.e08254.good defines class LockableText text as MutexLock of String: MutexLock("") default operator ? defines function listOfLockables() <- rtn as List of LockableText: [LockableText(), LockableText()]
Questions and answers
These Q&A entries show E08254 and its fix: