Skip to content

Commit 83df589

Browse files
committed
fix: Error on immediate load of self asset path.
Warn on deferred load of self asset path. feat: Permit read_asset_bytes for self dep. Don't record a loader_dependency for it, however. style: Reformat.
1 parent ebe0d08 commit 83df589

File tree

3 files changed

+60
-16
lines changed

3 files changed

+60
-16
lines changed

crates/bevy_asset/src/lib.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1997,7 +1997,8 @@ mod tests {
19971997
load_context: &mut LoadContext<'_>,
19981998
) -> Result<Self::Asset, Self::Error> {
19991999
let asset_path = load_context.asset_path().clone();
2000-
let loaded_asset = load_context.loader()
2000+
let loaded_asset = load_context
2001+
.loader()
20012002
.immediate()
20022003
.load::<TestAsset>(asset_path)
20032004
.await?;
@@ -2018,7 +2019,11 @@ mod tests {
20182019
run_app_until(&mut app, |_world| match asset_server.load_state(&handle) {
20192020
LoadState::Loading => None,
20202021
LoadState::Failed(err) => {
2021-
assert!(format!("{:?}", &err).contains("AssetDependentOnSelf"), "Error did not contain AssetDependentOnSelf: {:?}", &err);
2022+
assert!(
2023+
format!("{:?}", &err).contains("AssetDependentOnSelf"),
2024+
"Error did not contain AssetDependentOnSelf: {:?}",
2025+
&err
2026+
);
20222027
Some(())
20232028
}
20242029
state => panic!("Unexpected asset state: {state:?}"),
@@ -2046,7 +2051,8 @@ mod tests {
20462051
load_context: &mut LoadContext<'_>,
20472052
) -> Result<Self::Asset, Self::Error> {
20482053
let asset_path = load_context.asset_path().clone();
2049-
let loaded_asset = load_context.loader()
2054+
let loaded_asset = load_context
2055+
.loader()
20502056
.immediate()
20512057
.with_unknown_type()
20522058
.load(asset_path)
@@ -2071,7 +2077,11 @@ mod tests {
20712077
run_app_until(&mut app, |_world| match asset_server.load_state(&handle) {
20722078
LoadState::Loading => None,
20732079
LoadState::Failed(err) => {
2074-
assert!(format!("{:?}", &err).contains("AssetDependentOnSelf"), "Error did not contain AssetDependentOnSelf: {:?}", &err);
2080+
assert!(
2081+
format!("{:?}", &err).contains("AssetDependentOnSelf"),
2082+
"Error did not contain AssetDependentOnSelf: {:?}",
2083+
&err
2084+
);
20752085
Some(())
20762086
}
20772087
state => panic!("Unexpected asset state: {state:?}"),
@@ -2141,7 +2151,7 @@ mod tests {
21412151
messages,
21422152
[
21432153
AssetEvent::LoadedWithDependencies { id: handle.id() },
2144-
AssetEvent::Added { id: handle.id() }
2154+
AssetEvent::Added { id: handle.id() }
21452155
]
21462156
);
21472157
Some(())
@@ -2283,7 +2293,8 @@ mod tests {
22832293
let untyped_handle: UntypedHandle = load_context
22842294
.loader()
22852295
.with_unknown_type()
2286-
.load(asset_path).into();
2296+
.load(asset_path)
2297+
.into();
22872298

22882299
Ok(TestAssetUD(untyped_handle))
22892300
}
@@ -2320,7 +2331,7 @@ mod tests {
23202331
messages,
23212332
[
23222333
AssetEvent::LoadedWithDependencies { id: handle.id() },
2323-
AssetEvent::Added { id: handle.id() }
2334+
AssetEvent::Added { id: handle.id() }
23242335
]
23252336
);
23262337
Some(())

crates/bevy_asset/src/loader.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -306,12 +306,14 @@ pub enum LoadDirectError {
306306
error: AssetLoadError,
307307
},
308308
#[error(transparent)]
309-
AssetDependentOnSelf(#[from] AssetDependentOnSelf)
309+
AssetDependentOnSelf(#[from] AssetDependentOnSelf),
310310
}
311311

312312
#[derive(Error, Debug, Clone)]
313313
#[error("The asset at path `{}` loads itself as a dependent.", asset_path)]
314-
pub struct AssetDependentOnSelf { pub asset_path: AssetPath<'static> }
314+
pub struct AssetDependentOnSelf {
315+
pub asset_path: AssetPath<'static>,
316+
}
315317

316318
/// An error that occurs while deserializing [`AssetMeta`].
317319
#[derive(Error, Debug, Clone, PartialEq, Eq)]
@@ -514,7 +516,9 @@ impl<'a> LoadContext<'a> {
514516
path: path.path().to_path_buf(),
515517
source,
516518
})?;
517-
self.loader_dependencies.insert(path.clone_owned(), hash);
519+
if self.asset_path != path {
520+
self.loader_dependencies.insert(path.clone_owned(), hash);
521+
}
518522
Ok(bytes)
519523
}
520524

@@ -540,6 +544,12 @@ impl<'a> LoadContext<'a> {
540544
loader: &dyn ErasedAssetLoader,
541545
reader: &mut dyn Reader,
542546
) -> Result<ErasedLoadedAsset, LoadDirectError> {
547+
if self.asset_path == path {
548+
return Err(AssetDependentOnSelf {
549+
asset_path: self.asset_path.clone_owned(),
550+
}
551+
.into());
552+
}
543553
let loaded_asset = self
544554
.asset_server
545555
.load_with_meta_loader_and_reader(
@@ -557,6 +567,7 @@ impl<'a> LoadContext<'a> {
557567
})?;
558568
let info = meta.processed_info().as_ref();
559569
let hash = info.map(|i| i.full_hash).unwrap_or_default();
570+
560571
self.loader_dependencies.insert(path, hash);
561572
Ok(loaded_asset)
562573
}
@@ -600,5 +611,5 @@ pub enum ReadAssetBytesError {
600611
#[error("The LoadContext for this read_asset_bytes call requires hash metadata, but it was not provided. This is likely an internal implementation error.")]
601612
MissingAssetHash,
602613
#[error(transparent)]
603-
AssetDependentOnSelf(#[from] AssetDependentOnSelf)
614+
AssetDependentOnSelf(#[from] AssetDependentOnSelf),
604615
}

crates/bevy_asset/src/loader_builders.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
use crate::{
55
io::Reader,
66
meta::{meta_transform_settings, AssetMetaDyn, MetaTransform, Settings},
7-
Asset, AssetLoadError, AssetPath, ErasedAssetLoader, ErasedLoadedAsset, Handle, LoadContext,
8-
LoadDirectError, LoadedAsset, LoadedUntypedAsset, UntypedHandle,
7+
Asset, AssetDependentOnSelf, AssetLoadError, AssetPath, ErasedAssetLoader, ErasedLoadedAsset,
8+
Handle, LoadContext, LoadDirectError, LoadedAsset, LoadedUntypedAsset, UntypedHandle,
99
};
1010
use alloc::{borrow::ToOwned, boxed::Box, sync::Arc};
1111
use core::any::TypeId;
12+
use tracing::warn;
1213

1314
// Utility type for handling the sources of reader references
1415
enum ReaderRef<'a> {
@@ -304,6 +305,8 @@ impl NestedLoader<'_, '_, StaticTyped, Deferred> {
304305
/// [`with_unknown_type`]: Self::with_unknown_type
305306
pub fn load<'c, A: Asset>(self, path: impl Into<AssetPath<'c>>) -> Handle<A> {
306307
let path = path.into().to_owned();
308+
309+
let is_self_path = *self.load_context.asset_path() == path;
307310
let handle = if self.load_context.should_load_dependencies {
308311
self.load_context.asset_server.load_with_meta_transform(
309312
path,
@@ -318,8 +321,15 @@ impl NestedLoader<'_, '_, StaticTyped, Deferred> {
318321
};
319322
// `load_with_meta_transform` and `get_or_create_path_handle` always returns a Strong
320323
// variant, so we are safe to unwrap.
321-
let index = (&handle).try_into().unwrap();
322-
self.load_context.dependencies.insert(index);
324+
if !is_self_path {
325+
let index = (&handle).try_into().unwrap();
326+
self.load_context.dependencies.insert(index);
327+
} else {
328+
warn!(
329+
"Asset from path `{}` loaded the same path as a dependent, ignoring.",
330+
self.load_context.asset_path()
331+
);
332+
}
323333
handle
324334
}
325335
}
@@ -367,6 +377,7 @@ impl NestedLoader<'_, '_, UnknownTyped, Deferred> {
367377
/// This will infer the asset type from metadata.
368378
pub fn load<'p>(self, path: impl Into<AssetPath<'p>>) -> Handle<LoadedUntypedAsset> {
369379
let path = path.into().to_owned();
380+
let is_self_path = *self.load_context.asset_path() == path;
370381
let handle = if self.load_context.should_load_dependencies {
371382
self.load_context
372383
.asset_server
@@ -379,7 +390,12 @@ impl NestedLoader<'_, '_, UnknownTyped, Deferred> {
379390
// `load_unknown_type_with_meta_transform` and `get_or_create_path_handle` always returns a
380391
// Strong variant, so we are safe to unwrap.
381392
let index = (&handle).try_into().unwrap();
382-
self.load_context.dependencies.insert(index);
393+
394+
if !is_self_path {
395+
self.load_context.dependencies.insert(index);
396+
} else {
397+
warn!("Asset from path `{}` of unknown type loaded the same path as a dependent, ignoring.", self.load_context.asset_path());
398+
}
383399
handle
384400
}
385401
}
@@ -402,6 +418,12 @@ impl<'builder, 'reader, T> NestedLoader<'_, '_, T, Immediate<'builder, 'reader>>
402418
if path.label().is_some() {
403419
return Err(LoadDirectError::RequestedSubasset(path.clone()));
404420
}
421+
if self.load_context.asset_path() == path {
422+
return Err(AssetDependentOnSelf {
423+
asset_path: path.clone(),
424+
}
425+
.into());
426+
}
405427
self.load_context
406428
.asset_server
407429
.write_infos()

0 commit comments

Comments
 (0)