Require Clone for Message early when needed

Prior to this change, the widgets that needed a `Clone` bound on `Message` to
implement the `Widget` trait could be created with a non-cloneable `Message`.

As a consequence, the compiler complained only when actually trying to use the
`Widget` trait. Normally, this happens when trying to `push` the widget in a
container or turn it into an `Element`.

Furthermore, the compiler error in this case does not mention `Message` nor the
`Clone` bound, but instead complains about a missing `From` implementation.
Thus, it can easily cause confusion!

This change introduces `Clone` bounds in the main implementation of the
widgets that need it to properly implement the `Widget` trait. As a
result, the compiler complains early when trying to create one of these widgets
with a non-cloneable `Message` and explicitly mentions that the `Message` needs
to implement `Clone`.
This commit is contained in:
Héctor Ramón Jiménez 2020-10-17 08:10:30 +02:00
parent 17f0db57c3
commit d7a5e54455
6 changed files with 21 additions and 11 deletions

View File

@ -284,7 +284,7 @@ impl<C: 'static + ColorSpace + Copy> ColorPicker<C> {
let [s1, s2, s3] = &mut self.sliders; let [s1, s2, s3] = &mut self.sliders;
let [cr1, cr2, cr3] = C::COMPONENT_RANGES; let [cr1, cr2, cr3] = C::COMPONENT_RANGES;
fn slider<C>( fn slider<C: Clone>(
state: &mut slider::State, state: &mut slider::State,
range: RangeInclusive<f64>, range: RangeInclusive<f64>,
component: f32, component: f32,

View File

@ -689,7 +689,7 @@ fn ferris<'a>(width: u16) -> Container<'a, StepMessage> {
.center_x() .center_x()
} }
fn button<'a, Message>( fn button<'a, Message: Clone>(
state: &'a mut button::State, state: &'a mut button::State,
label: &str, label: &str,
) -> Button<'a, Message> { ) -> Button<'a, Message> {

View File

@ -18,6 +18,7 @@ use std::hash::Hash;
/// # type Button<'a, Message> = /// # type Button<'a, Message> =
/// # iced_native::Button<'a, Message, iced_native::renderer::Null>; /// # iced_native::Button<'a, Message, iced_native::renderer::Null>;
/// # /// #
/// #[derive(Clone)]
/// enum Message { /// enum Message {
/// ButtonPressed, /// ButtonPressed,
/// } /// }
@ -41,6 +42,7 @@ pub struct Button<'a, Message, Renderer: self::Renderer> {
impl<'a, Message, Renderer> Button<'a, Message, Renderer> impl<'a, Message, Renderer> Button<'a, Message, Renderer>
where where
Message: Clone,
Renderer: self::Renderer, Renderer: self::Renderer,
{ {
/// Creates a new [`Button`] with some local [`State`] and the given /// Creates a new [`Button`] with some local [`State`] and the given
@ -142,8 +144,8 @@ impl State {
impl<'a, Message, Renderer> Widget<Message, Renderer> impl<'a, Message, Renderer> Widget<Message, Renderer>
for Button<'a, Message, Renderer> for Button<'a, Message, Renderer>
where where
Renderer: self::Renderer,
Message: Clone, Message: Clone,
Renderer: self::Renderer,
{ {
fn width(&self) -> Length { fn width(&self) -> Length {
self.width self.width
@ -272,8 +274,8 @@ pub trait Renderer: crate::Renderer + Sized {
impl<'a, Message, Renderer> From<Button<'a, Message, Renderer>> impl<'a, Message, Renderer> From<Button<'a, Message, Renderer>>
for Element<'a, Message, Renderer> for Element<'a, Message, Renderer>
where where
Renderer: 'a + self::Renderer,
Message: 'a + Clone, Message: 'a + Clone,
Renderer: 'a + self::Renderer,
{ {
fn from( fn from(
button: Button<'a, Message, Renderer>, button: Button<'a, Message, Renderer>,

View File

@ -47,6 +47,8 @@ pub struct Radio<Message, Renderer: self::Renderer + text::Renderer> {
impl<Message, Renderer: self::Renderer + text::Renderer> impl<Message, Renderer: self::Renderer + text::Renderer>
Radio<Message, Renderer> Radio<Message, Renderer>
where
Message: Clone,
{ {
/// Creates a new [`Radio`] button. /// Creates a new [`Radio`] button.
/// ///
@ -123,8 +125,8 @@ impl<Message, Renderer: self::Renderer + text::Renderer>
impl<Message, Renderer> Widget<Message, Renderer> for Radio<Message, Renderer> impl<Message, Renderer> Widget<Message, Renderer> for Radio<Message, Renderer>
where where
Renderer: self::Renderer + text::Renderer + row::Renderer,
Message: Clone, Message: Clone,
Renderer: self::Renderer + text::Renderer + row::Renderer,
{ {
fn width(&self) -> Length { fn width(&self) -> Length {
self.width self.width
@ -264,8 +266,8 @@ pub trait Renderer: crate::Renderer {
impl<'a, Message, Renderer> From<Radio<Message, Renderer>> impl<'a, Message, Renderer> From<Radio<Message, Renderer>>
for Element<'a, Message, Renderer> for Element<'a, Message, Renderer>
where where
Renderer: 'a + self::Renderer + row::Renderer + text::Renderer,
Message: 'a + Clone, Message: 'a + Clone,
Renderer: 'a + self::Renderer + row::Renderer + text::Renderer,
{ {
fn from(radio: Radio<Message, Renderer>) -> Element<'a, Message, Renderer> { fn from(radio: Radio<Message, Renderer>) -> Element<'a, Message, Renderer> {
Element::new(radio) Element::new(radio)

View File

@ -26,6 +26,7 @@ use std::{hash::Hash, ops::RangeInclusive};
/// # use iced_native::{slider, renderer::Null}; /// # use iced_native::{slider, renderer::Null};
/// # /// #
/// # pub type Slider<'a, T, Message> = iced_native::Slider<'a, T, Message, Null>; /// # pub type Slider<'a, T, Message> = iced_native::Slider<'a, T, Message, Null>;
/// #[derive(Clone)]
/// pub enum Message { /// pub enum Message {
/// SliderChanged(f32), /// SliderChanged(f32),
/// } /// }
@ -53,6 +54,7 @@ pub struct Slider<'a, T, Message, Renderer: self::Renderer> {
impl<'a, T, Message, Renderer> Slider<'a, T, Message, Renderer> impl<'a, T, Message, Renderer> Slider<'a, T, Message, Renderer>
where where
T: Copy + From<u8> + std::cmp::PartialOrd, T: Copy + From<u8> + std::cmp::PartialOrd,
Message: Clone,
Renderer: self::Renderer, Renderer: self::Renderer,
{ {
/// Creates a new [`Slider`]. /// Creates a new [`Slider`].
@ -168,8 +170,8 @@ impl<'a, T, Message, Renderer> Widget<Message, Renderer>
for Slider<'a, T, Message, Renderer> for Slider<'a, T, Message, Renderer>
where where
T: Copy + Into<f64> + num_traits::FromPrimitive, T: Copy + Into<f64> + num_traits::FromPrimitive,
Renderer: self::Renderer,
Message: Clone, Message: Clone,
Renderer: self::Renderer,
{ {
fn width(&self) -> Length { fn width(&self) -> Length {
self.width self.width
@ -322,8 +324,8 @@ impl<'a, T, Message, Renderer> From<Slider<'a, T, Message, Renderer>>
for Element<'a, Message, Renderer> for Element<'a, Message, Renderer>
where where
T: 'a + Copy + Into<f64> + num_traits::FromPrimitive, T: 'a + Copy + Into<f64> + num_traits::FromPrimitive,
Renderer: 'a + self::Renderer,
Message: 'a + Clone, Message: 'a + Clone,
Renderer: 'a + self::Renderer,
{ {
fn from( fn from(
slider: Slider<'a, T, Message, Renderer>, slider: Slider<'a, T, Message, Renderer>,

View File

@ -63,7 +63,11 @@ pub struct TextInput<'a, Message, Renderer: self::Renderer> {
style: Renderer::Style, style: Renderer::Style,
} }
impl<'a, Message, Renderer: self::Renderer> TextInput<'a, Message, Renderer> { impl<'a, Message, Renderer> TextInput<'a, Message, Renderer>
where
Message: Clone,
Renderer: self::Renderer,
{
/// Creates a new [`TextInput`]. /// Creates a new [`TextInput`].
/// ///
/// It expects: /// It expects:
@ -175,8 +179,8 @@ impl<'a, Message, Renderer: self::Renderer> TextInput<'a, Message, Renderer> {
impl<'a, Message, Renderer> Widget<Message, Renderer> impl<'a, Message, Renderer> Widget<Message, Renderer>
for TextInput<'a, Message, Renderer> for TextInput<'a, Message, Renderer>
where where
Renderer: self::Renderer,
Message: Clone, Message: Clone,
Renderer: self::Renderer,
{ {
fn width(&self) -> Length { fn width(&self) -> Length {
self.width self.width
@ -629,8 +633,8 @@ pub trait Renderer: text::Renderer + Sized {
impl<'a, Message, Renderer> From<TextInput<'a, Message, Renderer>> impl<'a, Message, Renderer> From<TextInput<'a, Message, Renderer>>
for Element<'a, Message, Renderer> for Element<'a, Message, Renderer>
where where
Renderer: 'a + self::Renderer,
Message: 'a + Clone, Message: 'a + Clone,
Renderer: 'a + self::Renderer,
{ {
fn from( fn from(
text_input: TextInput<'a, Message, Renderer>, text_input: TextInput<'a, Message, Renderer>,