reflaxe.CPP icon indicating copy to clipboard operation
reflaxe.CPP copied to clipboard

Leaking(?) unsafe "this" pointer

Open fourst4r opened this issue 1 year ago • 3 comments

There's a slight inconsistency in the way the this pointer works between assigning to a variable and directly returning it. Assigning to a variable gives you Ptr, while returning gives you SharedPtr.

class FooBuilder {
    public function new() {}
    public function withBar() {

        // return this // <-- works

        var r = this;
        return r; // <-- does not work: Cannot convert unsafe pointer (Ptr<T>) to shared pointer (SharedPtr<T>).

    }
}

function main() {
    new FooBuilder().withBar();
}

fourst4r avatar Jan 02 '24 09:01 fourst4r

This is a real tough one, it's been keeping me up for weeks. I know I have a bad track record when it comes to saying things are "impossible", but I think this one might actually be atm. 😅

The issue is the typing of "this" doesn't come from Haxe. Reflaxe/C++ has to manually inject the idea is Ptr<FooBuilder> instead of FooBuilder.

This results in this issue where Reflaxe cannot know the true return type of this function without first iterating through the function and generating it. So if this function is encountered elsewhere, it can only use the type Haxe knows (which would be FooBuilder that defaults to SharedPtr <FoorBuilder>).

Of course, a system could be set up to analyze a function upon encountering anywhere, but at the current moment Reflaxe analyzes and generates simultaneously, so it would require a pretty big rework to "analyze" alone.

return this works because there's a special case for handling Ptr to SharedPtr conversion from this (the generated code still uses shared_ptr).

One day I plan to introduce an intermediate data system for Reflaxe/C++ instead of converting directly from AST to String, but until then, this'll need to be manually typed.

SomeRanDev avatar Jan 26 '24 05:01 SomeRanDev

Is there a way to convert this to SharedPtr?

fourst4r avatar Jan 26 '24 08:01 fourst4r

Yes! It's done with std::enable_shared_from_this. In the example above, you could do:

var r: cxx.SharedPtr<FooBuilder> = this;

Which will generate this:

class FooBuilder: public std::enable_shared_from_this<FooBuilder> {
public:
	FooBuilder();
	std::shared_ptr<FooBuilder> withBar();

	HX_COMPARISON_OPERATORS(FooBuilder)
};

// ---

std::shared_ptr<FooBuilder> FooBuilder::withBar() {
	std::shared_ptr<FooBuilder> r = this->weak_from_this().expired() ? std::make_shared<FooBuilder>(*this) : this->shared_from_this();

	return r;
}

SomeRanDev avatar Jan 26 '24 11:01 SomeRanDev