[
https://issues.apache.org/jira/browse/GROOVY-12037?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Paul King resolved GROOVY-12037.
--------------------------------
Fix Version/s: 6.0.0-alpha-2
Resolution: Fixed
> GDK: add toMutableList/toImmutableList/toImmutableSet variants and deprecate
> toList(Stream) shim
> ------------------------------------------------------------------------------------------------
>
> Key: GROOVY-12037
> URL: https://issues.apache.org/jira/browse/GROOVY-12037
> Project: Groovy
> Issue Type: New Feature
> Reporter: Paul King
> Assignee: Paul King
> Priority: Major
> Fix For: 6.0.0-alpha-2
>
>
> h2. Problem
> The GDK exposes only mutable conversions ({{toList}}/{{toSet}}) from
> {{Stream}}, {{BaseStream}}, {{Iterator}}, {{Iterable}} and arrays. Users
> wanting immutable results have to chain JDK helpers ({{List.copyOf}},
> {{Collectors.toUnmodifiableSet}}) — or, since JDK 16, silently get one from
> {{stream.toList()}}: that call now resolves to the native {{Stream#toList()}}
> (unmodifiable) rather than the GDK extension (mutable {{ArrayList}}), with no
> compiler signal. Code that mutated the result and worked pre-JDK 16 can
> now throw {{UnsupportedOperationException}} after an unrelated JDK upgrade.
> h2. Changes
> * *Add {{toImmutableList}} / {{toImmutableSet}}* across every receiver that
> already has {{toList}}/{{toSet}}: {{BaseStream}}, {{Iterator}}, {{Iterable}},
> {{T[]}}, and all 8 primitive array types. {{toImmutableSet}} also added for
> {{Stream}}. ({{toImmutableList(Stream)}} is omitted — native
> {{Stream#toList()}} already covers it.)
> * *Add explicit-mutability {{toMutableList}} / {{toMutableSet}}* for
> {{Stream}} and {{BaseStream}}, so user intent stays unambiguous and the GDK
> is defensively positioned against any future JDK release adding more native
> instance methods that would shadow GDK extensions the way native
> {{Stream#toList()}} did.
> * *Deprecate {{StreamGroovyMethods.toList(Stream)}}* — shadowed in both
> static and dynamic dispatch by native {{Stream#toList()}} on JDK 16+, so
> the method is effectively dead code in idiomatic call sites. Migration:
> {{toMutableList(Stream)}} for an explicit mutable list, native
> {{stream.toList()}} for an immutable one. The javadoc on the deprecated
> method is also updated to flag the JDK-16+ semantic shift for anyone who
> lands on it.
> h2. Scope
> || File || New methods || Other ||
> | {{StreamGroovyMethods}} | 7 ({{toMutableList(Stream)}},
> {{toMutableList(BaseStream)}}, {{toMutableSet(Stream)}},
> {{toMutableSet(BaseStream)}}, {{toImmutableList(BaseStream)}},
> {{toImmutableSet(Stream)}}, {{toImmutableSet(BaseStream)}}) | +1 cached
> {{Collector}} ({{TO_UNMODIFIABLE_SET}}) used by the new immutable Set
> methods; 1 deprecation; javadoc note |
> | {{DefaultGroovyMethods}} | 4 ({{toImmutableList(Iterator)}},
> {{toImmutableList(Iterable)}}, {{toImmutableSet(Iterator)}},
> {{toImmutableSet(Iterable)}}) | — |
> | {{ArrayGroovyMethods}} | 18 ({{toImmutableList}}/{{toImmutableSet}} ×
> {{T[]}} + 8 primitive arrays) | — |
> 29 new methods total, 1 deprecation. Fully additive: no public-API change to
> existing methods beyond the {{@Deprecated}} annotation and javadoc.
> h2. Compatibility
> * No source or binary breakage for any existing caller.
> * The deprecation produces no warnings on internal Groovy code: only callers
> of {{StreamGroovyMethods.toList(Stream)}} are themselves {{@Deprecated}}
> bridge methods (in {{PluginDefaultGroovyMethods}}), and javac's
> {{-Xlint:deprecation}} does not flag {{@Deprecated → @Deprecated}} calls.
> * Users on JDK 16+ writing idiomatic {{stream.toList()}} are already getting
> the native call — no change for them.
> * The only callers who will see the deprecation warning are those explicitly
> invoking the GDK extension via the static-method form
> ({{StreamGroovyMethods.toList(stream)}}), which is exactly the audience that
> needs to make an informed mutable-vs-immutable choice.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)