Re: [Vala] nullable generic types

On Mon, Apr 05, 2010 at 14:10:23 -0700, Adam Dingle wrote:
I've noticed that Vala forces generic types to be non-nullable when
instantiated with a primitive type.

Quite the opposite. Generic types in Vala can only contain reference types or
int, so all other struct types need to be boxed using '?'. Enums and boolean
should behave like int for this purpose, but I am not sure it's currently

For example:

public class List<T> {
 public T? abc() { return null; }

 public bool def(T? t) { return t == null; }

void main() {
 List<int> list = new List<int>();
 int? i =;   // i receives the value 0, not null
 bool b = list.def(null);   // compiler error: cannot convert from
null to int

What is going on here is that boxing of the type parameter is not
supported since it has to be boxed. 'int' is a special case, which would need
special-case code and there's none generated.

Is this behavior by design?  I suspect that it is: this allows the
compiler to generate only one copy of List<T> and use it for all
instantiations including both reference and primitive types.  If
this is a compromise by design, I think that it's a reasonable one,
though it would be nice to know whether we can expect this behavior
to remain the same in the future.  :)

There is indeed only one code for List<T>. That is so the generic code can be
placed in a library and used from separate code. In this it's similar to Java
generics and different from C++ templates that need to be fully defined in

The above has a practical consequence when using generic collections:

HashMap<int, int> m = ...;
int? i = m.get(5);

Now i receives the value 0 (not null) if the element is absent.

It returns T, which is int, NOT int?, so you don't expect it to return null,
do you?

On a related note, I've noticed that 'valac --vapi' makes generic
types non-nullable.  If I generate a VAPI file for the List class
above it looks like this:

public class List<T> {
   public List ();
   public T abc ();
   public bool def (T t);

Is this a bug?  Conceivably the nullable types are erased in the
VAPI file as a warning to callers that they will not actually be
nullable when the class is instantiated with a primitive type, given
the behavior above.  But there doesn't seem to be much point to
that, since callers must expect this same behavior when nullable
types are present in a generic class anyway, even one which is not
defined via a VAPI file.  Is there some other reason why the types
should not be nullable in the VAPI file?

As explained above, T is always reference type, so T? makes no sense.

The generic is compiled with just void * and pointers to correct copy/ref and
destroy/unref functions are passed around. Since it is already pointer, it is
already nullable, so conversion to nullable does nothing. All types are boxed
to be representable by void *. Except int, which is simply cast to void *
(sizeof(int) <= sizeof(void *) on all platforms), but that makes it

Note though, that you can substitute 'int?' as the template parameter and
than there will be difference between null and 0 (and a huge memory overhead
for allocating the storage).

                                                 Jan 'Bulb' Hudec <bulb ucw cz>

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]