Skip to content

Commit ddf30e6

Browse files
fix: ambiguous virtual method calls godot-rust#858
1 parent 97b66ec commit ddf30e6

File tree

5 files changed

+34
-8
lines changed

5 files changed

+34
-8
lines changed

godot-macros/src/class/data_models/field_var.rs

+1
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ impl GetterSetterImpl {
221221
is_script_virtual: false,
222222
rpc_info: None,
223223
},
224+
None,
224225
);
225226

226227
let export_token = export_token.expect("getter/setter generation should not fail");

godot-macros/src/class/data_models/func.rs

+21-4
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@ pub fn make_virtual_callback(
3838
class_name: &Ident,
3939
signature_info: &SignatureInfo,
4040
before_kind: BeforeKind,
41+
interface_trait: Option<&venial::TypeExpr>,
4142
) -> TokenStream {
4243
let method_name = &signature_info.method_name;
4344

44-
let wrapped_method = make_forwarding_closure(class_name, signature_info, before_kind);
45+
let wrapped_method =
46+
make_forwarding_closure(class_name, signature_info, before_kind, interface_trait);
4547
let sig_tuple = signature_info.tuple_type();
4648

4749
let call_ctx = make_call_context(
@@ -75,6 +77,7 @@ pub fn make_virtual_callback(
7577
pub fn make_method_registration(
7678
class_name: &Ident,
7779
func_definition: FuncDefinition,
80+
interface_trait: Option<&venial::TypeExpr>,
7881
) -> ParseResult<TokenStream> {
7982
let signature_info = &func_definition.signature_info;
8083
let sig_tuple = signature_info.tuple_type();
@@ -85,8 +88,12 @@ pub fn make_method_registration(
8588
Err(msg) => return bail_fn(msg, &signature_info.method_name),
8689
};
8790

88-
let forwarding_closure =
89-
make_forwarding_closure(class_name, signature_info, BeforeKind::Without);
91+
let forwarding_closure = make_forwarding_closure(
92+
class_name,
93+
signature_info,
94+
BeforeKind::Without,
95+
interface_trait,
96+
);
9097

9198
// String literals
9299
let method_name = &signature_info.method_name;
@@ -209,6 +216,7 @@ fn make_forwarding_closure(
209216
class_name: &Ident,
210217
signature_info: &SignatureInfo,
211218
before_kind: BeforeKind,
219+
interface_trait: Option<&venial::TypeExpr>,
212220
) -> TokenStream {
213221
let method_name = &signature_info.method_name;
214222
let params = &signature_info.param_idents;
@@ -238,7 +246,16 @@ fn make_forwarding_closure(
238246
let method_call = if matches!(before_kind, BeforeKind::OnlyBefore) {
239247
TokenStream::new()
240248
} else {
241-
quote! { instance.#method_name( #(#params),* ) }
249+
match interface_trait {
250+
Some(interface_trait) => {
251+
let instance_ref = match signature_info.receiver_type {
252+
ReceiverType::Mut => quote! { &mut instance },
253+
_ => quote! { &instance },
254+
};
255+
quote! { <#class_name as #interface_trait>::#method_name( #instance_ref, #(#params),* ) }
256+
}
257+
None => quote! { instance.#method_name( #(#params),* ) },
258+
}
242259
};
243260

244261
quote! {

godot-macros/src/class/data_models/inherent_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ pub fn transform_inherent_impl(
9898

9999
let method_registrations: Vec<TokenStream> = funcs
100100
.into_iter()
101-
.map(|func_def| make_method_registration(&class_name, func_def))
101+
.map(|func_def| make_method_registration(&class_name, func_def, None))
102102
.collect::<ParseResult<Vec<TokenStream>>>()?;
103103

104104
let constant_registration = make_constant_registration(consts, &class_name, &class_name_obj)?;

godot-macros/src/class/data_models/interface_trait_impl.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ pub fn transform_trait_impl(original_impl: venial::Impl) -> ParseResult<TokenStr
246246
hash_constant: quote! { hashes::#method_name_ident },
247247
signature_info,
248248
before_kind,
249+
interface_trait: Some(trait_path.clone()),
249250
});
250251
}
251252
}
@@ -266,6 +267,7 @@ pub fn transform_trait_impl(original_impl: venial::Impl) -> ParseResult<TokenStr
266267
hash_constant: quote! { ::godot::sys::known_virtual_hashes::Node::ready },
267268
signature_info: SignatureInfo::fn_ready(),
268269
before_kind: BeforeKind::OnlyBefore,
270+
interface_trait: None,
269271
};
270272

271273
overridden_virtuals.push(match_arm);
@@ -366,6 +368,7 @@ struct OverriddenVirtualFn<'a> {
366368
hash_constant: TokenStream,
367369
signature_info: SignatureInfo,
368370
before_kind: BeforeKind,
371+
interface_trait: Option<venial::TypeExpr>,
369372
}
370373

371374
impl OverriddenVirtualFn<'_> {
@@ -383,8 +386,12 @@ impl OverriddenVirtualFn<'_> {
383386
let pattern = method_name_str;
384387

385388
// Lazily generate code for the actual work (calling user function).
386-
let method_callback =
387-
make_virtual_callback(class_name, &self.signature_info, self.before_kind);
389+
let method_callback = make_virtual_callback(
390+
class_name,
391+
&self.signature_info,
392+
self.before_kind,
393+
self.interface_trait.as_ref(),
394+
);
388395

389396
quote! {
390397
#(#cfg_attrs)*

godot-macros/src/class/derive_godot_class.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,8 @@ fn make_user_class_impl(
279279
let tool_check = util::make_virtual_tool_check();
280280
let signature_info = SignatureInfo::fn_ready();
281281

282-
let callback = make_virtual_callback(class_name, &signature_info, BeforeKind::OnlyBefore);
282+
let callback =
283+
make_virtual_callback(class_name, &signature_info, BeforeKind::OnlyBefore, None);
283284

284285
// See also __virtual_call() codegen.
285286
// This doesn't explicitly check if the base class inherits from Node (and thus has `_ready`), but the derive-macro already does

0 commit comments

Comments
 (0)