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.
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.
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.
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;
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.
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
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’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