ChanServ changed the topic of #rust-embedded to: Welcome to the Rust Embedded IRC channel! Bridged to and logged at, code of conduct at
d3zd3z[m] has joined #rust-embedded
<d3zd3z[m]> In some experimenting with building rust with Zephyr, I am running into an issue with multiple definitions of __aebi_idiv, one coming from libgcc.a, and the other coming from the app .a built by cargo. Any thoughts or suggestions?
<JamesMunns[m]> the solutions are "weaken the symbols in one, or remove the symbols in one, so you don't have dupes; OR mangle the names in each compilation graph so they don't collide"
<JamesMunns[m]> there's an outstanding issue for it
<JamesMunns[m]> d3zd3z is the authoritative issue afaik
<d3zd3z[m]> For now, I've gotten past things with -Wl,--allow-multiple-definitions, but I'll need to figure out a better solution at some point.
stgl has quit [Quit: ZNC 1.8.2 -]
stgl has joined #rust-embedded
K900 has quit [Quit: Idle timeout reached: 172800s]
albus_dandelion[ has joined #rust-embedded
<albus_dandelion[> Hello! I'm trying to build oreboot for allwinner d1, but only get rust-lld: error: undefined symbol: sbss and rust-lld: error: undefined symbol: ebss errors. Can someone tell what I'm doing wrong?
<diondokter[m]> albus_dandelion[: Sounds like those should come from the linker script. Check if you've included the linkerscript in your build and that it is correct
<albus_dandelion[> Idk if I should include something myself. I'm just trying to build existing makefile. Already reinstalled everything, checked the version, check that rust-ldd has linked correctly and idk what else to do
<diondokter[m]> albus_dandelion[: Does oreboot know about that board? It will need some memory layout definition. If the project knows about that board, it might provide a default linker script, but if not you will have to provide it
<albus_dandelion[> Yes, it has support for it right on the main page
<diondokter[m]> albus_dandelion[: Ok, then that should work I guess. No idea then. Maybe ask the oreboot devs or community. I don't know if there are any oreboot people here
<albus_dandelion[> Thank, guess I should contact them somehow 
seds has quit [Ping timeout: 256 seconds]
seds has joined #rust-embedded
starblue has quit [Ping timeout: 255 seconds]
starblue has joined #rust-embedded
NiaLinaLunaStorm has quit [Quit: Idle timeout reached: 172800s]
explodingwaffle1 has quit [Quit: Idle timeout reached: 172800s]
ilpalazzo-ojiis4 has quit [Quit: Idle timeout reached: 172800s]
thejpster[m] has quit [Quit: Idle timeout reached: 172800s]
hmw has quit [Quit: Bye.]
hmw has joined #rust-embedded
hmw has quit [Client Quit]
hmw has joined #rust-embedded
hmw has quit [Client Quit]
hmw has joined #rust-embedded
qzl[m] has quit [Quit: Idle timeout reached: 172800s]
tangotaylor[m] has joined #rust-embedded
<tangotaylor[m]> Hey all! I'm new here. I've got a question about test-driven development. Coming from a C background, what I like to do is set up [Unity]( within a simulator (like QEMU or in [Keil MDK]( ) so that I use the exact same compiler for testing as I do for production. Unity's great because it's made for a "no_std"-style environment.
<tangotaylor[m]> I've been playing with the [f3discovery]( repo and the best I could do so far was use tons of `#![cfg_attr(not(test), no_std)]` to compile the tests for x64 on my host then compile for arm on the target. Haven't figured out emulator testing. Anyone have experience with this, running tests in the same environment as the target?
dngrs[m] has joined #rust-embedded
<dngrs[m]> <tangotaylor[m]> "Hey all! I'm new here. I've..." <- You can do qemu tests - for an example check out `firmware/qemu` in the defmt repo at
<dngrs[m]> General article for embedded rust TDD:
DanielHershcovic has joined #rust-embedded
<DanielHershcovic> Hi guys I just bought my BBC MICRO v2 for the discovery book. When I tried to run cargo `embed --target thumbv7em-none-eabihf` on my windows PC - I got a long error message.
<DanielHershcovic> The end looked like this:
<DanielHershcovic> * Hi guys I just bought my BBC MICRO v2 for the discovery book. When I tried to run cargo `embed --target thumbv7em-none-eabihf` on my windows PC - I got a long error message.... (full message at <>)
korken89[m] has quit [Quit: Idle timeout reached: 172800s]
<JamesMunns[m]> Do you have another development board plugged in?
<DanielHershcovic> No
<JamesMunns[m]> It looks like cargo embed sees two debugger chips for some reason, when there should only be one if the microbit is the only thing plugged in.
<JamesMunns[m]> Ahhh, it's picking up the dap and dapv1 endpoints. Maybe try asking in probe-rs, they should be able to help you select the right option!
<JamesMunns[m]> (the vid/PID/serials are the same, so I assume it's just different endpoints on the same device?)
<DanielHershcovic> Thats what I thought but had no idea what to do with that information. I looked around the probe-rs docs for a way to index into that array and choose [0], but had no luck. I'll try talking with them on their channel. Thanks for the time!
adamgreig[m] has quit [Quit: Idle timeout reached: 172800s]
Guest7282 has joined #rust-embedded
Guest7282 has left #rust-embedded [Error from remote client]
Foxyloxy_ has joined #rust-embedded
Foxyloxy_ has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
Foxyloxy_ has joined #rust-embedded
Foxyloxy_ has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
Foxyloxy_ has joined #rust-embedded
Foxyloxy_ has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
Foxyloxy_ has joined #rust-embedded
adamgreig[m] has joined #rust-embedded
<adamgreig[m]> Might be a few mins late starting our meeting this evening, seeya all soon!
thejpster[m] has joined #rust-embedded
<thejpster[m]> uuuuhhh, better cycle fast from the office to my house
<cr1901> I'm kinda-sorta here. Probably mostly read only
Foxyloxy_ has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
Foxyloxy_ has joined #rust-embedded
<adamgreig[m]> hi @room , meeting time again! agenda is, please add anything you have to announce or discuss and we'll start in a few mins. once i finish adding anything to the agenda :P
<adamgreig[m]> ok, let's start! I just have the one announcement about svdtools 0.3.11 release 🎉
<adamgreig[m]> Adam Hott: I think you're adding a question to last week's minutes
<thejpster[m]> I added a second :)
<adamgreig[m]> please go ahead thejpster
jannic[m] has joined #rust-embedded
<jannic[m]> Really 0.3.11? On I only see 0.3.10.
<thejpster[m]> Nominations are open for the t-launching-pad rep. Anyone in any launching pad team may nominate another member (or themselves).
AdamHott[m] has joined #rust-embedded
<AdamHott[m]> adamgreig[m]: fixed!
<adamgreig[m]> jannic: ah, the release PR is open but not yet merged
<adamgreig[m]> thejpster: thanks! do you wanna say anything about the role?
<thejpster[m]> it's fun! Sitting on the council lets you see inside and how the sausage gets made.
<adamgreig[m]> thanks, and thanks for being our rep so far too :)
<adamgreig[m]> next up, mabez?
mabez[m] has joined #rust-embedded
<mabez[m]> So I've found the aligned crate was missing some features. It looked unmaintained at the time, so I pinged Jorge an email and he has given me access and the option to transfer is somewhere if appropriate - so basically, is that something we want to do?
<mabez[m]> My initial suggestion would be to transfer to rust-embedded-community
vollbrecht[m] has joined #rust-embedded
<vollbrecht[m]> its about this crate ?
<mabez[m]> vollbrecht[m]: Correct
<adamgreig[m]> if it came to r-e it would probably be the libs team, so could see if they are interested ( dirbaio, newam, reitermarkus), but no objection to r-e-c
Foxyloxy_ has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
Foxyloxy_ has joined #rust-embedded
<dirbaio[m]> o/
<dirbaio[m]> libs team sounds good to me too, no preference for either
<adamgreig[m]> \o
<mabez[m]> Looking at the dependents of aligned, its not that widely used, but I plan to use it for some block device traits, and I believe dirbaio mentioned having alignment as part of the embedded storage traits
<mabez[m]> * dirbaio mentioned the possibility of having alignment
<mabez[m]> If no objections to transferring to r-e, I'll get that done asap
<vollbrecht[m]> not a lot of dependents but remove_dir_all with 80 million dll's a high impact one ;D
<jannic[m]> I guess the API could be updated using const generics? Otherwise, I don't think it'll see updates very often. So it probably doesn't matter much where it's hosted, as long as it's not completely unmaintained.
<thejpster[m]> We should probably have some rules about what goes into /rust-embedded and what doesn't.
<thejpster[m]> Like "the ecosystem would be a split in a harmful way if this wasn't in".
<mabez[m]> jannic[m]: There is already a better crate called `elain` that does that. It's really nice, but for my use case I ran into limitation of const generics so I fell back to `aligned`
<thejpster[m]> Because putting things "in" will naturally discourage anyone from developing a competitor that is "out".
<mabez[m]> > <> I guess the API could be updated using const generics? Otherwise, I don't think it'll see updates very often. So it probably doesn't matter much where it's hosted, as long as it's not completely unmaintained.
<mabez[m]> * There is already a better crate called `elain` that does that. It's really nice, but for my use case I ran into limitations of (stable) const generics so I fell back to `aligned`
<thejpster[m]> And competition is generally good. Except where we decide it is bad. Like the HAL traits.
<adamgreig[m]> currently the general policy is "if the relevant team decide they want it and are happy to look after it"
<adamgreig[m]> but it might well make sense to have some general guidelines for what sort of project is generally a good idea and what isn't, I think what you describe is more or less what we aim for but it's not written down
<dirbaio[m]> I wouldn't say elain is better either... despite using const generics it only works with a fixed set of alignments
<thejpster[m]> I wouldn't veto it being in r-e/libs, but r-e-c seems like a more natural fit. Unless you tell me that having two kinds of alignment in one binary is bad or something.#
<mabez[m]> dirbaio[m]: If `generic_const_exprs` ever gets stabilized it could be truly generic though I think
<thejpster[m]> s/.#/./
<dirbaio[m]> the point of const generics is the alignment could be the output of some maths calculation. but even with generic_const_exprs it won't work if it's impl'd for a fixed set of const generic values
<dirbaio[m]> because the compiler can't prove the output of the math is always one of those values
bartmassey[m] has joined #rust-embedded
<bartmassey[m]> Just wanted to let everyone know that it looks like a 0.16.1 release of nrf-hal is imminent. Discussion is on this issue
<bartmassey[m]> Thanks to @qwandor for huge work on this.
<bartmassey[m]> One big blocker is that I don't know who has permission to publish this crate. @qwandor doesn't and I don't think I do. If you do or know someone who does, please have them check out the issue above.
<adamgreig[m]> it's public on, whoever is listed as the owner on etc
<adamgreig[m]> (if a github team, then all members of that team)
<thejpster[m]> On that crate it is James and the github team nrf-rs/nrf52 ( which has 13 people in it.
<thejpster[m]> two of whom are me, apparently.
<adamgreig[m]> jpster and nega-jpster :D
<bartmassey[m]> I think @qwandor is a member of the team. Maybe there's something they need to do with cargo publish?
<bartmassey[m]> I'll look into it.
<bartmassey[m]> Oh nvm. There's a separate nrf52 team and we're not on it. Can we be added?
Foxyloxy_ has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
<bartmassey[m]> Dangit I'm wrong. We are on it. So IDK. Sorry for the spam.
<mabez[m]> Going back to aligned, I guess I'll try and get it transferred to r-e-c then, we can always move it to r-e after if we wish. I'd just like to get it out from a personal account
Foxyloxy_ has joined #rust-embedded
<adamgreig[m]> Adam Hott: wanna ask your question?
<AdamHott[m]> yes, about the Discovery Book. One of the things I ran into when I was learning earlier on, was trying to figure out how the individual files of and embedded project work together. I wondered if it would be helpful to have a section in the Discovery Book to talk about these files, with definitions or summaries and how it all connects?
<AdamHott[m]> If it's helpful, I'm happy to work on that.
<AdamHott[m]> Also bartmassey thanks for noting the issues with the microbit project template!
<bartmassey[m]> I think that would be great. I think most of the information is already there, but kind of scattered throughout the Book.
<AdamHott[m]> ok thanks, I'll take that on
eldruin[m] has joined #rust-embedded
<eldruin[m]> That sounds useful to me!
<AdamHott[m]> Anyone think it's redundant?
<AdamHott[m]> Or not relevant for the context of the Discovery Book?
<bartmassey[m]> One caveat is that much of it will change for the Embassy MB2 Discovery book, so it may have to be done twice. 😀
<AdamHott[m]> Ah gotcha, maybe I can get it started then and we can adjust it
<bartmassey[m]> A bit off-topic, but I'm really getting into exploring the Embassy MB2 ecosystem right now. Great stuff!
<AdamHott[m]> Embassy is very cool!
<bartmassey[m]> Sorry gtg to next meeting. I'll check later for anything I missed.
<adamgreig[m]> does anyone else have anything to discuss?
<AdamHott[m]> I'm starting to be forced to look at C and C++ code for transferring over to Rust projects, and I think I need to decide one of those to study a bit but I don't know which one to pick. Any recommendations?
relia1[m] has joined #rust-embedded
<relia1[m]> As someone new to embedded and Rust having a section that can be quickly referenced would be specifically useful.
<relia1[m]> * As someone new to embedded and Rust having a section that can be quickly referenced would specifically be useful.
<bartmassey[m]> Adam Hott: The learning curve for C is lower in my opinion. I'd start there. Most everything you learn will be transferable to C++, which is a much more complex language.
<adamgreig[m]> ok, let's end the meeting there then, thanks everyone!
<AdamHott[m]> thanks all!
Foxyloxy_ has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
Foxyloxy_ has joined #rust-embedded
rault[m] has joined #rust-embedded
<rault[m]> Hi guys, i did my first works using the embedded-hal during last year, but it was for i2c and spi devices.... (full message at <>)
<dirbaio[m]> the idea is the same, you write your driver using embedded-io
<dirbaio[m]> then you can use it with any serial/uart implementation that implements the embedded-io traits
<dirbaio[m]> IO is a bit different, because the std::io traits already exist and are in widespread use outside embedded
<dirbaio[m]> like, serialport implements std::io::{Read, Write}
<dirbaio[m]> but not embedded-io
<dirbaio[m]> so you have to use an adapter to convert it from std::io to embedded-io:
<dirbaio[m]> with that, it'll work with any driver using embedded-io
<dirbaio[m]> while HALs that already designed for embedded (like esp-hal, embassy-stm32, etc) implement embedded-io directly, so you don't have to use any adapter there
<rault[m]> nice! so basically i can write the library using the embedded-io,
<rault[m]> then on examples (that will run on a raspberry), I just select it to use serialports and it will be abble to use it, or from any microcontroller that wants to
Foxyloxy_ has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
<rault[m]> the thunderbird client missed the previous msgs :S can't see who replied, but thks!
Foxyloxy_ has joined #rust-embedded
<dirbaio[m]> you can see chat history here in case you missed stuff
Foxyloxy_ has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
Foxyloxy_ has joined #rust-embedded
Foxyloxy_ has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
Foxyloxy_ has joined #rust-embedded
Foxyloxy_ has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
Foxyloxy_ has joined #rust-embedded
Foxyloxy_ has quit [Quit: My Mac has gone to sleep. ZZZzzz…]
<d3zd3z[m]> I'm trying to come up with the best way to manage various Zephyr structures with Rust. The `k_timer` struct is a typical example. In C Zephyr code, instances are almost always statically allocated, and just referenced throughout the code, which isn't very Rust-like, and not very safe. Some thoughts I had were: 1. Make the Rust type pinned, along with the complexity of properly using a pinned type as a stack variable. 2. Have the
<d3zd3z[m]> Rust type have an internal `Pin<Box<T>>` that is heap allocated. This is more convenient, but then requires the heap. 3. Keep static, and have something to help manage them? Thoughts?
<d3zd3z[m]> The structures contain internal pointers that Zephyr uses while the structure is active (they will be linked into scheduler structures and such).
<JamesMunns[m]> I mean, does zephyr provide any indication that the item is live or not? Ref counting, etc?
<JamesMunns[m]> if the liveness properties are "trust me bro", then yeah, you probably want an `unsafe` constructuro
<JamesMunns[m]> s/constructuro/constructor/
<JamesMunns[m]> I guess the question is:
<JamesMunns[m]> 1. what are the liveness guarantees/properties?
<JamesMunns[m]> 2. what are the mutability guarantees/properties?
<d3zd3z[m]> The liveness depends on the item and available apis, but most things would generally have something that would be like drop that would make them no longer live. In the real zephyr world, things generally aren't deallocated, but it is usually doable with the API.
<d3zd3z[m]> The APIs for these items will usually want mutability, and there is going to be actual hidden mutation happening by the kernel. But, the APIs should map reasonably to how Rust wants mut.
<d3zd3z[m]> They do get a lot messier when they expect callbacks to be registered that get called in weird contexts.
<d3zd3z[m]> Fortunately, there has been a trend in Zephyr to move away from using callbacks, to more of threads, with calls that block.
<JamesMunns[m]> smells like something you either need to:
<JamesMunns[m]> * expose some kind of refcounting and mutex behavior on the C side, to ensure that an item can't be concurrently dropped or modified, OR
<JamesMunns[m]> * it's all unsafe on the Rust side
<JamesMunns[m]> (tho tbh, precedence probably says "don't trust C" if it's possible C could drop or mutate the structure unsynchronized
<JamesMunns[m]> * structure unsynchronized)
<d3zd3z[m]> I'm not sure I see where this aspect is an issue from the Rust side. As far as the API is concern, there is an initializer to make one, calls to do things to it, and a finalizer to make it no longer used. Making them unsafe wouldn't affect that.
<d3zd3z[m]> Nothing will be dropping them. And the mutations are hidden behind the API.
<d3zd3z[m]> My question is more that these things need to be pinned, and pinned things are a hassle to deal with in Rust.
<JamesMunns[m]> gotcha! Maybe I was misunderstanding your question.
<d3zd3z[m]> I'm wondering if I should have a static pool of them that the actual objects come from.
<d3zd3z[m]> Ideally, I'd like to be able to provide something usable in Rust like std::sync::Mutex, but that uses the Zephyr item.
johnmcnuggets has joined #rust-embedded
Foxyloxy_ has joined #rust-embedded
<d3zd3z[m]> For reference, std's Mutex on Posix does allocate the underlying items, and I probably need to at least manage that in some way to keep similar usage in Rust.
Foxyloxy_ has quit [Ping timeout: 246 seconds]
<JamesMunns[m]> So, the three relevant safety items:... (full message at <>)
<d3zd3z[m]> I believe the underlying Zephyr item will have to be Pinned, as it must not be moved or replaced.
<JamesMunns[m]> Fair! Then yes, I'd agree `Pin<&mut Timer>` or `Pin<&InnerMutableTimer>` makes sense
<JamesMunns[m]> ANY reference prevents moving (well - invalidation of the referenced item, wholesale replacement is allowed), but only Pin prevents replacement.
<JamesMunns[m]> * prevents moving and enforces liveness (well -
<adamgreig[m]> would it be so weird to just make them statics in rust if they're statically allocated in c?
<adamgreig[m]> with some sort of wrapper around them to manage the relevant invariants, but still static access
johnmcnuggets has quit [Changing host]
johnmcnuggets has joined #rust-embedded
<JamesMunns[m]> idk what the timer struct does, but a static mut with unsafe access still allows core::mem::swap. d3zd3z seems pretty emphatic about not wanting to allow that.
<d3zd3z[m]> They don't have to be statically allocated in C, they just usually are.
<adamgreig[m]> you can only swap it with unsafe, which is also true of pinned things, no?
<adamgreig[m]> I mean, if it's just unsafe access
<JamesMunns[m]> adamgreig[m]: I mean you can only anything with mutable statics with unsafe
<d3zd3z[m]> It is very important that something like swap not be done. The kernel stores things pointers inside of the struct while it is live.
<adamgreig[m]> I'm imagining you don't just have a `static mut` but instead some sort of wrapper that manages access including not giving out an &mut to the whole structure that you could swap with
<d3zd3z[m]> But, I wasn't expecting to export the inner timer structure (outside of a sys crate).
<adamgreig[m]> (and so a normal non-mut static)
<d3zd3z[m]> There would be something like Mutex that works like a std::sync::Mutex, and it manages this inner one that is the thing that has to be pinned or managed. Not sure if pinning is necessary if it is never exposed, though.
<d3zd3z[m]> But, my real question was how to allocate them. I could just use the heap, but that seems kind of unfriendly for an embedded system.
<d3zd3z[m]> Maybe with the possibility of an unsafe initializer that can initialize them from a static for the users that don't want them heap managed.
<JamesMunns[m]> like I said, it depends on the liveness properties. Where are they allocated, and how is this represented in Rust
<JamesMunns[m]> if it is allocated in C and "lives forever" to Rust, then `Pin<&'static Whatever>` is fine
<d3zd3z[m]> Well, the allocated version would be allocate, then made alive to Zephyr, and as part of its drop, it would be unitialized from Zephyr's point of view.
<JamesMunns[m]> Otherwise you could use something like static_cell::StaticCell or grounded::alloc_single::AllocSingle
<d3zd3z[m]> One with an unsafe static initializer would be initialized and deinitted the same way, but wouldn't deallocate.
<JamesMunns[m]> or a global alloc, or whatever
<JamesMunns[m]> d3zd3z[m]: but yeah, you can use `alloc::boxed::Box`, or a reasonable facsimile of your own.
<d3zd3z[m]> I will have to figure out some of the single stuff when I get to devices, as those tend to be structures that are built as C statics by the toolchain, but at least as far as Rust goes, I'd like to only see a single instance of them. But, that would end up like how PAC crates usually do things.
<JamesMunns[m]> But these are a means to an end - if you wanted to have SHARED access you should use refcounting or whatever to make sure you don't drop it until nobody has it anymore
<JamesMunns[m]> d3zd3z[m]: for this sort of behavior the two crates I linked are options
<d3zd3z[m]> Box definitely works. Am I correct in assuming that as long as this isn't exposed to anyone, it won't get moved.
<JamesMunns[m]> d3zd3z[m]: boxes are never moved, Pin<Box<T>>` means the T won't be swapped out of the box either.
<d3zd3z[m]> If the timer needs to be shared, that could be managed with something like `Arc<Rc<Mutex>>`.
<d3zd3z[m]> I don't think these structures should be managing their own sharing.
<JamesMunns[m]> d3zd3z[m]: Yeah, `Arc<Mutex<Timer>>` is fine too
<d3zd3z[m]> Well, actually `Arc<Mutex>` should be sufficient, I guess I'll need to probably handle that one specifically.
<JamesMunns[m]> however you need to mediate the shared mutable access.
<d3zd3z[m]> But, a Mutex around a timer makes sense. Given that I don't think they are intended to be shared on the Zephyr side, that is probably fine.
<JamesMunns[m]> but Arc/Box are about "ensuring it lives long enough", Mutex is about "ensuring shared XOR mutable access", Pin is about "thou shalt not replace"
<JamesMunns[m]> it's possible you need all three, as you've described it.
<JamesMunns[m]> ah, RwLock would be Shared XOR Mutable, Mutex is just "one at a time" access :)
<d3zd3z[m]> I'm just wondering if I explicitly need to use Pin on an internal field that is a reference. Say I have a private field that is Box. It is private, so no user of my type should be able to get to it to do something like replace, and if they replaced the Mutex, rust will make sure the lifetime is managed properly, and drop gets called if the replacement makes one of them go away. At least as I understand things.
<d3zd3z[m]> And, if I want my item to work with both a user-specified unsafe pointer, or with my own managed Box, I can make my own enum for that.
<JamesMunns[m]> `&mut` access authorizes full replacement. If you can't name the (sub) field because it is private, you can't safely replace it
<JamesMunns[m]> Having an `&mut Example` would allow you to replace ALL of the `Example` safely (if you can make a new one to replace the ref with), or replace `alpha`, but not `beta`.
<JamesMunns[m]> Most smart pointers like Box give you a `&mut Example` when you have a `Box<Example>` because of `DerefMut`
<JamesMunns[m]> replacing a pub field, as well as the whole struct, allowing you to forget the potentially side-effectful drop fields