Ah, I'm an idiot. There is still a proposal here somewhere...maybe. right now non jdk lists can't participate in the special casing?
On Tue, Aug 23, 2022, 9:00 PM Paul Sandoz <paul.san...@oracle.com> wrote: > List.copyOf already does what you want. > > > https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/List.java#L1068 > > https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/ImmutableCollections.java#L168 > > Paul. > > > On Aug 23, 2022, at 4:49 PM, Ethan McCue <et...@mccue.dev> wrote: > > > > Hi all, > > > > I am running into an issue with the collections framework where I have > to choose between good semantics for users and performance. > > > > Specifically I am taking a java.util.List from my users and I need to > choose to either > > * Not defensively copy and expose a potential footgun when I pass that > List to another thread > > * Defensively copy and make my users pay an unnecessary runtime cost. > > > > What I would really want, in a nutshell, is for List.copyOf to be a > no-op when used on lists made with List.of(). > > > > Below the line is a pitch I wrote up on reddit 7 months ago for a > mechanism I think could accomplish that. My goal is to share the idea a bit > more widely and to this specific audience to get feedback. > > > > > https://www.reddit.com/r/java/comments/sf8qrv/comment/hv8or92/?utm_source=share&utm_medium=web2x&context=3 > > > > Important also for context is Ron Pressler's comment above. > > -------------- > > > > What if the collections api added more marker interfaces like > RandomAccess? > > > > It's already a common thing for codebases to make explicit null checks > at error boundaries because the type system can't encode null | > List<String>. > > > > This feels like a similar problem. > > If you have a List<T> in the type system then you don't know for sure > you can call any methods on it until you check that its not null. In the > same way, there is a set of methods that you don't know at the > type/interface level if you are allowed to call. > > > > If the List is actually a __ > > Then you can definitely call > > And you know other reference holders might call > > And you can confirm its this case by > > null > > no methods > > no methods > > list == null > > List.of(...) > > get, size > > get, size > > ??? > > Collections.unmodifiableList(...) > > get, size > > get, size, add, set > > ??? > > Arrays.asList(...) > > get, size, set > > get, size, set > > ??? > > new ArrayList<>() > > get, size, add, set > > get, size, add, set > > ??? > > While yes, there is no feasible way to encode these things in the type > system. Its not impossible to encode it at runtime though. > > interface FullyImmutable { > > // So you know the existence of this implies the absence > > // of the others > > default Void cantIntersect() { return null; } > > } > > > > interace MutationCapability { > > default String cantIntersect() { return ""; } > > } > > > > interface Addable extends MutationCapability {} > > interface Settable extends MutationCapability {} > > > > If the List is actually a __ > > Then you can definitely call > > And you know other reference holders might call > > And you can confirm its this case by > > null > > no methods > > no methods > > list == null > > List.of(...) > > get, size > > get, size > > instanceof FullyImmutable > > Collections.unmodifiableList(...) > > get, size > > get, size, add, set > > !(instanceof Addable) && !(instanceof Settable) > > Arrays.asList(...) > > get, size, set > > get, size, set > > instanceof Settable > > new ArrayList<>() > > get, size, add, set > > get, size, add, set > > instanceof Settable && instanceof Addable > > In the same way a RandomAccess check let's implementations decide > whether they want to try an alternative algorithm or crash, some marker > "capability" interfaces would let users of a collection decide if they want > to clone what they are given before working on it. > > > > > > -------------- > > > > So the applicability of this would be that the list returned by List.of > could implement FullyImmutable, signifying that there is no caller which > might have a mutable handle on the collection. Then List.of could check for > this interface and skip a copy. > > > > > >