Skip to content

Conversation

@Bromeon
Copy link
Member

@Bromeon Bromeon commented Jan 5, 2026

It was possible for user-defined getters and setters to return/accept types that are completely unrelated to the field type.

This PR introduces descriptive compile-time errors, with tweaked spans for beautiful error messages.

Based on #1466.

Example

// in struct:
#[var(get, set)]
field: GString,

// in impl:
#[func]
pub fn get_field(&self) -> i32 { 123 }

#[func]
pub fn set_field(&mut self, value: i32) {}

causes these errors:

image

(Yes, it's not quite symmetric, if someone wants to tweak this further, I'm happy for PRs 🙂)

Breaking change

Previously, having wrong getter/setter types worked as long as they were compatible in Godot subtying terms, e.g. Gd<Derived> -> Gd<Base>, or i32 -> Variant, etc. The new typechecks are now stricter.

There are a few instances where such weak typing was used in itests, possibly deliberately, or possibly due to limitations in early godot-rust.

#[var(get = get_object_val, set = set_object_val)]
object_val: Option<Gd<Object>>,
#[var]
resource_var: OnEditor<Gd<Resource>>,
#[var(get = get_resource_rw, set = set_resource_rw, hint = RESOURCE_TYPE, hint_string = "Resource")]
resource_rw: Option<Gd<Resource>>,
#[var]
packed_int_array: PackedInt32Array,
#[var(pub, rename = renamed_variable)]
unused_name: GString,
}
#[godot_api]
impl HasProperty {
#[func]
pub fn get_object_val(&self) -> Variant {
if let Some(object_val) = self.object_val.as_ref() {
object_val.to_variant()
} else {
Variant::nil()
}
}
#[func]
pub fn set_object_val(&mut self, val: Gd<Object>) {
self.object_val = Some(val);
}
#[func]
pub fn get_resource_rw(&self) -> Variant {
if let Some(resource) = self.resource_rw.as_ref() {
resource.to_variant()
} else {
Variant::nil()
}
}
#[func]
pub fn set_resource_rw(&mut self, val: Gd<Resource>) {
self.resource_rw = Some(val);
}
}

@Bromeon Bromeon added quality-of-life No new functionality, but improves ergonomics/internals c: register Register classes, functions and other symbols to GDScript breaking-change Requires SemVer bump labels Jan 5, 2026
@Bromeon Bromeon force-pushed the qol/var-typechecks branch from 0f48648 to 7fc5593 Compare January 5, 2026 00:36
@GodotRust
Copy link

API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-1469

Comment on lines 202 to 208
/// pub fn set_my_node(&mut self, value: Gd<Node>) {
/// *self.my_node = value;
/// }
///
/// #[func]
/// pub fn get_my_value(&self) -> i32 {
/// self.my_value.get_property()
/// *self.my_value
Copy link
Contributor

Choose a reason for hiding this comment

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

Both won't work in an editor – dereferencing OnEditor will result in panic if value is not set yet (and it can't be set because we can't dereference it...).

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, great remark! So it would also be Var::var_get() here...

I guess we shoukd document this 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, and set should mirror it as well

fn var_get(field: &Self) -> Self::Via {
field
.get_property_inner()
.expect("OnEditor is not nullable")
Copy link
Contributor

@Yarwin Yarwin Jan 5, 2026

Choose a reason for hiding this comment

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

I would change expect message (OnEditor field of given type is not nullable and mustn't be None?)

i.e. leave the information why this expect in var getter is fine.

Copy link
Contributor

@Yarwin Yarwin 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 to me;

PR in general looks intimidating but it is smaller than it seems – bulk of the changes are due to switching from &mut self to field: &mut Self in Var signature (+ blanket impl SimpleVar).

I don't get why docs for OnEditor about setters/getters has been changed though.

@Bromeon
Copy link
Member Author

Bromeon commented Jan 5, 2026

Thanks a lot for the great review! 👍


PR in general looks intimidating but it is smaller than it seems

Yep, as written this is based on #1466 -- maybe I should have linked only the 3 relevant commits (out of 6):


I don't get why docs for OnEditor about setters/getters has been changed though.

I wasn't thinking of the editor case, so I accidentally "simplified" the doctests (they kept passing in unit-tests). Will fix that + add documentation why going through Var is necessary 🧐

Regarding "/// Use the default OnEditor<T> implementation to set/retrieve the value." to me it wasn't clear what the "default implementation" refers to? Maybe just "use Var instead of the Deref" or so?

@Yarwin
Copy link
Contributor

Yarwin commented Jan 5, 2026

Regarding "/// Use the default OnEditor implementation to set/retrieve the value." to me it wasn't clear what the "default implementation" refers to? Maybe just "use Var instead of the Deref" or so?

I think Maybe just "use Var instead of the Deref" or so? should be OKay

@Bromeon Bromeon force-pushed the qol/var-typechecks branch 2 times, most recently from 1d61b2a to da38a98 Compare January 5, 2026 19:48
It was possible for user-defined getters and setters to return/accept types that are
completely unrelated to the field type.

This introduces descriptive compile-time errors, with tweaked spans.
@Bromeon Bromeon force-pushed the qol/var-typechecks branch from da38a98 to 6392fb6 Compare January 5, 2026 19:52
@Bromeon Bromeon added this pull request to the merge queue Jan 5, 2026
Merged via the queue into master with commit db4fc76 Jan 5, 2026
20 checks passed
@Bromeon Bromeon deleted the qol/var-typechecks branch January 5, 2026 22:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change Requires SemVer bump c: register Register classes, functions and other symbols to GDScript quality-of-life No new functionality, but improves ergonomics/internals

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants