A small Kotlin challenge from a real permissions bug: each user has a set of roles. A teammate adds a role to one user, and a completely different user ends up with that role too. What happened? Watch the clip and share what you think below.

Love these real-world technical challenges. Great way to keep the community engaged!

`𝗰𝗼𝗽𝘆()` 𝗺𝗮𝗸𝗲𝘀 𝗮 𝘀𝗵𝗮𝗹𝗹𝗼𝘄 𝗰𝗼𝗽𝘆. 𝗕𝗼𝘁𝗵 𝗼𝗯𝗷𝗲𝗰𝘁𝘀 𝘀𝗵𝗮𝗿𝗲 𝘁𝗵𝗲 𝘀𝗮𝗺𝗲 𝗺𝘂𝘁𝗮𝗯𝗹𝗲 𝗹𝗶𝘀𝘁. 𝗖𝗼𝗽𝘆 𝘁𝗵𝗲 𝗹𝗶𝘀𝘁 (`𝘁𝗼𝗠𝘂𝘁𝗮𝗯𝗹𝗲𝗟𝗶𝘀𝘁()`) 𝗼𝗿 𝘂𝘀𝗲 𝗶𝗺𝗺𝘂𝘁𝗮𝗯𝗹𝗲 `𝗟𝗶𝘀𝘁` 𝗶𝗻𝘀𝘁𝗲𝗮𝗱. Here's our version: data class User( val name: String, val roles: MutableList<String> ) val alex = User( "Alex", mutableListOf("viewer") ) val sam = alex.copy( name = "Sam", roles = alex.roles.toMutableList() ) sam.roles.add("editor")

Sounds like a classic shared reference bug, probably sharing a default mutable set across user instances. Those are always a massive headache to track down!

Copy() function will perform a shallow copy. So it’ll end up updating both to the new roles. As suggested by others either create a new mutable list or use an immutable collection like List.

well "copy", what it did is not copying the list but the reference only , thats y when we try to add a role to sam , both of them gets the role. i think we should make the role list immutable to negate future modificaation

The bug occurs because Kotlin's copy() function performs a shallow copy, meaning mutable reference properties like MutableList are shared between the original and copied objects. Any modification to the shared mutable object through one instance is reflected in the other. To avoid this, explicitly create a new mutable collection (for example, using toMutableList()) when copying data classes that contain mutable properties.

Kotlin's default copy() function only performs a shallow copy of the data class properties. Since roles is a MutableList, both alex and sam end up holding a reference to the exact same list instance in memory. Mutating sam.roles directly mutates alex.roles as well. This is a prime example of why using immutable collections (List instead of MutableList) inside data classes is a massive lifesaver for preventing accidental side effects!

The root cause isn't copy()—it's aliasing of mutable references. Since roles points to the same MutableList, both instances observe the same mutations. Recommended solutions: Kotlin data class User( val name: String, val roles: List<String> ) val sam = alex.copy( name = "Sam", roles = alex.roles + "editor" ) This keeps the model immutable, thread-safe, and easier to reason about.

The issue is that copy() performs a shallow copy. The roles property is a MutableList, so both alex and sam reference the same list. Adding "editor" to sam.roles also updates alex.roles. Using immutable collections (List) or copying the list with toMutableList() avoids this shared-state bug.

Nice catch! This is a shallow copy issue. copy() shares the same MutableList, so changes affect both objects. The fix is to deep-copy the list using roles = alex.roles.toMutableList() or use immutable List instead.

See more comments

To view or add a comment, sign in

Explore content categories