From 38e7f2bcf4a3dc3dedec349cb9bd01bb88d08f6d Mon Sep 17 00:00:00 2001 From: Siddhant Shekhar Date: Wed, 22 Oct 2025 19:23:51 +0530 Subject: [PATCH] Inconsistent clone() requirement when passing Classes to HTML elements vs. components (#3589) (#3931) * Add From<&Classes> impl to allow &Classes in element props (#3589) * bless macro test error output adds an additional candidate to the impl block, which is fine --------- Co-authored-by: Martin Molzer --- .../tests/classes_macro/classes-fail.stderr | 12 ++++++------ .../yew-macro/tests/html_macro/element-fail.stderr | 1 + packages/yew/src/html/classes.rs | 12 ++++++++++++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/packages/yew-macro/tests/classes_macro/classes-fail.stderr b/packages/yew-macro/tests/classes_macro/classes-fail.stderr index 2622e838e..4361dd082 100644 --- a/packages/yew-macro/tests/classes_macro/classes-fail.stderr +++ b/packages/yew-macro/tests/classes_macro/classes-fail.stderr @@ -17,6 +17,7 @@ error[E0277]: the trait bound `Classes: From<{integer}>` is not satisfied | ^^ the trait `From<{integer}>` is not implemented for `Classes` | = help: the following other types implement trait `From`: + `Classes` implements `From<&Classes>` `Classes` implements `From<&Option>` `Classes` implements `From<&String>` `Classes` implements `From<&[T]>` @@ -24,7 +25,6 @@ error[E0277]: the trait bound `Classes: From<{integer}>` is not satisfied `Classes` implements `From<&str>` `Classes` implements `From>` `Classes` implements `From>` - `Classes` implements `From` and $N others = note: required for `{integer}` to implement `Into` note: required by a bound in `Classes::push` @@ -40,6 +40,7 @@ error[E0277]: the trait bound `Classes: From<{float}>` is not satisfied | ^^^^ the trait `From<{float}>` is not implemented for `Classes` | = help: the following other types implement trait `From`: + `Classes` implements `From<&Classes>` `Classes` implements `From<&Option>` `Classes` implements `From<&String>` `Classes` implements `From<&[T]>` @@ -47,7 +48,6 @@ error[E0277]: the trait bound `Classes: From<{float}>` is not satisfied `Classes` implements `From<&str>` `Classes` implements `From>` `Classes` implements `From>` - `Classes` implements `From` and $N others = note: required for `{float}` to implement `Into` note: required by a bound in `Classes::push` @@ -66,6 +66,7 @@ error[E0277]: the trait bound `Classes: From<{integer}>` is not satisfied | required by a bound introduced by this call | = help: the following other types implement trait `From`: + `Classes` implements `From<&Classes>` `Classes` implements `From<&Option>` `Classes` implements `From<&String>` `Classes` implements `From<&[T]>` @@ -73,7 +74,6 @@ error[E0277]: the trait bound `Classes: From<{integer}>` is not satisfied `Classes` implements `From<&str>` `Classes` implements `From>` `Classes` implements `From>` - `Classes` implements `From` and $N others = note: required for `{integer}` to implement `Into` = note: required for `Classes` to implement `From>` @@ -92,6 +92,7 @@ error[E0277]: the trait bound `Classes: From<{integer}>` is not satisfied | ^^^^ the trait `From<{integer}>` is not implemented for `Classes` | = help: the following other types implement trait `From`: + `Classes` implements `From<&Classes>` `Classes` implements `From<&Option>` `Classes` implements `From<&String>` `Classes` implements `From<&[T]>` @@ -99,7 +100,6 @@ error[E0277]: the trait bound `Classes: From<{integer}>` is not satisfied `Classes` implements `From<&str>` `Classes` implements `From>` `Classes` implements `From>` - `Classes` implements `From` and $N others = note: required for `{integer}` to implement `Into` = note: required for `Classes` to implement `From>` @@ -118,6 +118,7 @@ error[E0277]: the trait bound `Classes: From` is not satisfied | ^^^^ the trait `From` is not implemented for `Classes` | = help: the following other types implement trait `From`: + `Classes` implements `From<&Classes>` `Classes` implements `From<&Option>` `Classes` implements `From<&String>` `Classes` implements `From<&[T]>` @@ -125,7 +126,6 @@ error[E0277]: the trait bound `Classes: From` is not satisfied `Classes` implements `From<&str>` `Classes` implements `From>` `Classes` implements `From>` - `Classes` implements `From` and $N others = note: required for `u32` to implement `Into` = note: required for `Classes` to implement `From>` @@ -144,6 +144,7 @@ error[E0277]: the trait bound `Classes: From<{integer}>` is not satisfied | ^^ the trait `From<{integer}>` is not implemented for `Classes` | = help: the following other types implement trait `From`: + `Classes` implements `From<&Classes>` `Classes` implements `From<&Option>` `Classes` implements `From<&String>` `Classes` implements `From<&[T]>` @@ -151,7 +152,6 @@ error[E0277]: the trait bound `Classes: From<{integer}>` is not satisfied `Classes` implements `From<&str>` `Classes` implements `From>` `Classes` implements `From>` - `Classes` implements `From` and $N others = note: required for `{integer}` to implement `Into` note: required by a bound in `Classes::push` diff --git a/packages/yew-macro/tests/html_macro/element-fail.stderr b/packages/yew-macro/tests/html_macro/element-fail.stderr index 8488c5cea..0778bb336 100644 --- a/packages/yew-macro/tests/html_macro/element-fail.stderr +++ b/packages/yew-macro/tests/html_macro/element-fail.stderr @@ -695,6 +695,7 @@ error[E0277]: the trait bound `implicit_clone::unsync::string::IString: From<{in | ^^ the trait `From<{integer}>` is not implemented for `implicit_clone::unsync::string::IString` | = help: the following other types implement trait `From`: + `implicit_clone::unsync::string::IString` implements `From<&Classes>` `implicit_clone::unsync::string::IString` implements `From<&implicit_clone::unsync::string::IString>` `implicit_clone::unsync::string::IString` implements `From<&str>` `implicit_clone::unsync::string::IString` implements `From>` diff --git a/packages/yew/src/html/classes.rs b/packages/yew/src/html/classes.rs index 78ca7d83e..e04fb28f0 100644 --- a/packages/yew/src/html/classes.rs +++ b/packages/yew/src/html/classes.rs @@ -277,6 +277,18 @@ impl, const SIZE: usize> From<[T; SIZE]> for Classes { } } +impl From<&Classes> for Classes { + fn from(c: &Classes) -> Self { + c.clone() + } +} + +impl From<&Classes> for AttrValue { + fn from(c: &Classes) -> Self { + c.clone().into_prop_value() + } +} + impl PartialEq for Classes { fn eq(&self, other: &Self) -> bool { self.set.len() == other.set.len() && self.set.iter().eq(other.set.iter())