Skip to content

Commit f471603

Browse files
authored
bevy_reflect: Fix TypePath string concatenation (#18609)
# Objective Fixes #18606 When a type implements `Add` for `String`, the compiler can get confused when attempting to add a `&String` to a `String`. Unfortunately, this seems to be [expected behavior](rust-lang/rust#77143 (comment)) which causes problems for generic types since the current `TypePath` derive generates code that appends strings in this manner. ## Solution Explicitly use the `Add<&str>` implementation in the `TypePath` derive macro. ## Testing You can test locally by running: ``` cargo check -p bevy_reflect --tests ```
1 parent 58b8f55 commit f471603

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

crates/bevy_reflect/derive/src/string_expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl StringExpr {
8080
let owned = self.into_owned();
8181
let borrowed = other.into_borrowed();
8282
Self::Owned(quote! {
83-
#owned + #borrowed
83+
::core::ops::Add::<&str>::add(#owned, #borrowed)
8484
})
8585
}
8686
}

crates/bevy_reflect/src/lib.rs

+35
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,41 @@ mod tests {
988988
assert_eq!(values, vec![1]);
989989
}
990990

991+
/// This test ensures that we are able to reflect generic types with one or more type parameters.
992+
///
993+
/// When there is an `Add` implementation for `String`, the compiler isn't able to infer the correct
994+
/// type to deref to.
995+
/// If we don't append the strings in the `TypePath` derive correctly (i.e. explicitly specifying the type),
996+
/// we'll get a compilation error saying that "`&String` cannot be added to `String`".
997+
///
998+
/// So this test just ensures that we do do that correctly.
999+
///
1000+
/// This problem is a known issue and is unexpectedly expected behavior:
1001+
/// - <https://github.com/rust-lang/rust/issues/77143>
1002+
/// - <https://github.com/bodil/smartstring/issues/7>
1003+
/// - <https://github.com/pola-rs/polars/issues/14666>
1004+
#[test]
1005+
fn should_reflect_generic() {
1006+
struct FakeString {}
1007+
1008+
// This implementation confuses the compiler when trying to add a `&String` to a `String`
1009+
impl core::ops::Add<FakeString> for String {
1010+
type Output = Self;
1011+
fn add(self, _rhs: FakeString) -> Self::Output {
1012+
unreachable!()
1013+
}
1014+
}
1015+
1016+
#[derive(Reflect)]
1017+
struct Foo<A>(A);
1018+
1019+
#[derive(Reflect)]
1020+
struct Bar<A, B>(A, B);
1021+
1022+
#[derive(Reflect)]
1023+
struct Baz<A, B, C>(A, B, C);
1024+
}
1025+
9911026
#[test]
9921027
fn should_reflect_clone() {
9931028
// Struct

0 commit comments

Comments
 (0)