allow access to the source error of `AssetLoaderError` and downcasting
Objective
I have a custom asset loader, and need access to the error it reports when failing to load (e.g. through AssetLoadFailedEvent { error: AssetLoadError::AssetLoaderError(loader_error), .. }). However AssetLoaderError doesn't expose its <core::error::Error>::source() (i.e. its error field. It only formats it when Displayed.
I haven't searched for issues about it.
Solution
- Annotate
AssetLoaderError'serrorfield with#[source]. - Don't include the error when
AssetLoaderErrorisDisplayed (when one prints an error's source stack like a backtrace, it would now be dupplicated). - (optional, included as a separated commit) Add a getter for the
&dyn Errorstored in theerrorfield (whithin anArc). This is more ergonomic than usingError::source()because it casts an&Arc<dyn Error>into an&dyn Error, meaning one has to downcast it twice to get the original error from the loader, including once where you have to specify the correct type of the privateerrorfield. So downcasting fromError::source()effectively rely on the internal implementation ofAssetLoaderError. The getter instead return the trait object directly, which mean it will directly downcast to the expected loader error type.
I didn't included a test that checks that double-downcasting <AssetLoaderError as Error>::source() doesn't break user code that would rely on the private field's type.
Testing
- Downcasting the trait objects for both
source()and theerror()getter work as described above. cargo test -p bevy_asset --all-featurespass without errors.
Welcome, new contributor!
Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨
Oh this broke the test error_on_nested_immediate_load_of_subasset because it partly did what this PR tries to fix: It checks that we indeed get an error from the loader but cannot access it, so it matches the error message. I added a commit to fix it, now it downcasts the error and panics if it's not the underlying <_ as AssetLoader>::Error. It still checks that the error message mentions that nested immediate loads of subassets are unsupported though.
I expected the conflict, I'll get around that tomorrow now :)
- rebased :3
- I've removed the forwarding of the inner error through
coore::error::Error::source()because #19478 made it aBevyErrorwhich doesn't implements the trait. So the only change is the addition of a getter for it. cargo run -p ci -- lintsfailed locally but it seemed unrelated ? Unsure if I should do something about it here.
This is still failing CI. I think it might be relevant? It's from server/mod.rs.