Reflection Bug + Soln

Archives Forums/BlitzMax Bug Reports/Reflection Bug + Soln

beanage(Posted 2010) [#1]
Hey,

just came across this error: TTypeID.ForObject() will always return Null when executed in the constructor method of a global object declared in the scope of a type. Consider this code:

Type mytype
	Global objectvar:mytype = New mytype

	Method New()
		Local obj:Object = New mytype2
		Print TTypeId.ForObject( obj ).name() 'BUG HERE!
	End Method
End Type

Type mytype2
	
End Type


This should reasoably print "mytype2". But an EAV is what you get.
Took me a while to track this down tho, so please fix this soon!

A temporary solution is to move the global into file scope. This would not make TTypeID.ForObject( objectvar ) (from the example) work, but thats fine, as you would barely reflect an objects type within its own constructor.


Difference(Posted 2010) [#2]
Type mytype2
	
End Type

Type mytype
	Global objectvar:mytype = New mytype

	Method New()
		Local obj:Object = New mytype2
		Print TTypeId.ForObject( obj ).name() 'BUG HERE!
	End Method
End Type

This one works.
It seems TTypeId.ForObject needs the type declared earlier in the code in order to recognize it.


beanage(Posted 2010) [#3]
Thats strange. I mean, this seems to contradict all previous experiences where declaration order of functions and types just didnt seem to matter. Thanks for your reply!


beanage(Posted 2010) [#4]
Has anything been done on this yet, anyone? At least an explanation of the inconsistent behaviour would be nice.

Last edited 2010


plash(Posted 2010) [#5]
The problem is the order of declaration (clearly). Types are registered in the same order that they are declared, but globals inside of types are registered before the type gets registered (which should probably be changed, barring any other issues from an order change).

For example, with the original, the linear declaration order is:
Type mytype
Global objectvar:mytype
Type mytype2


Thus the order of calls will be:
_bb_mytype_objectvar = bbObjectNew(mytype)
bbObjectRegisterType(bb_mytype)
bbObjectRegisterType(bb_mytype2)


The mytype.New() method cannot access type information on mytype2 because it hasn't yet been registered.

With the working example by Difference, the order of mytype2 is before the declaration of objectvar and mytype:
Type mytype2
Type mytype
Global objectvar:mytype


Then the call order is:
bbObjectRegisterType(bb_mytype2)
_bb_mytype_objectvar = bbObjectNew(mytype)
bbObjectRegisterType(bb_mytype)


The safest solution (for example, if the mytype.New() method needs to know type information about mytype) would be to move the global below (or above) both declarations, but that would remove it from mytype. Moving the objectvar declaration out of and above or below the type declarations would work because all type members are instantiated and registered before global globals.

Last edited 2010


beanage(Posted 2010) [#6]
Thank you! - that really clears things up for me.

I thought it was a compiler bug, but that makes sense.

Last edited 2010