Skip to content

Conversation

@Eyad3skr
Copy link
Contributor

@Eyad3skr Eyad3skr commented Jan 7, 2026

Objective

Fixes #22239

Solution

  • Added resolve_path(&AssetPath) - equivalent to resolve(&str)
  • Added resolve_embed_path(&AssetPath) - equivalent to resolve_embed(&str)
  • Refactored resolve_internal to use shared resolve_from_parts helper
  • Added unit tests for equivalence
  • All semantic edge cases preserved (eg., label-only, or leading /)
  • No behavior changes to existing methods

Testing

  • Added 2 new equivalence tests proving resolve_path() ≡ resolve(&path.to_string())
  • All 20 tests pass: cargo test -p bevy_asset --lib path::tests
  • Test covers: relative paths, labels, leading /, explicit sources, RFC 1808 embed behavior

How to test

cargo test -p bevy_asset --lib path::tests

These new methods accept &AssetPath instead of &str, avoiding the need
to stringify and re-parse when the caller already has an AssetPath.

Fixes bevyengine#22239
These new methods accept &AssetPath instead of &str, avoiding the need
to stringify and re-parse when the caller already has an AssetPath.

Fixes bevyengine#22239
@github-actions
Copy link
Contributor

github-actions bot commented Jan 7, 2026

Welcome, new contributor!

Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨

@alice-i-cecile alice-i-cecile added A-Assets Load files from disk to use for things like images, models, and sounds C-Code-Quality A section of code that is hard to understand or change C-Usability A targeted quality-of-life change that makes Bevy easier to use S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Jan 7, 2026
@alice-i-cecile alice-i-cecile added X-Uncontroversial This work is generally agreed upon D-Straightforward Simple bug fixes and API improvements, docs, test and examples labels Jan 7, 2026
@alice-i-cecile
Copy link
Member

Very clean work; thank you :)

@viridia
Copy link
Contributor

viridia commented Jan 7, 2026

My only concern is that this propagates a pattern that we've been wanting to get rid of for a long time (but have never got around to fixing).

Specifically, AssetPath::resolve should not use PathBuf. PathBuf does a lot of crazy things - like parsing windows drive letters - which simply don't apply to Bevy asset paths, and which are a potential source of bugs. It would be much better to have our own path resolution algorithm that operates on string slices, this would be fairly easy to write, easy to test, and the behavior would be predictable.

PathBuf makes sense when we are talking about actual file paths: that is, when an asset path gets transformed into a path used to actually open files. This happens inside the filesystem asset source, and is not part of the higher-level asset framework.

But asset paths themselves are not file paths, they are more like URLs.

@Eyad3skr
Copy link
Contributor Author

Eyad3skr commented Jan 7, 2026

Thanks @alice-i-cecile for the compliment and thanks @viridia for the detailed feedback, that actually makes sense.

I agree AssetPath is closer to a URL-like path than a filesystem path, and PathBuf/std::path normalization brings platform-specific behavior (e.g. Windows prefixes / drive letters) that shouldn’t apply at the asset-path layer.

This PR intentionally kept behavior identical to the existing resolve / resolve_embed implementation, and the new resolve_*_path methods reuse the same internal logic to avoid any semantic changes. That said, I understand the concern that refactoring here may further entrench the PathBuf-based approach.

I thought of 2 things could be done rn :

  1. keep this PR scoped to the API improvement (accepting &AssetPath + equivalence tests), and I open a follow-up issue/PR to replace the resolution algorithm with a string-slice implementation, or
  2. expand this PR to replace the PathBuf usage as part of the same change?

I’m happy to do either..

@viridia
Copy link
Contributor

viridia commented Jan 7, 2026

If we commit to doing a follow-up PR then it would alleviate my concerns.

Copy link
Contributor

@Shatur Shatur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can sneak this into 0.18 since it's not a breaking change, but I'd probably rename old methods into *_str and keep path variants as "default" in a follow-up.

) -> AssetPath<'static> {
let mut base_path = PathBuf::from(self.path());
if replace && !self.path.to_str().unwrap().ends_with('/') {
// No error if base is empty
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why (per RFC 1808) in the comment was removed?

Comment on lines 419 to 420
/// Resolves `path` relative to `self`, using the same rules as [`AssetPath::resolve`],
/// but without reparsing from a string.
Copy link
Contributor

@Shatur Shatur Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe change the description of resolve instead and mention that it parses the asset path from the string?

@Eyad3skr
Copy link
Contributor Author

Eyad3skr commented Jan 7, 2026

@viridia Tracking issue opened: #22420 . I’ll follow up with a PR replacing PathBuf resolution with a deterministic segment-based resolver.

@alice-i-cecile alice-i-cecile added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Jan 7, 2026
@alice-i-cecile
Copy link
Member

@Eyad3skr if you can tackle @Shatur's comments briefly I'll be happy to merge this and wait for the follow-up issue to address the PathBuf concerns :)

@Eyad3skr
Copy link
Contributor Author

Eyad3skr commented Jan 7, 2026

@Shatur @alice-i-cecile On it

…suit the method name change occured. replacing back the RFC 1808 reference.
@Shatur
Copy link
Contributor

Shatur commented Jan 7, 2026

I meant to rename in a follow-up PR some time later because this would potentially allow us to include this change in 0.18. But if it's easier for you to do it now - it's okay, not that important to have this in 0.18 🙂

@Eyad3skr
Copy link
Contributor Author

Eyad3skr commented Jan 7, 2026

@Shatur oh really, sorry didn't catch this up! anyway I'm up for the night dodging studying for data engineering final, it is ok.

and sorry for the many mentions, we are more than 2 in the discussion, just so I don't mix things up.

@abdlla3amer
Copy link

Wonderful analogy with a high-level end-to-end object oriented solution Mr. @Eyad3skr

@Eyad3skr
Copy link
Contributor Author

Eyad3skr commented Jan 8, 2026

anybody got an idea of why CI / markdownlint (pull_request) fails?

@alice-i-cecile
Copy link
Member

Markdown errors can be found starting https://github.com/bevyengine/bevy/actions/runs/20803366790/job/59752575411?pr=22416#step:4:156; you need to expand the markdown section when looking at the job :)

Thanks for your work here; I'll merge this once CI is passing!

@alice-i-cecile alice-i-cecile added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Jan 8, 2026
pull_requests: [22416]
---

# `AssetPath::resolve` and `resolve_embed` now take `&AssetPath`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest to take a look at how other people write migration guides: https://github.com/bevyengine/bevy/tree/main/release-content/migration-guides
It's a bit verbose for such a simple change. I wouldn't even add "Before" and "After".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Eyad3skr I didn't mean to remove the labels. I meant to remove the whole blocks with the before and after code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so migration part I just write it in plain English?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, just a few sentences should be enough to explain the breaking change. Just take a look at the link I shared above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

passed it finally.. the linter was confused between the real title from template and my text because I used H1 after the title, so I reduced it to H2

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Shatur Ok I will see now

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's still overly verbose. Take a look at the migration guides I linked to you. You don't need headings, just write in plain English what was done (no need to write "# What was done"), how to migrate and why. It's obvious that if you have a string, it's more convenient to use the *_str methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair enough, made it


`AssetPath::resolve` and `AssetPath::resolve_embed` no longer accept `&str` and now take `&AssetPath` directly. The previous string-based APIs have been renamed to `resolve_str` and `resolve_embed_str`.

This change avoids unnecessary string allocation and parsing when an `AssetPath` is already available. To migrate, pass an `AssetPath` directly to `resolve` or `resolve_embed`; when working with strings, use the corresponding `*_str` methods instead. No behavioral or semantic changes were introduced. No newline at end of file
Copy link
Contributor

@Shatur Shatur Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost perfect, last tiny change, can be applied directly from the browser 🙂 I think the last sentence doesn't add anything.

Suggested change
This change avoids unnecessary string allocation and parsing when an `AssetPath` is already available. To migrate, pass an `AssetPath` directly to `resolve` or `resolve_embed`; when working with strings, use the corresponding `*_str` methods instead. No behavioral or semantic changes were introduced.
This change avoids unnecessary string allocation and parsing when an `AssetPath` is already available. To migrate, pass an `AssetPath` directly to `resolve` or `resolve_embed`; when working with strings, use the corresponding `*_str` methods instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made it, the linter failed anyway, needed a trailing newline

Copy link
Contributor Author

@Eyad3skr Eyad3skr Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Shatur btw as for the issue #22420, ig it needs to be labeled and see if my description is right so I can go on with it?

Copy link
Contributor

@Shatur Shatur Jan 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave the guiding for #22420 to @viridia .

I want to note that PathBuf was already used and you just moved it into a separate method to re-use the logic for AssetPath. So you did a great job.
#22420 it's a separate, but related issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, waiting for any updates. I'm trying to catch up anyway so I got no problem getting assigned this one too, thanks for the review and your effort!

Copy link
Contributor

@Shatur Shatur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect now! Thank you.

@Eyad3skr
Copy link
Contributor Author

Eyad3skr commented Jan 8, 2026

Perfect now! Thank you.

Always! Thank you for the review, much appreciated!

@alice-i-cecile alice-i-cecile added this pull request to the merge queue Jan 8, 2026
@alice-i-cecile alice-i-cecile added this to the 0.18 milestone Jan 8, 2026
Merged via the queue into bevyengine:main with commit adba91a Jan 8, 2026
38 checks passed
@Shatur
Copy link
Contributor

Shatur commented Jan 8, 2026

@alice-i-cecile this PR includes a breaking change, so we probably have to remove it from 0.18 😢
I suggested this one for 0.18 originally, but the author also included a rename. I don't think it's worth backporting the change without the rename for 0.18.

@cart cart modified the milestones: 0.18, 0.19 Jan 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Assets Load files from disk to use for things like images, models, and sounds C-Code-Quality A section of code that is hard to understand or change C-Usability A targeted quality-of-life change that makes Bevy easier to use D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it X-Uncontroversial This work is generally agreed upon

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Accept &AssetPath instead of &str in AssetPath::resolve

6 participants