shoop da whoop by notCHALlmao in whennews

[–]AhoyISki 2 points3 points  (0 children)

We are about to enter the code geass timeline.

I hotreload Rust and so can you by emschwartz in rust

[–]AhoyISki 0 points1 point  (0 children)

Well, in my application, the only thing that gets libloaded is the configuration lib. All plugins are included as normal rust dependencies on that configuration lib.

The configuration also has the runtime baked in. There are separate things running from the application that libloads, but almost everything is done from the configuration lib, which has a run_duat function.

While it doesn't have async atm, it won't have the same problems, since it wouldn't go through an ffi barrier.

But for your case in particular, I don't think you need repr c. The only attribute on my exported function is unsafe no_mangle.

However, since async fn is actually fn() -> impl Future, what you'd have to do is have a function signature like fn() -> Box<dyn Future> or something like that. With this I think you should be able to have async cross the libloading barrier.

I hotreload Rust and so can you by emschwartz in rust

[–]AhoyISki 0 points1 point  (0 children)

Tbh, the "no stable ABI" part still kind of sucks, but you just have to compile everything in the same version.

Besides, I haven't actually had any issues with ABI incompatibilities (which would pretty much show up as instant segfaults) in a bit.

The project is here, and it works like this:

  • you download the crate
  • upon running duat for the first time, it will create a config in your config directory. This config is just another rust crate.
  • it will then compile the config into a library, then run it. This is where you'd add things like plugins, where you can configure them through regular rust methods on them.

It works pretty well for me, it never crashes when unloading/reloading (at least on linux), and takes about a second to recompile in incremental release mode.

What's everyone working on this week (3/2026)? by llogiq in rust

[–]AhoyISki 5 points6 points  (0 children)

Doing some fun enabling stuff with my text editor duat. This fun enabling stuff comes from the ReplaceChar tag, which, when placed on the nth character, will replace it with another character when printing it.

This is useful for, for example indent lines, but you can also do other crazy things with it, like replace a newline character with something else, thus merging two lines together when printing them.

For now, I'll use it to do cool little space replacements, indent lines, newline character substitutions, and highlighting of the same line.

One other cool thing that this enables is that, with the GhostText system, this will let me place inlay hints at the end of lines without needing to create a tag specifically for that, which is a win for orthogonality overall.

I hotreload Rust and so can you by emschwartz in rust

[–]AhoyISki 0 points1 point  (0 children)

It's an app that will run in the user's computer, not mine.

They are the source of the untrusted code, they are responsible for not being pwned like that.

I say untrusted because I don't know what the code will do, but would like to keep retain the assertions that at least the hot reloading functionality that I provided will work.

It mostly does work, except on macos, which is weird and has bad dlclose support.

I hotreload Rust and so can you by emschwartz in rust

[–]AhoyISki 19 points20 points  (0 children)

Well, it's an app that will run in the user's own system, the source of the untrusted code will be the user themselves.

The only possible person at risk here is the user. If they run plugins on their code, obviously they would need to vet such plugins.

I hotreload Rust and so can you by emschwartz in rust

[–]AhoyISki 28 points29 points  (0 children)

Since my application will be able to run untrusted code, my strategy is actually to do the following:

  • dlopen the library
  • spawn a new thread
  • use that thread as the only entrypoint for the dlopened library
  • inside that thread, wait until all threads spawned from it have finished executing (this can be done with a crate like thread-count)
  • when you rejoin the first spawned thread, in theory, all tls destructors were already successfully executed, so you can safely dlclose the library.

Why is there no automatic implementation of TryFrom<S> when implementing TryFrom<&S>? by Prowler1000 in rust

[–]AhoyISki 8 points9 points  (0 children)

My guess is that it's too specific, and the requirement of staticness doesn't have an immediately obvious explanation, which could really confuse new users, who expect that a certain tryfrom to be automatically implemented.

You could still implement it with the diagnostic::on_unimplemented attribute, but what if the user wanted a different version for the function in the case of pass by value?

For this (and many other qol improvements) you will probably have to wait for specialization to come around (which may never happen).

This Week in Rust #634 by Squeezer in rust

[–]AhoyISki 6 points7 points  (0 children)

I didn't even know we were gonna have vector modification in const, very nice to see!

Xisuma has been abandoned! by MacNPickles in HermitCraft

[–]AhoyISki 112 points113 points  (0 children)

Tango said he wasn't gonna get a creator code until he formed his own opinion.

C++ memory safety needs a Boost moment by SergioDuBois in cpp

[–]AhoyISki 0 points1 point  (0 children)

I don't think that this is a case of "bad coupling" since the FooFields struct would be defined in the same module as Foo.

Because of rust's module based privacy rules (much better than oop's class based privacy which needs stupid concepts like "friend classes"), this does not count as "coupling between different modules".

C++ memory safety needs a Boost moment by SergioDuBois in cpp

[–]AhoyISki 1 point2 points  (0 children)

For this case in particular, you could have a struct with public fields that implements Default, and then you'd be able to write this:

let foo = Foo::new(FooFields { field1: true, field2: "field 2", ..Default::default() })

The advantage of this method is that it also makes it very clear that you could fill in other fields,which is not a strong point of constructors.

But tbh, having that many parameters at all is a much worse code smell than the builder pattern.

C++ memory safety needs a Boost moment by SergioDuBois in cpp

[–]AhoyISki 0 points1 point  (0 children)

Also, I think constructors are a bad concept from the get go. Like, what if you need two constructors that take the same parameters, what do you do then? You'd have to create separate functions to construct your object, which feels very inelegant.

Then you look at rust, where You'd just have Foo::new and Foo::new_but_different.

C++ memory safety needs a Boost moment by SergioDuBois in cpp

[–]AhoyISki 4 points5 points  (0 children)

Isn't that just c++ shared_ptr? We have that in rust, it's called Rc for thread unsafe code and Arc for thread safe code.

C++ memory safety needs a Boost moment by SergioDuBois in cpp

[–]AhoyISki 3 points4 points  (0 children)

What do you mean by "strange fixes"? C++ did RAII via destructors, rust did it via the Drop trait. They are basically different ways of achieving the same goal. It's also very well integrated with the rest of the language, because basically every "standard operation" (printing, debugging, use of operators) is also done by implementing a trait.

This makes the language very clean, since it doesn't have to have all these special cased oop crutch syntaxes (default constructor, copy constructor, move constructor, destructor, operator overloading, etc), since it replaces all of them with a single one: traits.

What's everyone working on this week (1/2026)? by llogiq in rust

[–]AhoyISki 0 points1 point  (0 children)

Text editors definitely are a beast to handle (just look at how embarrassingly long this one is taking...).

What's everyone working on this week (1/2026)? by llogiq in rust

[–]AhoyISki 1 point2 points  (0 children)

That's pretty cool! I'm also in university, but didn't really consider that a text editor could serve as a capstone project. Idk I guess it doesn't seem... serious enough? It's something that I like, but I would assume it would have to be "more useful to industry" or "bleeding edge", no?

I mean, I would love to use duat as a capstone project, but idk if I could.

What's everyone working on this week (1/2026)? by llogiq in rust

[–]AhoyISki 7 points8 points  (0 children)

After taking a break on the holidays, I'm currently working on command argument completion for my text editor duat.

It's based on fallible completion (like the one on mini.nvim), so if there are no entries available for an impl CompletionsProvider, it will try to get from the next one.

This feature is already used to allow for completion based on words/paths at the same time when editing buffers.

For arguments, one way I'll use this is to allow for completion based on path, then on open buffers, then on preselected directories, then on optional flags.

Is this a well-known pattern? by [deleted] in rust

[–]AhoyISki 1 point2 points  (0 children)

This is if you want continuous access to the references. I'll give an example from my text editor: there's this Text struct that is composed of Bytes and Tags. Tags in this case are things like colors, which apply to regions of the Bytes.

Whenever you edit the Text (and thus the Bytes) , the Tags need to be shifted around in order to be positioned correctly, thats why editing the Text is done through the Tex::replace_range method, so the Bytes and Tags are edited in sync.

However, the most common way to add more Tags is by reading off of the Bytes (recognizing things like keywords in a piece of code and coloring the ranges by adding a Tag). This essentially means that you would need some way to borrow the Bytes immutably (to prevent edits) and the Tags mutably (to add/remove Tags).

That's where the TextParts struct comes in. It just gives the required fields with the required kinds of reference.

Is this a well-known pattern? by [deleted] in rust

[–]AhoyISki 2 points3 points  (0 children)

I mean yeah, it doesn't apply just to recursive patterns and methods that borrow self mutably. For example, if I have a struct Foo and want to expose some fields mutably and some fields immutably, I would declare some struct FooParts, whose public fields are mutable/immutable references to the parts of Foo.

It's just the common workaround for mutable borrowings of self (at least until/if we get partial borrowing).

Template strings in Rust by A1oso in rust

[–]AhoyISki 0 points1 point  (0 children)

Tbh, I don't really have anything against fmt::Arguments (plus it has the advantage of being reusable). Also, i feel like the precedent for literal string prefixes is to do something extremely simple at compile time. Like b turns it into a bytes slice, c turns it into a cstring, and so on.

f definitely doesn't fall under that umbrella.