Closed Neverbirth closed 5 years ago
The second one is a real issue.
As for the object
- that's how the c# target currently works. As @waneck explained before, since the memory layout is the same, there's no real benefit of working around the haxe/c# type system differences to make the code look more "native", and by some tests it even worked faster. I'd like to review/check that again though, because this topic is brought quite often.
? Would love to see those tests. While what you say is true for some cases, it's not for all of them. Think for example of a generic that in the end is creating an array for ints, with the code used for c# you'll end creating an array of objects, in that case the memory layout is not the same and haxe code will be much slower for some uses. Also, what if you use constraints for the generic type? I didn't check this use case, but do you rely on reflection to access known methods and properties? in that case it's clear it will also be slower.
There are other cases too, but I'd say that in a lot of cases the produced code will be slower (admittedly in a lot of them the difference will be minimal), maybe those tests were not taking into account GC garbage, starting up overload and other things that can take an effect into the final results?
EDIT: Tested it, I see that constraints are not converted over to C# code, and that in fact reflection is used unless we define the exact type to be used in the interface or class declaration.
Well, for basic types (int,double,bool) it generates proper type, it's just all others that are pointers anyway, but yeah, we should look into it at some point in future.
I see, I thought the object replacement was used everywhere, my bad. There may be some cases where it can still be a problem, like arrays of primitive types, but I think this one would be very uncommon.
At any rate, that bug when using Dynamic is way more important, it's for example making hexMachina not usable when targetting C#, a real shame as it's already working for a few targets.
Is there any way to avoid this issue? Haxe falls back to reflection when iterating through Map values like this.
I'm not sure why losing generic parameter makes program faster either. That will cause lots of casts, and makes code size bigger. Compilers cannot generate optimized code from such big code.
Even when reflection is not used it could be bad for performance because of lots of casts.
Also, losing type information is bad if you want to make a library for existing .NET application, or if you want to use that library from Haxe with -net-lib
. You need to do cast everywhere to get an instance of correct type from arrays/maps.
Also, losing type information is bad if you want to make a library for existing .NET application, or if you want to use that library from Haxe with -net-lib. You need to do cast everywhere to get an instance of correct type from arrays/maps.
That's a good point... I didn't try it, but what if you have a library that requires to get for example some GenericClass<CustomClass>
instance? AFAIK GenericClass<Object>
won't work in the cases where variance is not defined, will it?
You mean we should support casting to GenericClass<object>
from GenericClass<CustomClass>
in some way?
Then, should all generic classes have wrapper object like arrays/maps to support variance? That may work, but makes generated code complex, and creates many objects for casting.
Could that be the other way around?
Just create class instances with type parameter(SomeList<CustomClass>
), and automatically upcast to CustomClass
if you want to push some element, and downcast to `object' when you get some element from object.
This way we don't need wrappers, but list cannot contain any kind of object anymore.
Should a List be able to contain any kind of object? Then it's not possible to support variance in this way.
but you can't insert objects to Array<Int>
already, can you?
You mean we should support casting to GenericClass
Not exactly. I mean if you have some external assembly expecting a GenericClass<CustomClass>
instance, but Haxe is generating for your code GenericClass<object>
your code won't work. I don't know if right now there is some workaround for this in place (you could use LINQ Cast() or OfType() functions for example), but if so I'd guess it would fail when using reflection for example.
I guess the same happens if you generate public API with Haxe? You want to generate an assembly that accepts GenericClass<CustomClass>
, but Haxe exposes GenericClass<object>
, is this so? Not very nice :S.
Not so nice, but it seems impossible to GenericClass<CustomClass>
without knowing about underlying type. You'll need to cast to GenericClass<CustomClass>
in some way.
But it's not possible to cast GenericClass<int>
to GenericClass<object>
either. Then is it meaningful to suppot GenericClass<CustomClass>
to GenericClass<object>
?
So, this is not for supporting cast to GenericClass<object>
??
I've tried writing a function that returns System.Collections.Generic.List<CustomClass>
. In this case the function returned List<CustomClass>
. So this only applies to Haxe-created classes?
I'm not sure to follow you :/. Having some fictitious 3rdparty.dll that you reference in your HxCS project, and 3rdparty.dll has a class NameSpace.ClassA
that you need to use, with a IComparable<ClassA> Comparer
property. You may have in your Haxe project something like class Test<T> implements IComparable_1<T>
.
When you do new ClassA().Comparer = new Test<ClassA>()
it gets converted to something similar to:
new global::NameSpace.ClassA().Comparer = ((global::System.IComparable<global::NameSpace.ClassA>) (new global::_Main.Test<object>()) );
Which AFAIK, should fail.
Just tested it. Indeed it fails. Note that my sample is not 100% valid tho, because I was using IComparable, and from .NET 4 onward it's using variance (it's defined as public interface IComparable<in T>
in there)... if we use a normal interface that isn't defining any variance (like I said some comments above) it's failing. I could upload a sample if desired.
I've found the place where this conversion is done.
Changing dynamic_anon
to t
disabled type parameter conversion. However, as I mentioned , this will cause problems with GenericClass<Dynamic>
because you cannot convert GenricClass<CustomClass>
to GenericClass<Dynamic>
.
@Neverbirth your test class is just a haxe-generated class that implements builtin .NET interface, so haxe still converts type parameters to object
I guess.
Should we be able to convert GenricClass<CustomClass>
to GenericClass<Dynamic>
, in the first place? I rarely use this technique, but probably we should support this in some way because other targets support this.
Could this be fixed without converting all type parameters to object
when https://github.com/HaxeFoundation/haxe/issues/4475 is implemented?
Oh, I didn't consider how GenericClass<Dynamic>
works in Haxe. Tricky indeed... I can think of workarounds for a lot of cases, but not to all of them... never had to thought of a case like this... Personally, if I would have to choose between this and keeping class definitions in generics I would choose the second tho.
EDIT: I guess typedefs can also become a bit tricky... didn't check the generated code for a case like this.
Anyway, all this topic is not a showstopper like the second bug I mentioned in my original report.
Seems to be fixed by #8387 (or is there something else to do here?)
Having for example the following piece of code:
Generates the following C# code for ISubTest:
As you can see it completely loses the types we want to use. I tried different types, and I was always getting object for the generic type. Furthermore, this one:
Doesn't compile at all, because it generates some invalid implementation of the interface in
TestClass
:I would say this is a rather important issue.