Skip to content

Commit e9185cc

Browse files
authored
Merge branch 'master' into jovan/script_instance_mut_wrapper
2 parents 6b3c3c9 + ed88b6f commit e9185cc

File tree

26 files changed

+127
-30
lines changed

26 files changed

+127
-30
lines changed

.github/composite/rust/action.yml

+14-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ runs:
3434
id: configure
3535
env:
3636
CS: ${{ inputs.components }}
37+
# TODO use actual Rust version, e.g. 1.78 in cache, not just "stable"
3738
run: |
3839
echo "Rust cache shared-key: '${{ runner.os }}-${{ inputs.rust }}${{ inputs.cache-key }}'"
3940
echo "components=$( for c in ${CS//,/ }; do echo -n ' --component' $c; done )" >> $GITHUB_OUTPUT
@@ -48,12 +49,24 @@ runs:
4849
rustup default ${{ inputs.rust }}
4950
shell: bash
5051

52+
- name: "Extract Rust version"
53+
# Transforms into format "1.78.0-stable" or "1.80.0-nightly-d2d24e395", which can be used as cache key.
54+
run: |
55+
version=$(rustc --version)
56+
if echo "$version" | grep -q "nightly"; then
57+
version=$(echo "$version" | sed -E 's/rustc ([0-9]+\.[0-9]+\.[0-9]+)-nightly \(([a-f0-9]+) .*/\1-nightly-\2/')
58+
else
59+
version=$(echo "$version" | sed -E 's/rustc ([0-9]+\.[0-9]+\.[0-9]+) .*/\1-stable/')
60+
fi
61+
echo "INSTALLED_RUST_VERSION=$version" >> $GITHUB_ENV
62+
shell: bash
63+
5164
- name: "Reuse cached dependencies"
5265
uses: Swatinem/rust-cache@v2
5366
with:
5467
# A cache key that is used instead of the automatic `job`-based key, and is stable over multiple jobs.
5568
# default: empty
56-
shared-key: "${{ runner.os }}-${{ inputs.rust }}${{ inputs.cache-key }}"
69+
shared-key: "${{ runner.os }}-${{ env.INSTALLED_RUST_VERSION }}${{ inputs.cache-key }}"
5770

5871
# An additional cache key that is added alongside the automatic `job`-based
5972
# cache key and can be used to further differentiate jobs.

.github/workflows/full-ci.yml

+2-3
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,9 @@ jobs:
5858
- name: "Patch Cargo.toml to use nightly extension API"
5959
run: .github/other/patch-prebuilt.sh nightly
6060

61+
# rustdoc is included as component.
6162
- name: "Install Rust"
6263
uses: ./.github/composite/rust
63-
with:
64-
components: rustdoc
6564

6665
- name: "Check rustdoc"
6766
env:
@@ -127,7 +126,7 @@ jobs:
127126

128127
- name: linux
129128
os: ubuntu-20.04
130-
rust-toolchain: "1.77.1"
129+
rust-toolchain: "1.78"
131130
rust-special: -msrv
132131

133132
steps:

.github/workflows/minimal-ci.yml

+1-2
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,9 @@ jobs:
5959
steps:
6060
- uses: actions/checkout@v4
6161

62+
# rustdoc is included as component.
6263
- name: "Install Rust"
6364
uses: ./.github/composite/rust
64-
with:
65-
components: rustdoc
6665

6766
- name: "Check rustdoc"
6867
env:

.github/workflows/update-docs.yml

+15
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ on:
1717
branches:
1818
- master
1919

20+
env:
21+
# Keep this a variable for easy search&replace.
22+
MSRV: 1.78
2023

2124
jobs:
2225
notify-docs:
@@ -26,6 +29,18 @@ jobs:
2629
- name: "Checkout"
2730
uses: actions/checkout@v4
2831

32+
# If Rust version is below msrv, install latest stable.
33+
- name: "Install Rust"
34+
run: |
35+
# Get middle part of version, e.g. 78 from 1.78.0
36+
isMinorVer=$(rustc --version | sed -E 's/rustc [0-9]+\.([0-9]+)\..*/\1/')
37+
shouldMinorVer=$(echo $MSRV | sed -E 's/[0-9]+\.([0-9]+)(\.|$).*/\1/')
38+
39+
if [ $isMinorVer -lt $shouldMinorVer ]; then
40+
echo "Rust version is below MSRV; install latest stable..."
41+
rustup update stable
42+
fi
43+
2944
# This is just a sanity check to make sure that the follow-up docs generation doesn't break.
3045
# So we use the Rust version provided by the GitHub runners, which hopefully is >= MSRV.
3146
- name: "Compile"

examples/dodge-the-creeps/rust/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "dodge-the-creeps"
33
version = "0.1.0"
44
edition = "2021"
5-
rust-version = "1.77.1"
5+
rust-version = "1.78"
66
license = "MPL-2.0"
77
publish = false
88

godot-bindings/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "godot-bindings"
33
version = "0.1.0"
44
edition = "2021"
5-
rust-version = "1.77.1"
5+
rust-version = "1.78"
66
license = "MPL-2.0"
77
keywords = ["gamedev", "godot", "engine", "ffi", "sys"]
88
categories = ["game-engines", "graphics"]

godot-cell/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "godot-cell"
33
version = "0.1.0"
44
edition = "2021"
5-
rust-version = "1.77.1"
5+
rust-version = "1.78"
66
license = "MPL-2.0"
77
keywords = ["gamedev", "godot", "engine", "ffi"]
88
categories = ["game-engines", "graphics"]

godot-codegen/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "godot-codegen"
33
version = "0.1.0"
44
edition = "2021"
5-
rust-version = "1.77.1"
5+
rust-version = "1.78"
66
license = "MPL-2.0"
77
keywords = ["gamedev", "godot", "engine", "codegen"]
88
categories = ["game-engines", "graphics"]

godot-core/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "godot-core"
33
version = "0.1.0"
44
edition = "2021"
5-
rust-version = "1.77.1"
5+
rust-version = "1.78"
66
license = "MPL-2.0"
77
keywords = ["gamedev", "godot", "engine", "2d", "3d"] # possibly: "ffi"
88
categories = ["game-engines", "graphics"]

godot-core/src/builtin/array.rs

+5
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ impl_builtin_froms!(VariantArray;
9090
PackedVector3Array => array_from_packed_vector3_array,
9191
);
9292

93+
#[cfg(since_api = "4.3")]
94+
impl_builtin_froms!(VariantArray;
95+
PackedVector4Array => array_from_packed_vector4_array,
96+
);
97+
9398
impl<T: ArrayElement> Array<T> {
9499
fn from_opaque(opaque: sys::types::OpaqueArray) -> Self {
95100
// Note: type is not yet checked at this point, because array has not yet been initialized!

godot-core/src/builtin/dictionary.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ impl<'a> DictionaryIter<'a> {
412412
self.next_idx += 1;
413413
}
414414

415-
self.last_key = new_key.clone();
415+
self.last_key.clone_from(&new_key);
416416
new_key
417417
}
418418

godot-core/src/builtin/meta/godot_convert/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ use super::{GodotFfiVariant, GodotType};
2121
///
2222
/// [`GodotType`] is a stronger bound than [`GodotConvert`], since it expresses that a type is _directly_ representable
2323
/// in Godot (without intermediate "via"). Every `GodotType` also implements `GodotConvert` with `Via = Self`.
24+
25+
#[diagnostic::on_unimplemented(
26+
message = "`GodotConvert` is needed for `#[func]` parameters/returns, as well as `#[var]` and `#[export]` properties",
27+
note = "check following errors for more information"
28+
)]
2429
pub trait GodotConvert {
2530
/// The type through which `Self` is represented in Godot.
2631
type Via: GodotType;

godot-core/src/builtin/meta/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ mod sealed {
6969
impl Sealed for PackedStringArray {}
7070
impl Sealed for PackedVector2Array {}
7171
impl Sealed for PackedVector3Array {}
72+
#[cfg(since_api = "4.3")]
73+
impl Sealed for PackedVector4Array {}
7274
impl Sealed for PackedColorArray {}
7375
impl Sealed for Plane {}
7476
impl Sealed for Projection {}
@@ -251,6 +253,11 @@ where
251253
/// Notable differences are:
252254
/// - Only `VariantArray`, not `Array<T>` is allowed (typed arrays cannot be nested).
253255
/// - `Option` is only supported for `Option<Gd<T>>`, but not e.g. `Option<i32>`.
256+
#[diagnostic::on_unimplemented(
257+
message = "`Array<T>` can only store element types supported in Godot arrays (no nesting).",
258+
label = "does not implement `Var`",
259+
note = "see also: https://godot-rust.github.io/docs/gdext/master/godot/builtin/meta/trait.ArrayElement.html"
260+
)]
254261
pub trait ArrayElement: GodotType {}
255262

256263
// ----------------------------------------------------------------------------------------------------------------------------------------------

godot-core/src/builtin/meta/signature.rs

+1-12
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ macro_rules! impl_varcall_signature_for_tuple {
142142
#[allow(unused_variables)]
143143
impl<$R, $($Pn,)*> VarcallSignatureTuple for ($R, $($Pn,)*)
144144
where
145-
$R: ToGodot + FromGodot + FromVariantIndirect + Debug,
145+
$R: ToGodot + FromGodot + Debug,
146146
$(
147147
$Pn: ToGodot + FromGodot + Debug,
148148
)*
@@ -559,17 +559,6 @@ fn return_error<R>(call_ctx: &CallContext, err: ConvertError) -> ! {
559559
panic!("in function `{call_ctx}` at return type {return_ty}: {err}");
560560
}
561561

562-
/// Helper trait to support `()` which doesn't implement `FromVariant`.
563-
trait FromVariantIndirect {
564-
fn convert(variant: Variant) -> Self;
565-
}
566-
567-
impl<T: FromGodot> FromVariantIndirect for T {
568-
fn convert(variant: Variant) -> Self {
569-
T::from_variant(&variant)
570-
}
571-
}
572-
573562
unsafe fn new_from_ptrcall<T: FromGodot>(
574563
process_return_ptr: impl FnOnce(sys::GDExtensionTypePtr),
575564
) -> Result<T, ConvertError> {

godot-core/src/builtin/packed_array.rs

+19
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,25 @@ impl_packed_array!(
687687
},
688688
);
689689

690+
#[cfg(since_api = "4.3")]
691+
impl_packed_array!(
692+
type_name: PackedVector4Array,
693+
element_type: Vector4,
694+
opaque_type: OpaquePackedVector4Array,
695+
inner_type: InnerPackedVector4Array,
696+
argument_type: Vector4,
697+
return_type: __GdextType,
698+
from_array: packed_vector4_array_from_array,
699+
operator_index: packed_vector4_array_operator_index,
700+
operator_index_const: packed_vector4_array_operator_index_const,
701+
trait_impls: {
702+
Default => packed_vector4_array_construct_default;
703+
Clone => packed_vector4_array_construct_copy;
704+
Drop => packed_vector4_array_destroy;
705+
PartialEq => packed_vector4_array_operator_equal;
706+
},
707+
);
708+
690709
impl_packed_array!(
691710
type_name: PackedColorArray,
692711
element_type: Color,

godot-core/src/builtin/variant/impls.rs

+2
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ mod impls {
135135
impl_ffi_variant!(PackedStringArray, packed_string_array_to_variant, packed_string_array_from_variant);
136136
impl_ffi_variant!(PackedVector2Array, packed_vector2_array_to_variant, packed_vector2_array_from_variant);
137137
impl_ffi_variant!(PackedVector3Array, packed_vector3_array_to_variant, packed_vector3_array_from_variant);
138+
#[cfg(since_api = "4.3")]
139+
impl_ffi_variant!(PackedVector4Array, packed_vector4_array_to_variant, packed_vector4_array_from_variant);
138140
impl_ffi_variant!(PackedColorArray, packed_color_array_to_variant, packed_color_array_from_variant);
139141
impl_ffi_variant!(Plane, plane_to_variant, plane_from_variant);
140142
impl_ffi_variant!(Projection, projection_to_variant, projection_from_variant);

godot-core/src/obj/traits.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ use godot_ffi as sys;
2020
///
2121
/// Normally, you don't need to implement this trait yourself; use [`#[derive(GodotClass)]`](../register/derive.GodotClass.html) instead.
2222
// Above intra-doc link to the derive-macro only works as HTML, not as symbol link.
23+
#[diagnostic::on_unimplemented(
24+
message = "Only classes registered with Godot are allowed in this context",
25+
note = "you can use `#[derive(GodotClass)]` to register your own structs with Godot",
26+
note = "see also: https://godot-rust.github.io/book/register/classes.html"
27+
)]
2328
pub trait GodotClass: Bounds + 'static
2429
where
2530
Self: Sized,
@@ -206,6 +211,12 @@ pub trait IndexEnum: EngineEnum {
206211
///
207212
/// Gives direct access to the containing `Gd<Self>` from `Self`.
208213
// Possible alternative for builder APIs, although even less ergonomic: Base<T> could be Base<T, Self> and return Gd<Self>.
214+
#[diagnostic::on_unimplemented(
215+
message = "Class `{Self}` requires a `Base<T>` field",
216+
label = "missing field `_base: Base<...>`",
217+
note = "A base field is required to access the base from within `self`, or when using script virtual functions",
218+
note = "see also: https://godot-rust.github.io/book/register/classes.html#the-base-field"
219+
)]
209220
pub trait WithBaseField: GodotClass + Bounds<Declarer = bounds::DeclUser> {
210221
/// Returns the `Gd` pointer containing this object.
211222
///
@@ -243,7 +254,7 @@ pub trait WithBaseField: GodotClass + Bounds<Declarer = bounds::DeclUser> {
243254
/// # unsafe impl ExtensionLibrary for Test {}
244255
/// ```
245256
///
246-
/// However we cannot call methods that require `&mut Base`, such as
257+
/// However, we cannot call methods that require `&mut Base`, such as
247258
/// [`Node::add_child()`](crate::engine::Node::add_child).
248259
///
249260
/// ```compile_fail
@@ -423,6 +434,13 @@ pub mod cap {
423434
/// This trait is not manually implemented, and you cannot call any methods. You can use it as a bound, but typically you'd use
424435
/// it indirectly through [`Gd::default()`][crate::obj::Gd::default()]. Note that `Gd::default()` has an additional requirement on
425436
/// being reference-counted, meaning not every `GodotDefault` class can automatically be used with `Gd::default()`.
437+
#[diagnostic::on_unimplemented(
438+
message = "Class `{Self}` requires either an `init` constructor, or explicit opt-out",
439+
label = "needs `init`",
440+
note = "To provide a default constructor, use `#[class(init)]` or implement an `init` method",
441+
note = "To opt out, use `#[class(no_init)]`",
442+
note = "see also: https://godot-rust.github.io/book/register/constructors.html"
443+
)]
426444
pub trait GodotDefault: GodotClass {
427445
/// Provides a default smart pointer instance.
428446
///

godot-core/src/private.rs

+5
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ pub(crate) fn iterate_plugins(mut visitor: impl FnMut(&ClassPlugin)) {
9797

9898
// If someone forgets #[godot_api], this causes a compile error, rather than virtual functions not being called at runtime.
9999
#[allow(non_camel_case_types)]
100+
#[diagnostic::on_unimplemented(
101+
message = "`impl` blocks for Godot classes require the `#[godot_api]` attribute",
102+
label = "missing `#[godot_api]` before `impl`",
103+
note = "see also: https://godot-rust.github.io/book/register/functions.html#godot-special-functions"
104+
)]
100105
pub trait You_forgot_the_attribute__godot_api {}
101106

102107
pub struct ClassConfig {

godot-core/src/property.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ use crate::engine::global::PropertyHint;
2121
///
2222
/// This does not require [`FromGodot`] or [`ToGodot`], so that something can be used as a property even if it can't be used in function
2323
/// arguments/return types.
24+
25+
// We also mention #[export] here, because we can't control the order of error messages. Missing Export often also means missing Var trait,
26+
// and so the Var error message appears first.
27+
#[diagnostic::on_unimplemented(
28+
message = "`#[var]` properties require `Var` trait; #[export] ones require `Export` trait",
29+
label = "type cannot be used as a property",
30+
note = "see also: https://godot-rust.github.io/book/register/properties.html"
31+
)]
2432
pub trait Var: GodotConvert {
2533
fn get_property(&self) -> Self::Via;
2634
fn set_property(&mut self, value: Self::Via);
@@ -31,6 +39,12 @@ pub trait Var: GodotConvert {
3139
}
3240

3341
/// Trait implemented for types that can be used as `#[export]` fields.
42+
// Mentioning both Var + Export: see above.
43+
#[diagnostic::on_unimplemented(
44+
message = "`#[var]` properties require `Var` trait; #[export] ones require `Export` trait",
45+
label = "type cannot be used as a property",
46+
note = "see also: https://godot-rust.github.io/book/register/properties.html"
47+
)]
3448
pub trait Export: Var {
3549
/// The export info to use for an exported field of this type, if no other export info is specified.
3650
fn default_export_info() -> PropertyHintInfo;
@@ -351,7 +365,7 @@ mod export_impls {
351365
(@type_string_hint $Ty:ty) => {
352366
impl TypeStringHint for $Ty {
353367
fn type_string() -> String {
354-
use sys::GodotFfi;
368+
use sys::GodotFfi as _;
355369
let variant_type = <$Ty as $crate::builtin::meta::GodotType>::Ffi::variant_type();
356370
let type_name = <$Ty as $crate::builtin::meta::GodotType>::godot_type_name();
357371
format!("{}:{}", variant_type as i32, type_name)
@@ -400,6 +414,8 @@ mod export_impls {
400414
impl_property_by_godot_convert!(PackedStringArray, no_export);
401415
impl_property_by_godot_convert!(PackedVector2Array, no_export);
402416
impl_property_by_godot_convert!(PackedVector3Array, no_export);
417+
#[cfg(since_api = "4.3")]
418+
impl_property_by_godot_convert!(PackedVector4Array, no_export);
403419
impl_property_by_godot_convert!(PackedColorArray, no_export);
404420

405421
// Primitives

godot-ffi/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "godot-ffi"
33
version = "0.1.0"
44
edition = "2021"
5-
rust-version = "1.77.1"
5+
rust-version = "1.78"
66
license = "MPL-2.0"
77
keywords = ["gamedev", "godot", "engine", "ffi"]
88
categories = ["game-engines", "graphics"]

godot-ffi/src/extras.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use crate::VariantType;
1414
// Static checks
1515

1616
// The impls only compile if those are different types -- ensures type safety through patch
17+
#[allow(dead_code)]
1718
trait Distinct {}
1819
impl Distinct for GDExtensionVariantPtr {}
1920
impl Distinct for GDExtensionTypePtr {}

godot-ffi/src/toolbox.rs

+2
Original file line numberDiff line numberDiff line change
@@ -193,12 +193,14 @@ pub fn unqualified_type_name<T>() -> &'static str {
193193
pub(crate) trait Inner: Sized {
194194
type FnPtr: Sized;
195195

196+
#[cfg(before_api = "4.1")]
196197
fn extract(self, error_msg: &str) -> Self::FnPtr;
197198
}
198199

199200
impl<T> Inner for Option<T> {
200201
type FnPtr = T;
201202

203+
#[cfg(before_api = "4.1")]
202204
fn extract(self, error_msg: &str) -> Self::FnPtr {
203205
self.expect(error_msg)
204206
}

0 commit comments

Comments
 (0)