#deccer+rust=?
269 messages · Page 1 of 1 (latest)
se fuck is IntellijRustDollarCrate
Was
I have no idea what you are doing to see these arcane objects
Oh
Yeah don’t do that

deccer learning rust, 2023
May I interest you in a vulkan abstraction library for rust 
no


Why do we have
but not :novk:
Because vk is good
It's time to make a new suggestion
no
I missed reading the standard btw
https://eel.is/c++draft/over.match#class.deduct-example-2 This is so beautiful
Using Rust with gl is fiiiine (I have Stockholm Syndrome).

hmm
does clion support all that library/module nonsense too?
with the rust plugin that is
made new folder lib/lib-graphics with Cargo.toml and a lib.rs
lib.rs has a module with the same name in it graphics
but from main.rs i was expecting that i can do use graphics; and instantiate whatever is declared in graphics module
: )
and have the rustplugin add graphics to any dependency like intellij-intellisense ususally does
I don’t think it does that no
But you probably just want submodules, not entire sub crates
So src/graphics/mod.rs
That way you don’t need to manage dependencies between each module
If you do want that (I do this it does have some advantages), you may want to look into cargo workspaces instead
like this?
backyard
├── Cargo.lock
├── Cargo.toml
└── src
├── garden
│ └── vegetables.rs
├── garden.rs
└── main.rs
less intuitive were my fist thoughts
This is equivalent to replacing garden.rs with garden/mod.rs
yeah i went with your way
hmm i then assumed i can just do
use graphics;
fn main() {
let x = Thing(); // thing is in graphics module
}
or have the rust plugin resolve it for me 😉
use graphics just imports the module, you can’t write the unqualified name of the contents yet
But yes I do that too
use graphics::Thing or let x = graphics::Thing::new()
yep wanted to peek into your code : )
I just let clion import what I need lol
Usually I don’t qualify names at all
Idk if that’s good practice but it seems to hold up with what I’ve seen
hmm
thats the module
mod graphics {
struct Device {}
impl Device {
fn CreateTexture2D(texture2DDescriptor: Texture2DDescriptor) -> Texture2D {
return Texture2D {};
}
}
}
pub
ah
Its private by default
pub mod neh?
Pub everything 
kkkk
deccer let me know how annoying the Rust compiler is
the thing is usually it yells at u but also tells u how to fix it
it doesnt thats the thing
just gives totally unrelated hints
unless they are just named like shit
i removed pub mod graphics, just left all the things in there
but then it probably needs to stay
oh wait
in graphics/mod.rs you dont need to declare mod graphics
the file itself is already the module
Yeah its a reserved name, kinda like main.rs or lib.rs
rust encourages you to group types logically
hrm i cant load any github page

now it werks
weird
ah its slow again
who knows, maybe the kids who attacked gitlab recently now try github somehow
me seeing the title of this thread

i know a guy irl, who looks exactly like that man 😄
fooking github
Discord and GitHub seem to be having some issues
theyre fine for me
They're very slow for me, perhaps it's just me
that is ugly
why is self not a builtin in instance methods
the reason is you also use it to specify if the method can mutate self or not
C# did it right
i suppose its coming from the fact that declaration and definition of "classes" is separate ... struct Foo { } impl Foo { }
public void Thing(this Self stuff) {
}```
You can even rename the this parameter, how cool is that
thats almost correct c#, method must be static there, and then its an extension if it lives in a static class
struct Foo {}
impl Foo {
fn bar() {} // static
fn baz(&self) {} // const method
fn baw(&mut self) {} // non-const method
fn bax(self) {} // moves out of self
}
yeah imo a lot of things seem weird initially but do make sense in the big picture in the end
The hell does move out of self mean
that you when mama kicks you out
kind of
imagine it as calling bar(std::move(thing))
but in rust moves are destructive, so thing is no longer accessible after calling that
imagine calling static functions static 😄
I fail to see how this is useful
so i have to think more c like rather than c++ (and classes) like
let foo = Foo {};
foo.bax();
// using foo is now a compiler error
imagine a builder struct
Maybe for stuff like optional?
with build() moving out of self and returning the target object
thats a weird explanation, self is the builder itself, and build() returns the object to be build
you also are not allowed to move out of fields inside &(mut) self functions
as a practical example
again please excuse my ignorance
Hmm
I c (read: I see)
I have IncompleteCommandBuffer which allows recording commands
It has a finish(self) method
Which calls vkEndCommandBuffer and returns a new CommandBuffer that doesnt expose methods for recording but can be submitted
Why is using foo here a compiler error
this guarantees at compile time that
- you cannot record commands after vkEndCommandBuffer
- you cannot submit unfinished command buffers
because it has been moved
But that doesn't make any sense, what if I want to use the same IncompleteCommandBuffer to record the next pass frame
you mean the next frame?
you dont finish() between passes
Only when youre done recording
Yeah, frame lol
I have some internal recycling going on
But in general in my lib you just allocate a new command buffer
The lib might re-use an old one, I haven't implemented that yet but it's worth considering
Yet another L for destructive moves smh
But you can't use it anymore
It's in another castle
sure but doing so is an error anyway
if you use it before its done executing you get a sync bug
i think ill just stay on my c# island, and keep my small brain safe
if you use it after its fine but you have to reset it first
I do that yes
I decided not to expose the possibility of this mistake
wait_fence + reset
by just telling you to cope and ask for a new one 
: )
the library might do some pooling in the future, thats not a bad idea tbh
How do you pool though, the command buffer is forever stuck inside a moved-from location
but in general a frame looks a bit like
let cmd = exec.on_domain::<All>()?;
let cmd = graph.record(cmd, &bindings, &mut pool, None, &mut ())?;
let cmd = cmdfinish()?;
let mut batch = exec.start_submit_batch()?;
batch.submit_for_present(cmd, &ifc, pool)?;
Ok(batch)
fn finish(self) -> Result<CommandBuffer<D>> {
// SAFETY:
// * `self` is valid, so `device` and `self.handle` are valid.
// * `self` is valid, so this command buffer is in the recording state (see `new()`).
unsafe { self.device.end_command_buffer(self.handle)? }
Ok(CommandBuffer {
handle: self.handle,
_domain: PhantomData,
})
}
finish() passes its handle to the CommandBuffer
this handle can be pooled internally
I could store a Pooled<vk::CommandBuffer> instead and thats it
Meh
is the fact that you need to allocate a new command buffer each frame throwing you off
No, it's the destructive move that me no likey
consider this C++ code
auto foo = FooWithImportantInternalState {};
bar(std::move(foo));
// accessing foo might now be UB, depending on how its move
// constructor is implemented
From SO
Sure foo is in an unspecified state
But we all know that strong and powerful C++ developers either put foo in a default-initialized state for trivial and default constructible types or in a zero-initialized state for POD and non-default-constructible types
standard lib containers are guaranteed to be in a valid state at least
If you don't put foo in a well-defined state you deserve to SIGSEGV 
Also, if you want to re-use the foo name in Rust, you can just rebind it: ```rs
let foo = Foo {};
foo.move_me();
let foo = Foo {}; // ayy we back
Redeclaration? wut
shadowing
thats a new instance, innit?
yeh
oh god
it just hides the old one
w🇹🇫
now i get that this looks like a huge ick
BUT
in typical rust code, this is actually a good thing
for example
let foo: Option<T> = get_an_optional_value();
if let Some(foo) = foo {
// use foo
} else {
// dont use foo
}
Having to rename the initial foo to foo_opt would be quite ugly
how to get the value out of your monad
Some(body)
Once(told)
smh not using std::sync::Once
Once reads like dunce almost
std::think::Dunce
hehe
sir penguin
Yessir
How do you do this in rust:
alignas(max_align) unsigned char my_garbage_ok_dont_ask[max_size];
auto* ptr = new (my_garbage_ok_dont_ask) T();
ptr->execute_order_66();
ptr->~T();```
Well yes, I guess this is not very safe for Rust 
There might be a way to do this that’s not UB
Maybe the following:
let buffer = Box::new_uninit::<[u8]>(size);
let ptr = Box::into_raw(buffer);
let foo = ptr as *mut Foo;
*foo = Foo {};
let foo = Box::from_raw(foo);
let foo = foo.assume_init();
foo.execute_order_66();
drop(foo);
how do you make a memory allocator in rust? impossible mode: safe rust only
I typed this on mobile so i don’t know if this compiles but

That doesn't call Foo's constructor though does it?
This is subtly different from placement new in that this foo is created on the stack and then moved into the pointed to value
But that’s usually not important
Box<T> is unique_ptr<T> btw
Looking at my C++ code I don't wonder how much unsafe I should have
I wonder how much safe instead
I'd be quicker to just do unsafe {} the whole program 
There’s a neat tool that prints all unsafe lines in a c++ program
Pog
Its called cat
(Joke stolen from jaker)
I thought it was some sort of potential ubsan

Would be cool ngl
Mfw a simple + is potentially undefined due to integer promotion

You just need to embrace UB instead of reject it
(which I stole from somewhere else)
Jake stolen from Joker
crate::hint::black_box(()); 😄
deccer going beast mode?
rust is hardly a beast
👀
: )
Rust isn't a difficult language.
