@@ -161,10 +161,10 @@ pub trait Model {
161161 ModelIterator :: new ( self )
162162 }
163163
164- /// Return something that can be downcast'ed (typically self)
164+ /// Return something that can be downcast'ed (typically self).
165165 ///
166- /// This is useful to get back to the actual model from a [`ModelRc`] stored
167- /// in a ItemTree .
166+ /// Use this to retrieve the concrete model from a [`ModelRc`] stored
167+ /// in your tree of UI elements .
168168 ///
169169 /// ```
170170 /// # use i_slint_core::model::*;
@@ -175,11 +175,58 @@ pub trait Model {
175175 /// assert_eq!(handle.row_data(3).unwrap(), 4);
176176 /// ```
177177 ///
178- /// Note: the default implementation returns nothing interesting. this method should be
179- /// implemented by model implementation to return something useful. For example :
178+ /// Note: Custom models must implement this method for the cast to succeed.
179+ /// A valid implementation is to return `self` :
180180 /// ```ignore
181181 /// fn as_any(&self) -> &dyn core::any::Any { self }
182182 /// ```
183+ ///
184+ /// ## Troubleshooting
185+ /// A common reason why the dowcast fails at run-time is because of a type-mismatch
186+ /// between the model created and the model downcasted. To debug this at compile time,
187+ /// try matching the model type used for the downcast explicitly at model creation time.
188+ /// In the following example, the downcast fails at run-time:
189+ ///
190+ /// ```
191+ /// # use i_slint_core::model::*;
192+ /// # use std::rc::Rc;
193+ /// let model = VecModel::from_slice(&[3i32, 2, 1])
194+ /// .filter(Box::new(|v: &i32| *v >= 2) as Box<dyn Fn(&i32) -> bool>);
195+ /// let model_rc = ModelRc::new(model);
196+ /// assert!(model_rc.as_any()
197+ /// .downcast_ref::<FilterModel<VecModel<i32>, Box<dyn Fn(&i32) -> bool>>>()
198+ /// .is_none());
199+ /// ```
200+ ///
201+ /// To debug this, let's make the type explicit. It fails to compile.
202+ ///
203+ /// ```compile_fail
204+ /// # use i_slint_core::model::*;
205+ /// # use std::rc::Rc;
206+ /// let model: FilterModel<VecModel<i32>, Box<dyn Fn(&i32) -> bool>>
207+ /// = VecModel::from_slice(&[3i32, 2, 1])
208+ /// .filter(Box::new(|v: &i32| *v >= 2) as Box<dyn Fn(&i32) -> bool>);
209+ /// let model_rc = ModelRc::new(model);
210+ /// assert!(model_rc.as_any()
211+ /// .downcast_ref::<FilterModel<VecModel<i32>, Box<dyn Fn(&i32) -> bool>>>()
212+ /// .is_none());
213+ /// ```
214+ ///
215+ /// The compiler tells us that the type of model is not `FilterModel<VecModel<..>>`,
216+ /// but instead `from_slice()` already returns a `ModelRc`, so the correct type to
217+ /// use for the downcast is wrapped in `ModelRc`:
218+ ///
219+ /// ```
220+ /// # use i_slint_core::model::*;
221+ /// # use std::rc::Rc;
222+ /// let model: FilterModel<ModelRc<i32>, Box<dyn Fn(&i32) -> bool>>
223+ /// = VecModel::from_slice(&[3i32, 2, 1])
224+ /// .filter(Box::new(|v: &i32| *v >= 2) as Box<dyn Fn(&i32) -> bool>);
225+ /// let model_rc = ModelRc::new(model);
226+ /// assert!(model_rc.as_any()
227+ /// .downcast_ref::<FilterModel<ModelRc<i32>, Box<dyn Fn(&i32) -> bool>>>()
228+ /// .is_some());
229+ /// ```
183230 fn as_any ( & self ) -> & dyn core:: any:: Any {
184231 & ( )
185232 }
0 commit comments