Skip to content

Commit f10ad4c

Browse files
committed
refactor errors considerably
1 parent 85f2e9e commit f10ad4c

File tree

15 files changed

+1254
-820
lines changed

15 files changed

+1254
-820
lines changed

assets/scripts/bevy_api.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function on_event()
2222

2323
print("\noption")
2424
-- print(comp:get("option_usize"))
25-
print(comp.option_usize)
25+
print(comp.option_usie)
2626
comp.option_usize = 69
2727
print(comp.option_usize)
2828
comp.option_usize = nil

crates/bevy_mod_scripting_core/src/asset.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ impl AssetLoader for ScriptAssetLoader {
4444
load_context: &mut bevy::asset::LoadContext<'_>,
4545
) -> Result<Self::Asset, Self::Error> {
4646
let mut content = Vec::new();
47-
reader.read_to_end(&mut content).await.map_err(|e| {
48-
ScriptError::new_lifecycle_error(e).with_context(load_context.asset_path())
49-
})?;
47+
reader
48+
.read_to_end(&mut content)
49+
.await
50+
.map_err(|e| ScriptError::new_error(e).with_context(load_context.asset_path()))?;
5051
if let Some(processor) = &self.preprocessor {
5152
processor(&mut content)?;
5253
}

crates/bevy_mod_scripting_core/src/bindings/function.rs

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ use std::{any::TypeId, borrow::Cow, ops::Deref, sync::Arc};
33
use bevy::reflect::{
44
func::{
55
args::{Arg, ArgInfo, Ownership},
6-
ArgList, ArgValue, DynamicFunction, FunctionResult, Return,
6+
ArgList, ArgValue, DynamicFunction, FunctionInfo, FunctionResult, Return,
77
},
88
PartialReflect,
99
};
1010

11-
use crate::error::{ScriptError, ScriptResult, ValueConversionError};
11+
use crate::error::{InteropError, ScriptError, ScriptResult};
1212

1313
use super::{
1414
access_map::ReflectAccessId,
@@ -26,19 +26,13 @@ pub trait CallableWithAccess {
2626
args: I,
2727
world: Arc<WorldAccessGuard>,
2828
f: F,
29-
) -> ScriptResult<O>;
29+
) -> Result<O, InteropError>;
3030

3131
fn dynamic_call<I: IntoIterator<Item = ScriptValue>>(
3232
&self,
3333
args: I,
3434
world: Arc<WorldAccessGuard>,
35-
) -> ScriptResult<ScriptValue> {
36-
self.with_call(args, world.clone(), |r| match r {
37-
Return::Owned(partial_reflect) => partial_reflect.as_ref().into_script_value(world),
38-
Return::Ref(ref_) => ref_.into_script_value(world),
39-
Return::Mut(mut_ref) => mut_ref.into_script_value(world),
40-
})?
41-
}
35+
) -> Result<ScriptValue, InteropError>;
4236
}
4337

4438
impl CallableWithAccess for DynamicFunction<'_> {
@@ -47,7 +41,7 @@ impl CallableWithAccess for DynamicFunction<'_> {
4741
args: I,
4842
world: Arc<WorldAccessGuard>,
4943
f: F,
50-
) -> ScriptResult<O> {
44+
) -> Result<O, InteropError> {
5145
let info = self.info().args();
5246

5347
// We need to:
@@ -68,9 +62,9 @@ impl CallableWithAccess for DynamicFunction<'_> {
6862
{
6963
std::iter::once(ScriptValue::World)
7064
.chain(arg_iter)
71-
.into_args_list_with_access(info, world.clone())?
65+
.into_args_list_with_access(self.info(), world.clone())?
7266
} else {
73-
arg_iter.into_args_list_with_access(info, world.clone())?
67+
arg_iter.into_args_list_with_access(self.info(), world.clone())?
7468
};
7569

7670
let mut final_args_list = ArgList::default();
@@ -101,7 +95,7 @@ impl CallableWithAccess for DynamicFunction<'_> {
10195
unsafe { world.release_access(id) };
10296
});
10397

104-
return Err(e.into());
98+
return Err(InteropError::function_call_error(e));
10599
}
106100
};
107101

@@ -114,6 +108,19 @@ impl CallableWithAccess for DynamicFunction<'_> {
114108

115109
Ok(out)
116110
}
111+
112+
fn dynamic_call<I: IntoIterator<Item = ScriptValue>>(
113+
&self,
114+
args: I,
115+
world: Arc<WorldAccessGuard>,
116+
) -> Result<ScriptValue, InteropError> {
117+
self.with_call(args, world.clone(), |r| match r {
118+
Return::Owned(partial_reflect) => partial_reflect.as_ref().into_script_value(world),
119+
Return::Ref(ref_) => ref_.into_script_value(world),
120+
Return::Mut(mut_ref) => mut_ref.into_script_value(world),
121+
})?
122+
.map_err(|e| InteropError::function_interop_error(self.info(), None, e).into())
123+
}
117124
}
118125

119126
/// Trait implementable by lists of things representing arguments which can be converted into an `ArgList`.
@@ -122,9 +129,9 @@ impl CallableWithAccess for DynamicFunction<'_> {
122129
pub trait IntoArgsListWithAccess {
123130
fn into_args_list_with_access<'w>(
124131
self,
125-
arg_info: &[ArgInfo],
132+
function_info: &FunctionInfo,
126133
world: WorldGuard<'w>,
127-
) -> ScriptResult<(Vec<ArgValue<'w>>, Vec<(ReflectAccessId, Ownership)>)>;
134+
) -> Result<(Vec<ArgValue<'w>>, Vec<(ReflectAccessId, Ownership)>), InteropError>;
128135
}
129136

130137
impl<I: Iterator<Item = ScriptValue>> IntoArgsListWithAccess for I {
@@ -134,9 +141,10 @@ impl<I: Iterator<Item = ScriptValue>> IntoArgsListWithAccess for I {
134141
/// Meaning that only after releasing access is it possible to create unsafe aliases
135142
fn into_args_list_with_access<'w>(
136143
self,
137-
arg_info: &[ArgInfo],
144+
function_info: &FunctionInfo,
138145
world: WorldGuard<'w>,
139-
) -> ScriptResult<(Vec<ArgValue<'w>>, Vec<(ReflectAccessId, Ownership)>)> {
146+
) -> Result<(Vec<ArgValue<'w>>, Vec<(ReflectAccessId, Ownership)>), InteropError> {
147+
let arg_info = function_info.args();
140148
let mut accesses = Vec::default();
141149
let mut arg_list = Vec::default();
142150

@@ -147,23 +155,23 @@ impl<I: Iterator<Item = ScriptValue>> IntoArgsListWithAccess for I {
147155
});
148156
};
149157

150-
for (value, arg_info) in self.zip(arg_info.iter()) {
158+
for (value, argument_info) in self.zip(arg_info.iter()) {
151159
match value {
152160
// TODO: I'd see the logic be a bit cleaner, this if is needed to support 'Raw' ScriptValue arguments
153161
// as we do not want to claim any access since we're not using the value yet
154162
ScriptValue::Reference(arg_ref)
155-
if arg_info.type_id() != TypeId::of::<ScriptValue>() =>
163+
if argument_info.type_id() != TypeId::of::<ScriptValue>() =>
156164
{
157-
let access_id =
158-
ReflectAccessId::for_reference(arg_ref.base.base_id.clone()).ok_or_else(|| {
159-
ScriptError::new_reflection_error(format!(
160-
"Could not call function, argument: {:?}, with type: {} is not a valid reference. Have you registered the type?",
161-
arg_info.name().map(str::to_owned).unwrap_or_else(|| arg_info.index().to_string()),
162-
arg_ref.display_with_world(world.clone())
163-
))
164-
})?;
165+
let access_id = ReflectAccessId::for_reference(arg_ref.base.base_id.clone())
166+
.ok_or_else(|| {
167+
InteropError::function_interop_error(
168+
function_info,
169+
Some(argument_info),
170+
InteropError::unregistered_base(arg_ref.base.clone()),
171+
)
172+
})?;
165173

166-
let is_write = matches!(arg_info.ownership(), Ownership::Mut);
174+
let is_write = matches!(argument_info.ownership(), Ownership::Mut);
167175

168176
let success = if is_write {
169177
world.claim_write_access(access_id)
@@ -173,20 +181,27 @@ impl<I: Iterator<Item = ScriptValue>> IntoArgsListWithAccess for I {
173181

174182
if !success {
175183
release_accesses(&mut accesses);
176-
return Err(ScriptError::new_reflection_error(format!(
177-
"Could not claim access for argument {}",
178-
arg_ref.display_with_world(world.clone())
179-
)));
184+
return Err(InteropError::function_interop_error(
185+
function_info,
186+
Some(argument_info),
187+
InteropError::cannot_claim_access(arg_ref.base.clone()),
188+
)
189+
.into());
180190
}
181191

182-
accesses.push((access_id, arg_info.ownership()));
192+
accesses.push((access_id, argument_info.ownership()));
183193

184-
let val = unsafe { arg_ref.clone().into_arg_value(world.clone(), arg_info) };
194+
let val =
195+
unsafe { arg_ref.clone().into_arg_value(world.clone(), argument_info) };
185196
let val = match val {
186197
Ok(v) => v,
187198
Err(e) => {
188199
release_accesses(&mut accesses);
189-
return Err(e);
200+
return Err(InteropError::function_interop_error(
201+
function_info,
202+
Some(argument_info),
203+
e,
204+
));
190205
}
191206
};
192207
arg_list.push(val);
@@ -200,22 +215,27 @@ impl<I: Iterator<Item = ScriptValue>> IntoArgsListWithAccess for I {
200215
let value = match <dyn PartialReflect>::from_script_value(
201216
value,
202217
world.clone(),
203-
arg_info.type_id(),
218+
argument_info.type_id(),
204219
) {
205220
Some(Ok(v)) => v,
206221
Some(Err(e)) => {
207222
// Safety: Same as above
208223
accesses.iter().for_each(|(id, _)| {
209224
unsafe { world.release_access(*id) };
210225
});
211-
return Err(e);
226+
return Err(InteropError::function_interop_error(
227+
function_info,
228+
Some(argument_info),
229+
e,
230+
));
212231
}
213232
None => {
214233
release_accesses(&mut accesses);
215-
return Err(ValueConversionError::TypeMismatch {
216-
expected_type: arg_info.type_path().into(),
217-
actual_type: None,
218-
}
234+
return Err(InteropError::function_interop_error(
235+
function_info,
236+
Some(argument_info),
237+
InteropError::impossible_conversion(argument_info.type_id()),
238+
)
219239
.into());
220240
}
221241
};

crates/bevy_mod_scripting_core/src/bindings/pretty_print.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
use crate::reflection_extensions::TypeIdExtensions;
22

3-
use super::{
4-
script_val::ScriptValue, ReflectBase, ReflectBaseType, ReflectReference, WorldAccessGuard,
5-
WorldGuard,
6-
};
3+
use super::{script_val::ScriptValue, ReflectBase, ReflectBaseType, ReflectReference, WorldGuard};
74
use bevy::reflect::{PartialReflect, ReflectRef};
85
use itertools::Itertools;
96
use std::{any::TypeId, borrow::Cow};
@@ -309,16 +306,30 @@ impl ReflectReferencePrinter {
309306

310307
/// For types which can't be pretty printed without world access.
311308
/// Implementors should try to print the best value they can, and never panick.
312-
pub trait DisplayWithWorld {
309+
pub trait DisplayWithWorld: std::fmt::Debug {
313310
/// Display the `shallowest` representation of the type using world access.
314311
/// For references this is the type path and the type of the value they are pointing to.
315312
fn display_with_world(&self, world: WorldGuard) -> String;
316313

317314
/// Display the most literal representation of the type using world access.
318315
/// I.e. for references this would be the pointed to value itself.
319-
fn display_value_with_world(&self, world: WorldGuard) -> String;
316+
fn display_value_with_world(&self, world: WorldGuard) -> String {
317+
self.display_with_world(world)
318+
}
320319
}
321320

321+
#[macro_export]
322+
macro_rules! impl_dummy_display (
323+
($t:ty) => {
324+
impl std::fmt::Display for $t {
325+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
326+
write!(f, "Displaying {} without world access: {:#?}", stringify!($t), self);
327+
Ok(())
328+
}
329+
}
330+
};
331+
);
332+
322333
impl DisplayWithWorld for ReflectReference {
323334
fn display_with_world(&self, world: WorldGuard) -> String {
324335
ReflectReferencePrinter::new(self.clone()).pretty_print(world)
@@ -377,6 +388,7 @@ impl DisplayWithWorld for ScriptValue {
377388
ScriptValue::Float(f) => f.to_string(),
378389
ScriptValue::String(cow) => cow.to_string(),
379390
ScriptValue::World => "World".to_owned(),
391+
ScriptValue::Error(script_error) => script_error.to_string(),
380392
}
381393
}
382394
}

0 commit comments

Comments
 (0)