Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core: Integrate Ref instantiate where possible #92986

Merged

Conversation

Repiteo
Copy link
Contributor

@Repiteo Repiteo commented Jun 10, 2024

Followup to #88183, which expanded Ref<T>::instantiate() to accept constructor arguments. This PR is focused on converting existing Ref constructors to the shorthand syntax where applicable. Does not convert every instance, as some constructors happen on the same line a Ref is declared; converting these would require a static method, and is more suitable as a separate PR.

@Repiteo Repiteo added this to the 4.x milestone Jun 10, 2024
@Repiteo Repiteo requested review from a team as code owners June 10, 2024 16:01
Copy link
Member

@AThousandShips AThousandShips left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good and improves readability quite substantially

@Repiteo Repiteo force-pushed the core/ref-instantiate-integration branch 2 times, most recently from e2fd2ce to a3e7aa0 Compare June 16, 2024 13:25
@Repiteo Repiteo modified the milestones: 4.x, 4.4 Oct 31, 2024
@Repiteo Repiteo force-pushed the core/ref-instantiate-integration branch from a3e7aa0 to 076fa63 Compare October 31, 2024 17:37
@Repiteo Repiteo requested review from a team as code owners October 31, 2024 17:37
@fire
Copy link
Member

fire commented Oct 31, 2024

I'm curious, we seem to flip between memnew and instantiate. Which one do we pick for reviews?

@Repiteo
Copy link
Contributor Author

Repiteo commented Oct 31, 2024

Ideally, we'd want to use instantiate over memnew where possible. As mentioned in the OP, the only places where that isn't feasible is when it's the same line Ref is declared. That could be solved with a static method along the lines of:

// old
Ref<SomeType> some_value = Ref<SomeType>(memnew(SomeType()));

// new
Ref<SomeType> some_value = Ref<SomeType>::construct();

Initially I wanted to tackle that in a separate PR, but if desired I could integrate it here instead

@Repiteo Repiteo force-pushed the core/ref-instantiate-integration branch from 076fa63 to 789ae99 Compare October 31, 2024 18:44
@Repiteo
Copy link
Contributor Author

Repiteo commented Nov 1, 2024

…Alternatively, if keeping within the initial scope of the PR is desired, there's this:

// old
Ref<SomeType> some_value = Ref<SomeType>(memnew(SomeType()));

// new
Ref<SomeType> some_value;
some_value.instantiate();

I'd say this is still more readable than using memnew, even if it's arguably more verbose. There's already places in the repo utilizing this exact structure, so it wouldn't be unprecedented.

However, this wouldn't remove the need for a static constructor. To demonstrate, here's a scenario where instantiate would hurt readability:

// old
some_function(Ref<SomeType>(memnew(SomeType)));

// new (static)
some_function(Ref<SomeType>::construct());

// new (local)
Ref<SomeType> some_value;
some_value.instantiate();
some_function(some_value);

With all this in mind, I'll probably leave this concept alone for now. Maaaybe I'll sweep for cases that aren't reliant on one-liners, but I'd prefer to keep this PR as simple as possible

@Repiteo Repiteo removed request for a team November 1, 2024 15:18
Copy link
Member

@adamscott adamscott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything seems alright!

@adamscott
Copy link
Member

adamscott commented Nov 4, 2024

…Alternatively, if keeping within the initial scope of the PR is desired, there's this:

// old
Ref<SomeType> some_value = Ref<SomeType>(memnew(SomeType()));

// new
Ref<SomeType> some_value;
some_value.instantiate();

I'd say this is still more readable than using memnew, even if it's arguably more verbose. There's already places in the repo utilizing this exact structure, so it wouldn't be unprecedented.

I'm all for the new behavior. I'm already coding in that way and it does what it says.

However, this wouldn't remove the need for a static constructor. To demonstrate, here's a scenario where instantiate would hurt readability:

// old
some_function(Ref<SomeType>(memnew(SomeType)));

// new (static)
some_function(Ref<SomeType>::construct());

// new (local)
Ref<SomeType> some_value;
some_value.instantiate();
some_function(some_value);

I actually don't agree. I don't think passing a new instance of Ref<> is actually clearer than being explicit.

void my_func() {
    ...
    {
        // The ideal code would scope the ref to deference it ASAP.
        Ref<SomeType> some_value;
        some_value.instantiate();
        some_function(some_value);
    }
    ...
}

Or, we could always make it so that instantiate() returns itself.

void my_func() {
    ...
    {
        Ref<SomeType> some_value;
        some_function(some_value.instantiate());
    }
    ...
}

@Repiteo Repiteo force-pushed the core/ref-instantiate-integration branch from 789ae99 to 925b690 Compare November 10, 2024 19:09
Copy link
Member

@akien-mga akien-mga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

@Repiteo Repiteo merged commit 9be806a into godotengine:master Nov 11, 2024
20 checks passed
@Repiteo Repiteo deleted the core/ref-instantiate-integration branch November 11, 2024 20:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants