You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is an annoying issue, possibly best left until mut generics is available.
If nothing else, this serves as an exemplar of what we might want mut generics to achieve.
Problem
fn Layout::draw (i.e. widget draw) takes &mut self. Implementations only require &self, except those using a layout visitor. (The same is true of fn try_probe while fn size_rules and fn set_rect impls do require &mut self.)
Background
Macro-generated layout implementations actually implement this trait:
pubtraitLayoutVisitor{/// Layout defined by a [`Visitor`]fnlayout_visitor(&mutself) -> Visitor<implVisitable>;}
which uses these:
/// A sub-set of [`Layout`] used by [`Visitor`].////// Unlike when implementing a widget, all methods of this trait must be/// implemented directly.#[crate::autoimpl(for<T:trait + ?Sized> &'_ mutT,Box<T>)]pubtraitVisitable{/// Get size rules for the given axis////// This method is identical to [`Layout::size_rules`].fnsize_rules(&mutself,sizer:SizeCx,axis:AxisInfo) -> SizeRules;/// Set size and position////// The caller is expected to set `self.core.rect = rect;`./// In other respects, this functions identically to [`Layout::set_rect`].fnset_rect(&mutself,cx:&mutConfigCx,rect:Rect,hints:AlignHints);/// Look for a widget at this `coord`////// Returns the [`Id`] of a child when some child occupies `coord`. Returns/// [`None`] when there is no (probable) child widget at `coord`, in which/// case the caller may use its own [`Id`].fntry_probe(&mutself,coord:Coord) -> Option<Id>;/// Draw a widget and its children////// This method is identical to [`Layout::draw`].fndraw(&mutself,draw:DrawCx);}/// A layout visitor////// Objects are generated by [`layout`] syntax. These all have limited lifetime.////// [`layout`]: crate::widget#layout-1pubstructVisitor<V:Visitable>(V);
The actual implementation of fn Layout::draw is then just LayoutVisitor::layout_visitor(self).draw(draw).
Solutions
The first solution is to simply ignore the problem: fn draw receives &mut self even though it doesn't "need" it. This is the simplest (and perhaps best) option.
The "obvious" alternative is to let fn draw and fn try_probe receive &self, but this is not trivial to implement. Details below.
A const layout visitor
fn LayoutVisitor::layout_visitor must take &mut self in order to support fn Visitable::set_rect (and fn size_rules). If we wanted to support const (non-mut) usage, we'd need another method, fn layout_visitor_const(&self). Since this method's return value cannot implement fn Visitable::set_rect (which requires &mut self), we'd need to split the Visitable trait.
A possible result of this is:
#[crate::autoimpl(for<T:trait + ?Sized> &'_ T,Box<T>)]pubtraitVisitableConst{fntry_probe(&self,coord:Coord) -> Option<Id>;fndraw(&self,draw:DrawCx);}#[crate::autoimpl(for<T:trait + ?Sized> &'_ mutT,Box<T>)]pubtraitVisitable:VisitableConst{/// Get size rules for the given axis////// This method is identical to [`Layout::size_rules`].fnsize_rules(&mutself,sizer:SizeCx,axis:AxisInfo) -> SizeRules;/// Set size and position////// The caller is expected to set `self.core.rect = rect;`./// In other respects, this functions identically to [`Layout::set_rect`].fnset_rect(&mutself,cx:&mutConfigCx,rect:Rect,hints:AlignHints);}pubstructVisitor<V:VisitableConst>(V);pubtraitLayoutVisitor{fnlayout_visitor_const(&self) -> Visitor<implVisitableConst>;fnlayout_visitor(&mutself) -> Visitor<implVisitable>;}
This approach is probably viable, though now all implementations of LayoutVisitor must write impls for both fn layout_visitor and fn layout_visitor_const despite the impls being mostly identical. mut-generics should allow these to collapse down into a single impl, assuming the generics also apply to the trait Visitable.
const Visitable
We described trait VisitableConst above, which is required to support implementations of fn layout_visitor_const. In practice, this is just an artifact required by the type system. We would never want to impl VisitableConst without implementing Visitable (mut).
It would be neater if we could simply write const Visitable (or maybe Visitable<const>).
Const visitors
Visitor<impl Visitable> objects are provided by visitor methods, e.g. fn Visitor::single(widget: &'a mut dyn Layout) returns Visitor(Single { .. }) using
For the above, we'd need a const alternative, fn single_const(widget: &'a dyn Layout).
The implementation object could remain the same struct Single type, if its generics change to Single<W> { widget: W }, however it would now need at least two, possibly three impl blocks (VisitableConst for Single<&'a dyn Layout>, VisitableConst for Single<&'a mut dyn Layout, Visitable for Single<&'a mut dyn Layout>) instead of just one.
The text was updated successfully, but these errors were encountered:
This is an annoying issue, possibly best left until
mut
generics is available.If nothing else, this serves as an exemplar of what we might want
mut
generics to achieve.Problem
fn Layout::draw
(i.e. widget draw) takes&mut self
. Implementations only require&self
, except those using a layout visitor. (The same is true offn try_probe
whilefn size_rules
andfn set_rect
impls do require&mut self
.)Background
Macro-generated layout implementations actually implement this trait:
which uses these:
The actual implementation of
fn Layout::draw
is then justLayoutVisitor::layout_visitor(self).draw(draw)
.Solutions
The first solution is to simply ignore the problem:
fn draw
receives&mut self
even though it doesn't "need" it. This is the simplest (and perhaps best) option.The "obvious" alternative is to let
fn draw
andfn try_probe
receive&self
, but this is not trivial to implement. Details below.A
const
layout visitorfn LayoutVisitor::layout_visitor
must take&mut self
in order to supportfn Visitable::set_rect
(andfn size_rules
). If we wanted to support const (non-mut) usage, we'd need another method,fn layout_visitor_const(&self)
. Since this method's return value cannot implementfn Visitable::set_rect
(which requires&mut self
), we'd need to split theVisitable
trait.A possible result of this is:
This approach is probably viable, though now all implementations of
LayoutVisitor
must write impls for bothfn layout_visitor
andfn layout_visitor_const
despite the impls being mostly identical.mut
-generics should allow these to collapse down into a singleimpl
, assuming the generics also apply to the traitVisitable
.const Visitable
We described
trait VisitableConst
above, which is required to support implementations offn layout_visitor_const
. In practice, this is just an artifact required by the type system. We would never want to implVisitableConst
without implementingVisitable
(mut).It would be neater if we could simply write
const Visitable
(or maybeVisitable<const>
).Const visitors
Visitor<impl Visitable>
objects are provided by visitor methods, e.g.fn Visitor::single(widget: &'a mut dyn Layout)
returnsVisitor(Single { .. })
usingFor the above, we'd need a const alternative,
fn single_const(widget: &'a dyn Layout)
.The implementation object could remain the same
struct Single
type, if its generics change toSingle<W> { widget: W }
, however it would now need at least two, possibly threeimpl
blocks (VisitableConst for Single<&'a dyn Layout>
,VisitableConst for Single<&'a mut dyn Layout
,Visitable for Single<&'a mut dyn Layout>
) instead of just one.The text was updated successfully, but these errors were encountered: