On 12/31/25 6:42 PM, Joel Fernandes wrote:
On 12/31/2025 7:46 PM, John Hubbard wrote:
On 12/31/25 4:15 PM, Joel Fernandes wrote:
On Dec 31, 2025, at 5:47 PM, John Hubbard <[email protected]> wrote:
On 12/31/25 2:33 PM, Timur Tabi wrote:
On Wed, 2025-12-31 at 13:47 -0800, John Hubbard wrote:
The builder-pattern setters (self -> Self) enabled method chaining like:
reg.set_foo(x).set_sec(y).write(bar);
This made separate operations appear as a single expression, obscuring
that each setter is a distinct mutation.
So you're concerned about the fact that the compiler is not merging the
set_foo(x) and the
set_sec(y) into a single read-modify-write?
No, I don't care about that aspect.
These setters are infallible,
so the chaining provides no error-propagation benefit—it just obscures
what are simple, independent assignments.
Change the bitfield!() macro to generate `&mut self` setters, so each
operation is a distinct statement:
reg.set_foo(x);
reg.set_sec(y);
reg.write(bar);
Are you sure about this? It just seems like you're throwing out a neat little
feature of Rust and
replacing it with something that's very C-like. This breaks compatible with
all users of the regs
macros. Seems really disruptive for what seems to me like a cosmetic change.
It's only a neat feature if it *does* something. In this case, it *looks*
like a neat Rust feature, but under the covers it really is just handing
around copies unnecessarily, when really, it *is* doing the C-like thing
in the end.
I object to the fake Rust-ness that's being done here. It's like putting
hubcabs on a car.
But IMO there is only one operation here, the IO write. The setter is just
mutations. Builder pattern chaining is idiomatic to Rust.
I would not call it fake Rustness since it is Rustness in the Rust language.
Afair, similar arguments were made before and conclusion was, well, this is
Rust.
There is nothing about doing sequential .set_foo() calls that goes against
Rust idioms.
Huh, I just meant we should "Ok" with and inclined to be using Rust idioms even
though they may seem unfamiliar at first.
But this really is fake chaining, because there are no Results involved.
It's not buying us anything except a bit of indirection and cognitive
load for the reader.
Chaining is not really only about error propagation. Builder pattern can be used
for other cases too, like passing a setter chained expression to a function
argument for better clarity, I was planning to do that for the sequencer for
instance since there's a lot of parameters passed to it.
Let's see if that has any use for this.
So far, though, in the code base that we have today, there is absolutely
zero benefit. The diffs here prove it.
But in this case, I am actually absolutely opposed against this, it makes the
API hard to use because now how do you differentiate between an IO function call
versus something that just mutates memory? Is set() an IO or write()?
That's a completely separate, pre-existing issue with the API.
reg.set_foo(x); // no IO
reg.set_sec(y);
reg.write(bar); // IO.
So no thank you, I quite dislike it. :)
Instead with chaining, we can just rely on the last part of the chain concluding
in a write() with the intermediaries just mutating memory.
Same as above, just a more happy-happy chaining interface, but the same
function calls must be made in the same order.
The main benefit of chaining is really in the Result's that allow
an early return from the whole thing. If one is not using that, the
benefits drop sharply off.
Further, your suggestion could also make it easier to introduce bugs?
reg.set_foo(x);
reg.write(bar);
reg.set_sec(y);
While this is also possible to mess up with the register macro, it is much
harder to do with chaining since there is no opportunity to interleave a write()
incorrectly.
Regarding the copies, I am intrigued - have you verified that the code
generation actually results in copies? I would be surprised if the compiler did
not optimize.
No no, I just mean conceptually using Copy instead of a mutable Self.
Conceptually, but the compiler would not do any copies through the setter chain
was my point though. Note that all setters are #[inline(always)], the compiler
No argument about the actual copies. My point here is about the API and
how we use it and understand it.
thanks,
--
John Hubbard