www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - detect implicitly convertible typeid's?

reply bitwise <bitwise.pvt gmail.com> writes:
Is it possible to tell if two objects represented by TypeInfo's 
are convertible to each other?

Basically, is there a built in way to do this?

int x;
long y;
assert(typeid(x).isImplicitlyConvertibleTo(typeid(y));

    Thanks
Sep 23 2017
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 9/23/17 11:52 AM, bitwise wrote:
 Is it possible to tell if two objects represented by TypeInfo's are 
 convertible to each other?
 
 Basically, is there a built in way to do this?
 
 int x;
 long y;
 assert(typeid(x).isImplicitlyConvertibleTo(typeid(y));
I would say no. There isn't any function/data to detect that. Keep in mind that TypeInfo is generated by the compiler, and only contains what the developers of the runtime have wanted it to contain. It's not a full-fledged reflection system. However, you COULD build something in RTInfo that could place that inside the TypeInfo. That is what RTInfo was added for. -Steve
Sep 25 2017
parent reply bitwise <bitwise.pvt gmail.com> writes:
On Monday, 25 September 2017 at 13:20:03 UTC, Steven 
Schveighoffer wrote:
 On 9/23/17 11:52 AM, bitwise wrote:
 Is it possible to tell if two objects represented by 
 TypeInfo's are convertible to each other?
 
 Basically, is there a built in way to do this?
 
 int x;
 long y;
 assert(typeid(x).isImplicitlyConvertibleTo(typeid(y));
I would say no. There isn't any function/data to detect that. Keep in mind that TypeInfo is generated by the compiler, and only contains what the developers of the runtime have wanted it to contain. It's not a full-fledged reflection system.
Something like this along side TypeInfo.postblit and TypeInfo.destroy would actually be useful: TypeInfo.cast(void* src, void** dst, TypeInfo dstType); I wonder though...does a cast even resolve to a single function call at compile time, or is there scattered context-dependent code throughout the compiler to insert the appropriate logic? Based on current trends though, it seems like TypeInfo.postblit/destroy may be on the chopping block...any idea?
 However, you COULD build something in RTInfo that could place 
 that inside the TypeInfo. That is what RTInfo was added for.
The comments say it's for precise GC: https://github.com/dlang/druntime/blob/cc8edc611fa1d753ebb6a5fabbc3f37d8564bda3/src/object.d#L312-L314 Doesn't that mean my code could some day get clobbered if I put it there and precise GC is implemented? Also, don't I need to compile a custom runtime for that? Thanks
Sep 25 2017
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 9/25/17 10:43 AM, bitwise wrote:
 On Monday, 25 September 2017 at 13:20:03 UTC, Steven Schveighoffer wrote:
 On 9/23/17 11:52 AM, bitwise wrote:
 Is it possible to tell if two objects represented by TypeInfo's are 
 convertible to each other?

 Basically, is there a built in way to do this?

 int x;
 long y;
 assert(typeid(x).isImplicitlyConvertibleTo(typeid(y));
I would say no. There isn't any function/data to detect that. Keep in mind that TypeInfo is generated by the compiler, and only contains what the developers of the runtime have wanted it to contain. It's not a full-fledged reflection system.
Something like this along side TypeInfo.postblit and TypeInfo.destroy would actually be useful: TypeInfo.cast(void* src, void** dst, TypeInfo dstType);
I'm not sure of how much use this is, but I do not know enough to say that it's completely useless :) Certainly, some code somewhere has to be able to understand what the actual type of something is. That code may be more equipped to do the cast than code that doesn't know.
 I wonder though...does a cast even resolve to a single function call at 
 compile time, or is there scattered context-dependent code throughout 
 the compiler to insert the appropriate logic?
A cast of builtin types is handled directly by the compiler. There is no function, for instance, to cast an int to a long. A cast of a class will go through dynamic type casting. A cast of custom types will call the opCast member (or in the case of implicit conversions, will use the alias this call).
 Based on current trends though, it seems like TypeInfo.postblit/destroy 
 may be on the chopping block...any idea?
Hm... I don't know, but I would guess that almost everything in TypeInfo is on the chopping block. If we could replace AA implementation with something that is entirely library based, we wouldn't need most of that stuff.
 However, you COULD build something in RTInfo that could place that 
 inside the TypeInfo. That is what RTInfo was added for.
The comments say it's for precise GC: https://github.com/dlang/druntime/blob/cc8edc611fa1d753ebb6a5fabbc3f37d8564bda3/sr /object.d#L312-L314
The reason it was added was to allow development of a precise GC without having to muck with the compiler. Essentially it is instantiated once per type and the result added to the TypeInfo by the compiler. Precise GC is one possibility for that, but it can be used for anything.
 Doesn't that mean my code could some day get clobbered if I put it there 
 and precise GC is implemented?
 
 Also, don't I need to compile a custom runtime for that?
The answer to the last is that, yes, at the moment you need a custom runtime. The answer to the first is that you need a custom runtime anyway, so you don't have to worry about clobbering :) I would say that once we DO need RTInfo for something (right now it is unused), we need to consider options for how to make it available for multiple things at once. -Steve
Sep 25 2017
parent reply bitwise <bitwise.pvt gmail.com> writes:
On Monday, 25 September 2017 at 15:12:57 UTC, Steven 
Schveighoffer wrote:
 [...]

 I'm not sure of how much use this is, but I do not know enough 
 to say that it's completely useless :)
 Certainly, some code somewhere has to be able to understand
 what the actual type of something is. That code may be more
 equipped to do the cast than code that doesn't know.
Type-boxing can be made much easier. The current implementation of Variant falls short in a few ways. Variant.coerce(T) needs the type at compile time, only works for certain types, and needs a bunch of extra code to get it done. Giving TypeInfo a 'cast' method seems like a more robust solution. I've been working through a problem though, and it seesms like the only insurmountable issue is that Variant won't give you a pointer to it's contents without knowing the exact type. I have a reflection system where you can get a collection of 'Property' objects that represent all properties of a class/struct. The 'Property' returns a Variant holding the return value of the property function. So even though the 'Property' gives me a Reflection object for the return value, I still can't reflect on the contents of the Variant because I can't get a pointer to it at runtime. Basically, I need to take a given class and recursively scan 2-3 levels deep to find any properties/fields that are floats so they can be animated. The only setback right now is that Variant won't give me a void* to it's contents so I can reflect on it, modify it, and set it back in.
 A cast of builtin types is handled directly by the compiler. 
 There is no function, for instance, to cast an int to a long.

 A cast of a class will go through dynamic type casting.

 A cast of custom types will call the opCast member (or in the 
 case of implicit conversions, will use the alias this call).
I guess this makes sense. I suppose it would be dumb to resort to checking TypeInfo every time you needed to cast a byte to an int. This part of my question was not particularly well(at all) thought out =/
 The answer to the last is that, yes, at the moment you need a 
 custom runtime.
I really don't want to maintain a custom runtime just for this. It would be nice if there was a compiler flag to specify an RTInfo template to use. Or better yet, an attribute. so this: ` module source; template MyRTInfo(T) { ... } ` dmd source.d -rtinfo "source.MyRTInfo" Or even better, this: ` module reflection; rtinfo template RTInfo(T) { ... } module test; class Test{} // typeid(Test).rtinfo == reflection.RTInfo ` dmd reflection.d test.d So of course, dmd could complain if you specified more than one RTInfo either way. If two static libraries were built with different RTInfo's, I don't think it would technically be a problem since every TypeInfo would get it's own rtinfo pointer anyways. Maybe something in the runtime could somehow warn about mismatched RTInfo types like it does about cyclic module dependencies.
Sep 26 2017
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 9/26/17 12:56 PM, bitwise wrote:
 On Monday, 25 September 2017 at 15:12:57 UTC, Steven Schveighoffer wrote:
 The answer to the last is that, yes, at the moment you need a custom 
 runtime.
I really don't want to maintain a custom runtime just for this. It would be nice if there was a compiler flag to specify an RTInfo template to use. Or better yet, an attribute. so this: ` module source; template MyRTInfo(T) { ... } ` dmd source.d -rtinfo "source.MyRTInfo" Or even better, this: ` module reflection; rtinfo template RTInfo(T) { ... } module test; class Test{} // typeid(Test).rtinfo == reflection.RTInfo ` dmd reflection.d test.d
I think there have been attempts to make the resulting rtinfo a combination of what druntime wants + whatever the type wants. But I'm not sure how far those got or the problems involved. I would expect that at some point we will need to flesh it out. It's more of an abstract concept than something anyone has used for meaningful work.
 So of course, dmd could complain if you specified more than one RTInfo 
 either way. If two static libraries were built with different RTInfo's, 
 I don't think it would technically be a problem since every TypeInfo 
 would get it's own rtinfo pointer anyways. Maybe something in the 
 runtime could somehow warn about mismatched RTInfo types like it does 
 about cyclic module dependencies.
I would expect that you could embed as many descriptors as you want inside the TypeInfo. We just have to come up with a way to store them in ROM and address them sensibly. Similar to a vtable. -Steve
Sep 26 2017
parent reply bitwise <bitwise.pvt gmail.com> writes:
On Tuesday, 26 September 2017 at 17:27:02 UTC, Steven 
Schveighoffer wrote:
 -Steve
About Variant - I was considering a pull request for retrieving a pointer to the internal data, but figured that it was left out on purpose due to safety. OTOH, I was looking through dmd commits, and it seems like there has been significant progress on 'scope'. So I was thinking this: struct Variant { scope inout(ubyte)[] data() inout { auto sz = type.tsize; assert(sz <= size); return store[0..sz]; } } Thoughts?
Sep 26 2017
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 9/26/17 3:14 PM, bitwise wrote:
 On Tuesday, 26 September 2017 at 17:27:02 UTC, Steven Schveighoffer wrote:
 -Steve
About Variant - I was considering a pull request for retrieving a pointer to the internal data, but figured that it was left out on purpose due to safety. OTOH, I was looking through dmd commits, and it seems like there has been significant progress on 'scope'. So I was thinking this: struct Variant {     scope inout(ubyte)[] data() inout     {         auto sz = type.tsize;         assert(sz <= size);         return store[0..sz];     } } Thoughts?
I just recently fixed Variant so it could accept shared data (so you could pass shared data using std.concurrency), and part of that depends on the fact that I know nothing else can point at the data (so no locking/atomics are necessary, we know the actual data is not shared). I think it's very dangerous to extract a reference to the data, it breaks all kinds of expectations. -Steve
Sep 26 2017
parent bitwise <bitwise.pvt gmail.com> writes:
On Tuesday, 26 September 2017 at 19:31:56 UTC, Steven 
Schveighoffer wrote:
 [...]

 I just recently fixed Variant so it could accept shared data 
 (so you could pass shared data using std.concurrency), and part 
 of that depends on the fact that I know nothing else can point 
 at the data (so no locking/atomics are necessary, we know the 
 actual data is not shared).

 I think it's very dangerous to extract a reference to the data, 
 it breaks all kinds of expectations.

 -Steve
Ok - I guess I'll have to make a custom Box of some kind. Or maybe...even think outside the box ;) Thanks
Sep 26 2017