Error E62: Type mismatch, cannot assign "array of nullable Single" to "array of Single"

IDE: Fire_
Version: 9.3.0.2191
Target OSX
Description: I got the Errormessage:
error E62: Type mismatch, cannot assign “array of nullable Single” to “array of Single”

Steps:

namespace test;
type
  TTestArray<T> = class
  private
    fData : array of T;
  public
    constructor (Value: array of T; StartIndex: Integer; aLength: Integer);
    begin
      fData := new T[aLength];
      for i: Integer := StartIndex to (StartIndex + aLength) - 1 do
        fData[i - StartIndex] := Value[i];
    end;

    constructor(const Values : array of T);
    begin
      constructor (Values, 0, Values.length);
    end;

    class operator Implicit(Values : array of T) : TTestArray<T>;
    begin
      exit new TTestArray<T>(Values);
    end;

    method toArray() :  array of T;
    begin
      var i : Integer;
      result := new T[fData.length];
      for i := 0 to fData.length-1 do
        result[i] := fData[i];
    end;
  end;

end.

method Program.testArray;
begin
  var s : TTestArray<Single> := [1.1, 2.2];
  var a : array of Single;
  a := s.toArray; // Error is here
end;

Seems valid? they aren’t the same thing. one has nullable (ie wrapped) singles, one other regular (unwrapped) ones. they wont be assignment compatible.

pmfji, is TGeneric<T> always implicitly (effectively) TGeneric<nullable T>?

Right because of how type erasure generics work (which we use on Cocoa and Java) all generic parameters are reference types.

So is this platform specific ? i.e. different on .net (and island ?)

In any event, and perhaps this horse has long since bolted, but I personally would prefer that if the compiler requires that a type be nullable then this be required to be explicit in the code.

In this case, knowing how the compiler works the error makes sense/is valid.

Not knowing how the compiler works, the error seems to contradict the code/looks like a compiler bug.

I wonder how many people might be coding with TGeneric<T> without being aware of the need - potentially - to properly allow for the implicit nullability of T ? You could argue that if it isn’t causing a problem (in those cases) then it isn’t a problem. Or you could argue that these are problems waiting to happen. :wink:

imho

Having just confirmed that there is a clear distinction between TGeneric<Single> and TGeneric<nullable Single> on .net at least, I am going to stick my neck out and say that imho the compiler should simply not allow the former on platforms where the latter is required due to platform considerations/constraints.

If such code is required to be cross-platform then the developer must surely consciously opt-in to and design for the use of a nullable type or consider an alternative approach.

Or am I just a nervous ninny ? O.o

We’re working against platform limitations so we can’t really “fix” this in a way that makes it work equal.

If we disallow say ArrayList<Integer> then it becomes impossible to write cross platform code, so it’s a bit of a problem. We went for the middle road, and if you use type inference it generally works exactly the way you expect it, which I hope is the best solution for a hard problem.

Ok i understand the limitations, so for me there is no way to easily use a generic way to solve a problem i have with legal code.
The code in general is using a lot of array of records with
like myarray := myarray + [value, …].
The idea was to solve it with a generic array class.
i need it with not nullable types.
so how to declare a method that will return a array of not nullable T as return type?

 method toArray() :  array of T;  // How can i make these a not Nullable?
    begin
      var i : Integer;
      result := new T[fData.length];
      for i := 0 to fData.length-1 do
        result[i] := fData[i];
    end;

@ck I don’t understand.

If you disallow ArrayList<Integer> on platforms that don’t/can’t actually support ArrayList<Integer> then you would instead need simply to explicitly use ArrayList<nullable Integer> which would then be cross-platform code and have the benefit of not just being the same source compilable on all platforms but also have the same runtime behaviours on those platforms. No ?

Is it not the case that currently whilst the code (as source) compiles on all platforms, but on some platforms you have potentially significantly different results from compiling that source vs others ?

One consequence is that which we see here: Some code which looks as though it should compile on any platform and I believe does compile on some platforms, but not on others.

So is the cross-platform goal even achieved ? And if it can’t be, then is it not better to have code that least “does what it says on the tin” ? imho. :slight_smile:

1 Like

That’d make for a lot of ugly code with generics on value types though. no more silly doing List<Int>.

Supplemental question: What happens if/when Generic Specialization arrives in Java (Project Valhalla) ? Would an Oxygene TGeneric<T> suddenly switch from being compiled as TGeneric<silently,implicitly nullable T> to … what was actually written (on Java, as is already the case for .net etc) ? O.o

Probably, yes.

Ok, so I still don’t get it then. “Ugly” is not a term I would use in place of “unfortunately necessary”. Inconvenient maybe.

But as a developer, imho, inconvenience is your friend when doing things you need to be aware of that you might otherwise not necessarily be aware of.

ERRxxxx: `TGeneric<Integer>` is not supported.  Value type generic specializations are required to be nullable on this platform.  Use `TGeneric<nullable Integer>` instead.

Damn, thinks I, it would have been convenient if the compiler just made it nullable anyway, but at least now I know that use of this generic instance requires me to allow for potential nulls which otherwise I might not. If I need those nulls then this is no big deal - I would simply declare and use it as such (just as I will in the future if/when it makes sense on this platform to distinguish between nullable and not-nullable type specialisation).

But if I was expecting non-nullability (as written) and not properly catering for it then this error potentially saved me some more serious headaches.

i see your point and kinda agree, yeah. i‘ll bring it iup for discussion w/ @ck.

I’m with Jolyon here,
it is inconvenience. You can declare a Generic but if you want to use a Block
you need the Nullable. So at least a warning should be shown. In other cases you are looking at the code and there is no way to find out what is wrong.
See here:
https://talk.remobjects.com/t/generic-block/14248?source_topic_id=14281

Thanks, logged as bugs://78578

bugs://E20169 was closed as fixed.