Skip to content

Commit c3f5fe8

Browse files
committed
Deprecated return by reference
The ways of emit warnings is a terrible hack. This is because there is no way to emit warnings from macros in stable Rust. Follow these steps to emit warnings. - Detect whether reference types are used in derive_methods(). - Expand the call to deprecated_reference_return!() macro to user code.
1 parent 552b7a8 commit c3f5fe8

File tree

4 files changed

+37
-16
lines changed

4 files changed

+37
-16
lines changed

gdnative-core/src/export/macros.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ macro_rules! godot_wrap_method_if_deref {
2222
};
2323
}
2424

25+
#[doc(hidden)]
26+
#[macro_export]
27+
#[deprecated = "This function does not actually pass by reference to the Godot engine. You can clarify by writing #[export(deref_return)]."]
28+
macro_rules! deprecated_reference_return {
29+
() => {};
30+
}
31+
2532
#[doc(hidden)]
2633
#[macro_export]
2734
macro_rules! godot_wrap_method_inner {

gdnative-core/src/export/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ pub(crate) mod type_tag;
2626

2727
pub mod user_data;
2828

29+
#[allow(deprecated)]
30+
pub use crate::deprecated_reference_return;
2931
pub use crate::godot_wrap_method;
3032
pub use class::*;
3133
pub use class_builder::*;

gdnative-derive/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ mod variant;
5050
/// impl gdnative::export::NativeClassMethods for Foo {
5151
/// fn register(builder: &ClassBuilder<Self>) {
5252
/// use gdnative::export::*;
53-
/// builder.method("foo", gdnative::export::godot_wrap_method!(Foo, fn foo(&self, _owner: &Reference, bar: i64) -> i64))
53+
/// builder.method("foo", gdnative::export::godot_wrap_method!(Foo, false, fn foo(&self, _owner: &Reference, bar: i64) -> i64))
5454
/// .with_rpc_mode(RpcMode::Disabled)
5555
/// .done_stateless();
5656
/// }

gdnative-derive/src/methods.rs

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub(crate) fn derive_methods(item_impl: ItemImpl) -> TokenStream2 {
8686
let name = sig.ident;
8787
let name_string = args.name_override.unwrap_or_else(|| name.to_string());
8888
let ret_span = sig.output.span();
89-
let ret_ty = match sig.output {
89+
let ret_ty = match &sig.output {
9090
syn::ReturnType::Default => quote_spanned!(ret_span => ()),
9191
syn::ReturnType::Type(_, ty) => quote_spanned!( ret_span => #ty ),
9292
};
@@ -128,6 +128,16 @@ pub(crate) fn derive_methods(item_impl: ItemImpl) -> TokenStream2 {
128128
}
129129
});
130130

131+
let deprecated = if let syn::ReturnType::Type(_, ty) = &sig.output {
132+
if !is_deref_return && matches!(**ty, syn::Type::Reference(_)) {
133+
quote_spanned!(ret_span=> ::gdnative::export::deprecated_reference_return!();)
134+
} else {
135+
quote_spanned!(ret_span=>)
136+
}
137+
} else {
138+
quote_spanned!(ret_span=>)
139+
};
140+
131141
quote_spanned!( sig_span=>
132142
{
133143
let method = ::gdnative::export::godot_wrap_method!(
@@ -139,6 +149,8 @@ pub(crate) fn derive_methods(item_impl: ItemImpl) -> TokenStream2 {
139149
#builder.method(#name_string, method)
140150
.with_rpc_mode(#rpc)
141151
.done_stateless();
152+
153+
#deprecated
142154
}
143155
)
144156
})
@@ -204,19 +216,19 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
204216
let _export_args = export_args.get_or_insert_with(ExportArgs::default);
205217
use syn::{punctuated::Punctuated, Lit, Meta, NestedMeta};
206218
let nested_meta_iter = match attr.parse_meta() {
207-
Err(err) => {
208-
errors.push(err);
209-
return false;
210-
}
219+
Err(err) => {
220+
errors.push(err);
221+
return false;
222+
}
211223
Ok(Meta::NameValue(name_value)) => {
212224
let span = name_value.span();
213225
let msg = "NameValue syntax is not valid";
214-
errors.push(syn::Error::new(span, msg));
226+
errors.push(syn::Error::new(span, msg));
215227
return false;
216-
}
228+
}
217229
Ok(Meta::Path(_)) => {
218230
Punctuated::<NestedMeta, syn::token::Comma>::new().into_iter()
219-
}
231+
}
220232
Ok(Meta::List(list)) => list.nested.into_iter(),
221233
};
222234
for nested_meta in nested_meta_iter {
@@ -239,15 +251,15 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
239251
(&name_value.path, Some(&name_value.lit))
240252
}
241253
},
242-
};
254+
};
243255
if path.is_ident("rpc") {
244-
// rpc mode
256+
// rpc mode
245257
match lit {
246258
None => {
247-
errors.push(syn::Error::new(
259+
errors.push(syn::Error::new(
248260
nested_meta.span(),
249261
"name parameter requires string value",
250-
));
262+
));
251263
}
252264
Some(Lit::Str(str)) => {
253265
let value = str.value();
@@ -273,13 +285,13 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
273285
}
274286
}
275287
} else if path.is_ident("name") {
276-
// name override
288+
// name override
277289
match lit {
278290
None => {
279-
errors.push(syn::Error::new(
291+
errors.push(syn::Error::new(
280292
nested_meta.span(),
281293
"name parameter requires string value",
282-
));
294+
));
283295
}
284296
Some(Lit::Str(str)) => {
285297
if name_override.replace(str.value()).is_some() {

0 commit comments

Comments
 (0)