Equality

Peter Levart peter.levart at gmail.com
Wed Dec 23 16:30:55 UTC 2015


Hi,

Sometimes I miss a feature in generic type declarations where one could 
refer to a type variable of a super type without repeating it in the 
declaration of the generic type. For example, currently one has to write:


interface Snapshooter<E, C extends Collection<E>> {
     C snapshot();
     boolean addElement(E e);
}

Snapshooter<String, List<String>> strings = ...;

List<String> snapshot1 = strings.snapshot();
strings.addElement("abc");
List<String> snapshot2 = strings.snapshot();


What if E could be implicitly declared like:

interface <E> Snapshooter<C extends Collection<E>> {
     C snapshot();
     boolean addElement(E e);
}

Snapshooter<List<String>> strings = ...;


Which would be similar to declaring:

interface Snapshooter<C extends Collection<?>> { ... }

...with added benefit that one could refer to E from Collection<E>.


I don't know if this could be soundly incorporated into the language 
type system, but if it could be, and if interfaces could also be 
implemented by value types, then...

On 12/19/2015 05:38 PM, Brian Goetz wrote:
>> Anyfy equals, and adjust default implementation of boolean 
>> T.equals(any x)
>
> I think we may be talking past each other (while basically saying the 
> same thing from opposite directions.)
>
> "any" is not a type; it is a modifier that affects the domain of type 
> variables.  So we don't have (and I think we don't want) a meaning for 
> equals(any x).  But what we do want, is a way of expressing "I'll take 
> anything which could be on the other side of the == operator with me." 
> For refs, that's Object; for a value type V, that's just V.
>
> Where we had gotten with the <V super U> / superation idiom (not 
> suggesting either of these syntaxes is great) is being able to express:
>
>  - If T is value, then T, else the erasure of T (usually object) **
>
> I'll write this as Sup<T> for short.  The convenient thing about 
> Sup<T> is that it conveniently collapses to Object in the places where 
> we want Object, so we could define contains/remove as
>
>   contains(Sup<T>)
>
> and contains will always bottom out at equals(), so equals() similarly 
> needs to be
>
>   equals(Sup<Self>)
>
> If this is a valid approach (and I think its the best one we've got so 
> far), then we're looking for how to spell Sup<Self> (in all of: type 
> system, language syntax, bytecode descriptors.)


....there could be a special interface:

public interface Any<any T extends Any<T>> {
     boolean equals(T x);
}


...implemented by Object:

public class Object implements Any<Object> {...}

...and implicitly implemented by every value type:

public value ValueType [ implements Any<ValueType> ] {...}


Sup<E> from Collection<any E> could then be expressed as:

public interface <T> Collection<any E extends Any<T>> extends Iterable<E> {
     boolean contains(T x);
     ...


Regards, Peter

>
>> I still think that doing something like this removes the need
>> to specially deal with Collection.contains and related methods.
>
> I don't see it yet; those signatures are still currently 
> contains(Object), which isn't appropriate for value types.  So we have 
> to do *something*.
>
>
>
>
> ** There's a lot of sloppiness in the ref/val distinction, which is 
> going to need to be cleaned up.  Sometimes when we say ref/val, we 
> mean "erased/reified".  Sometimes we mean "polymorphic/monomorphic". 
> Sometimes we mean "nullable/non-nullable."



More information about the valhalla-spec-experts mailing list