The exercise is an interesting one: how to add support for something like `List.of(...)` for Java 8-21 when the method exists only for 9+ and some behavior you seek in only in 16+.
However, is it worthwhile in this case to add new `ScriptBytecodeAdapter` methods to support this for records instead of just writing the bytecode you need based on the compile-time target bytecode version? From: Oscar N <paintninjaproje...@outlook.com> Sent: Monday, January 22, 2024 10:46 AM To: dev@groovy.apache.org Subject: [EXT] Re: Questions regarding implementation approach for GROOVY-11294 External Email: Use caution with links and attachments. Wrapping in Collections.unmodifiableList is an option, although using List.of() when possible should yield better performance as it has stronger immutability guarantees at the JVM level (uses @jdk.internal.vm.annotation.Stable on its internal backing fields). You are right that it doesn't link to internal state - I forgot that it performs defensive copying/makes a new list each time. You could make the argument that it allows mutating the returned Map to change the returned values, although you could also say the same for mutable record components so it's kind of a moot point. I suppose the main benefit is performance-wise again, as the immutable List/Map could be cached. ________________________________ From: Milles, Eric (TR Technology) via dev <dev@groovy.apache.org<mailto:dev@groovy.apache.org>> Sent: 22 January 2024 16:04 To: dev@groovy.apache.org<mailto:dev@groovy.apache.org> <dev@groovy.apache.org<mailto:dev@groovy.apache.org>> Subject: RE: Questions regarding implementation approach for GROOVY-11294 Can you just wrap what is presently returned with a call to Collections.unmodifiableList or Collections.unmodifiableMap? If the return values of toList() or toMap() from a record do not link to any internal state, what is the concern if they are mutable or not? From: Oscar N <paintninjaproje...@outlook.com<mailto:paintninjaproje...@outlook.com>> Sent: Monday, January 22, 2024 8:53 AM To: dev@groovy.apache.org<mailto:dev@groovy.apache.org> Subject: [EXT] Questions regarding implementation approach for GROOVY-11294 External Email: Use caution with links and attachments. Hello all, While working on GROOVY-11294, I was investigating approaches for creating an immutable list from an array and have some questions... Java's List.of() usually doesn't allow nulls but can on 16+ by using Stream.toList(). I've used the VMPlugin system to handle this with appropriate fallbacks depending on what's available for a given Java version. Next I created methods in ScriptBytecodeAdapter and InvokerHelper that call it. First question: Should I add a createImmutableList() method to both ScriptBytecodeAdapter and InvokerHelper, or does it only need to be in one of those? Presumably createList() is in both for compatibility reasons, although I'm unsure how it should work for new methods. Second question: Would it be better to add new typed methods to ArrayGroovyMethods called toImmutableList() and calling that from inside the record's generated toList() method instead? Third question: If going down the ScriptBytecodeAdapter/InvokerHelper route, how deep should support for generating immutable lists be in the compiler? The idea of an ImmutableListExpression or a setImmutable() method on ListExpression or similar for marking lists as immutable at compile-time could be useful in cases such as @Immutable and provide an easy way for AST transformers and type checkers to check and change the mutability of collections... It would also theoretically allow for skipping some runtime overhead in situations where we know all elements are never null. Looking forward to hearing your thoughts on this. -Oscar