Guild icon
DDraceNetwork
Development / developer
Development discussion. Logged to https://ddnet.tw/irclogs/ Connected with DDNet's IRC channel, Matrix room and GitHub repositories β€” IRC: #ddnet on Quakenet | Matrix: #ddnet-developer:matrix.org GitHub: https://github.com/ddnet
Between 2021-07-16 00:00:00Z and 2021-07-17 00:00:00Z
Avatar
code sample pls
00:00
@GutZuFusss how is it going?
00:01
For this to be correct I need let bindings for the temporaries I create, which looks unpretty
00:02
I even have a proposal for this new revolutionary language features name LetLive. Creates a temporary that will live through the entirety of it's parent block
00:02
s/features/feature/
Avatar
where is that a problem there?
00:03
can you post the error? my brain rust compiler accepts your code
Avatar
s.com_id.to_string() is a temporary, query! wants a &str
00:04
here is the error
00:04
Actually I think it takes a &String not &str but same issue either way
Avatar
ah
00:05
I don't know the exact rules around that. you might be able to cheat using a match statement πŸ˜„
00:06
I guess that would be similar to a let binding
Avatar
C++ doesn't have compound literals either, it's so annoying 😦
Avatar
hah
00:07
my base64 encoding code only had two bugs caught by the tests
Avatar
huh, none of the libraries we have has one?
00:07
I thought curl would include one
Avatar
didn't check
00:07
curl is extremely conservative with exposing features
00:07
it didn't even have an URL parser until recently
00:08
no, its base64 parser is private as well
00:08
time to write a decoder πŸ˜›
Avatar
I shall draft a RFC for my C Compliance Changes (CCC), introducing compound literals and (post/pre)crement operators
Avatar
does "compound literal" specify the lifetime?
00:09
I thought it only meant that you can have struct literals. you can have that in rust
Avatar
C18: 6.5.2.5p5: The value of the compound literal is that of an unnamed object initialized by the initializer list. If the compound literal occurs outside the body of a function, the object has static storage duration; otherwise, it has automatic storage duration associated with the enclosing block.
Avatar
the dictionary doesn't tell me that compound means something like "lives long"
Avatar
So my 3rd error would be fixed by (i32){ s.state as i32}
Avatar
Avatar
heinrich5991
the dictionary doesn't tell me that compound means something like "lives long"
Compound long-living literals just doesn't sound as catchy πŸ˜›
00:12
I bet the compiler could even do some magic to figure out how long they are actually needed with all the lifetime information rust has associated with it's functions
00:14
I have a more rusty syntax for it too LetLive! { s.state as i32 } ooor (let s.state as i32)
Avatar
yay, the decoder also only had two bugs
Avatar
o(-`Π΄´- q)
Avatar
d9a094d M Dead Darkness, M Im No Superman 2 - ddnet-maps
Avatar
justatest python-like java programming justatest
Avatar
@Learath2 I found an argument against base64-encoding the bytes: other teeworlds mods don't have a base64 function at their disposal, making the protocol harder to implement for them
10:29
perhaps I should just go for 0-terminated string
Avatar
Can be used by testers in testing channels using the command edit. The arguments are directly passed to the program. The message in which the command is executed must either have a map attached or be a reply to a message where a map is attached. This can be used for example to extend all layers in any direction (up and left are not supported by the editor) and remove unused envelopes. The command finalize simply executes edit with the arguments --remove-everything-unused and `--shri...
Avatar
Uff, I'm just about to replace the map testing bot :/
14:52
It's kinda broken
Avatar
oh no 😦
14:55
I told Patiga that this is the map testing bot and it'd be best to work on that if he wants to add something
14:55
d4d987c Add bare-bones setup steps in README - Patiga
Avatar
@Learath2 where's the new bot? I think I might owe Patiga porting his PR to the new one
Avatar
It'll be at Learath2/ddnet-discordbot but I didn't push the map testing part yet, but I don't intend it to be permanent either
15:01
I'll personally port it for him, if we never end up fixing @DDNet
Avatar
can you explain the bot situation? there's the currently broken python DDNet. you wrote a replacement bot in rust, but it's only temporary? what happens after that temporary state? we go back to the python DDNet? you write some nodejs DDNet bot?
πŸ€– 1
Avatar
I'll do one in rust that's not this much of a mess when life calms down a little bit
Avatar
I see. so the plan is that the python bot is on its way out
Avatar
That's my intention yes
15:08
why is it not a thing for people to document the lifetimes in their code?
Avatar
link?
Avatar
A type that contains or can provide a database connection to use for executing queries against the database.
Avatar
pub trait Executor<'c>: Send + Debug { type Database: Database; fn fetch_many<'e, 'q, E>(
15:09
uh oh
Avatar
I think 'c denotes the lifetime of the Connection but I honestly don't know from a glance
15:10
impl<'c> Executor<'c> for &'c mut PoolConnection<Sqlite> this is what I based my guess on but who knows πŸ˜„
15:15
Yeah okay, my final verdict on sqlx is that it's just annoying. So hard to wrap queries in functions when they return adhoc structs
Avatar
hi all, is there a way to set a net_tcp_recv delay, in a sense that when i have an endless loop i dont have to use thread_sleep in order to not have 100% cpu usage?
Avatar
What do you want that to do? Usually you'd not have an endless loop to begin with but instead block on select
Avatar
i want to keep a tcp connection going and recv packets from it from time to time
Avatar
Avatar
Learath2
What do you want that to do? Usually you'd not have an endless loop to begin with but instead block on select
can you name an example? i dont really know what u mean, sorry
Avatar
e.g. net_socket_read_wait when you call this function it will wait for packets on the socket for time, during this time it will yield to the kernel so you won't be using the cpu at all
Avatar
ahhh, i see! yes, this seems like what i have been looking for. thank you!
Avatar
If you don't have any realtime obligations (like the server having to keep the physics running) you can just pass time = 0 this will block on select until there are some packets there
heartw 1
16:42
time = -1 sorry 0 returns immediately if there are no packetx
Avatar
@Learath2 The code I wrote was just executing binaries and retrieving their stdout/files they created, so I don't think its hard to port it (it wouldn't bother me too much to do it again). I spend most of the time trying to setup the bot and understanding how it works ^^
Avatar
@GutZuFusss if you want to just wait for anything to arrive, you can set the socket to blocking mode (the default, actually) and call recv on it
Avatar
@heinrich5991 here?
Avatar
hai
Avatar
Q: https://paste.pr0.tips/1U Err: https://paste.pr0.tips/k1 Do you happen to know why reply2 won't compile? Feels like the compiler has enough information to not need the type annotation
17:53
reply1 suggests it does indeed know enough to coerce the type of the box
Avatar
ah
17:57
the problem seems to be that it infers the type of the closure first, for whatever reason
17:57
and gets to Box<YourSpecificErrorType>
17:58
and Result<Message, Box<YourSpecificErrorType>> cannot be coerced to Result<Message, Box<dyn Error>>, I think
17:58
let me try
18:00
that seems to be correct
18:01
use std::fmt; fn main() { let x: Result<(), Box<()>> = Ok(()); let y: Result<(), Box<dyn fmt::Debug>> = x; }
18:01
gives me
18:01
error[E0308]: mismatched types --> a.rs:4:46 | 4 | let y: Result<(), Box<dyn fmt::Debug>> = x; | ------------------------------- ^ expected trait object `dyn Debug`, found `()` | | | expected due to this | = note: expected enum `Result<_, Box<dyn Debug>>` found enum `Result<_, Box<()>>` error: aborting due to previous error For more information about this error, try `rustc --explain E0308`.
Avatar
Hm, does () even implement Debug?
Avatar
yes
18:33
println!("{:?}", ());
18:34
idk why i dont like errors with dyn boxes
18:34
i strongly prefer enums with from impls
18:35
and its rly ez with thiserror lib
Avatar
Hm, this is a shortcoming of the compiler, no? There is indeed enough information here to do coercion properly
Avatar
if ur error implements std::error::Error you can do .map_err(|e| e.into()) and it gets boxed
Avatar
@Ryozuki I also prefer concrete error types but in this specific case this is irrecoverable anyway
Avatar
if ur error implements std::error::Error you can do .map_err(|e| e.into()) and it gets boxed
18:37
discord told me smth weird about a emote
18:37
The stdlib helps in boxing our errors by having Box implement conversion from any type that implements the Error trait into the trait object Box<Error>, via From.
Avatar
Avatar
Learath2
@Ryozuki I also prefer concrete error types but in this specific case this is irrecoverable anyway
then why not panic kek
Avatar
It's not that irrecoverable πŸ˜„
Avatar
or use anyhow?
18:38
github crates-io docs-rs
Avatar
Avatar
Ryozuki
or use anyhow?
This just needs to be done now, I can't afford to take anymore detours refactoring code to use anyhow and thiserror
Avatar
refactoring for anyhow should be super ez
18:39
change Result<Message, Box<dyn StdError>> to Result<Message> where result is anyhow::Result
Avatar
The final thing will probably use thiserror but I'm not coding that until later, maybe end of august
18:40
ye thiserror is the way i like most
18:40
but its specially useful for libraries
18:40
for clients anyhow does it
18:40
binaries*
Avatar
Avatar
Ryozuki
if ur error implements std::error::Error you can do .map_err(|e| e.into()) and it gets boxed
This was a smart idea but it's not good enough here, the compiler can't infer the type inside the first map_err
Avatar
@Learath2 the problem is that hte compiler infers the wrong type, not that coercion doesn't happen, I think
Avatar
I have another interesting type issue
18:49
expected trait std::error::Error, found trait std::error::Error + Sync + std::marker::Send
This one idk how to fix
Avatar
maybe add + Sync + std::marker::Send
18:49
brb eat
Avatar
Can't it's the trait function source()
18:50
Well I do know how to fix it but it's quite ugly πŸ˜„
18:51
self.1.as_ref().map(|e| -> &(dyn StdError + 'static) { &**e })
18:51
Why doesn't the compiler know here that it can drop the two extra traits itself?
18:52
idk, I sort of miss my concrete rules in C/C++ I honestly don't know whether something will compile or not until I hit compile in rust, and if it doesn't compile I usually don't get why not
Avatar
Avatar
Learath2
self.1.as_ref().map(|e| -> &(dyn StdError + 'static) { &**e })
Also this entire thing is a bit of a fail on rusts part imo, &**e is so ugly πŸ˜›
18:55
Actually I wonder as_deref would work
Avatar
Avatar
Learath2
idk, I sort of miss my concrete rules in C/C++ I honestly don't know whether something will compile or not until I hit compile in rust, and if it doesn't compile I usually don't get why not
do u actually compile it?
19:00
cargo b?
19:00
u justh ave to check it
19:00
cargo c
19:00
its faster
19:00
also with rust-analyzer it will tell you
Avatar
No, rust-analyzer tells me, which is indeed faster
19:01
but it's still sometimes baffling how hard it is to reason about extremely simple looking code in rust
Avatar
can u try self.source.asref().map(|err| err.as_ref() as )
19:02
self.1.as_ref().map(|err| err.as_ref() as _) (edited)
19:02
stupid discord
Avatar
I did self.1.as_deref().map(|e| -> &(dyn StdError + 'static) { e }) at the end and that works
19:02
I can try yours too if you are interested
Avatar
try it
Avatar
Ah perfect, type inference does work with the explicit as _
19:03
_ is like magic
19:03
xd
Avatar
"is like magic" is not very good in a programming language πŸ˜„
19:03
well i would look into it
19:03
but im 2 lazy rn
Avatar
oh, this is another problem I have with rust, no spec
19:04
When I want to lookup something very low level like this in C or C++ I just open the standard
19:04
look here
19:04
its in the works tho
19:04
but has lot of stuff already
Avatar
I checked around this to find the type inference rules to figure out why my first question wouldn't work
19:05
couldn't find anything though
19:05
this is the _
19:05
for types
19:05
The inferred type asks the compiler to infer the type if possible based on the surrounding information available. It cannot be used in item signatures. It is often used in generic arguments:
19:06
i guess its the following: since rust doesnt do implicit casts (that i know of) it will error because the type difers
19:06
but as _
19:06
is a explicit cast
19:06
so it will allow it
19:06
thats my nobo reasoning
Avatar
sounds reasonable
19:08
they should maybe relax type matching for dyn
19:08
dyn Error + Send + Sync definitely satisfies dyn Error
Avatar
rust strongly prefers monomorphization over dynamic dispatch
19:09
thats why i never use dyn errors
Avatar
hm, but why? leads to code bloat
Avatar
i use my enum
Avatar
Avatar
heinrich5991
hm, but why? leads to code bloat
you don't like generics?
Avatar
btw i think dyn dispatch in rust is more efficient, c++ uses 1 pointer to a structure that has the vtable and the data, rust has 2 pointers, one to the data and one to the vtable
19:12
so its less indirection
19:12
i read it somewhere
Avatar
Οƒβ„“Γ­β™‘ 2021-07-16 19:12:21Z
xd? one person created a bunch of tee (edited)
Avatar
@Οƒβ„“íβ™‘ pls report this elsewhere
Avatar
I think it leads to code bloat if you duplicate e.g. the sort function for essentially every call site
Avatar
Hm, I don't really know what kind of optimizations are available to the compilers in case of generics, but I'd think they can share some code between the implementations
Avatar
u can profile
19:14
the code
19:14
Twiggy🌱 is a code size profiler. Contribute to rustwasm/twiggy development by creating an account on GitHub.
Avatar
no, afaik not @Learath2
Avatar
that "same function optimization" essentially never works AFAIK
Avatar
Hm, well we can take a look at c++ I guess
Avatar
i wonder how much bloat is acceptable, maybe if u are doing embedded u want everything with dynamic, but i dont think its that much elsewhere?
Avatar
@Learath2 c++ has the same problem, I think
Avatar
it does
Avatar
Yeah, that's why I'm checking C++ πŸ˜„
19:16
if clang and gcc can't do it rustc probably can't either being my reasoning
Avatar
@Ryozuki every where code size matters
Avatar
but then why rust uses static dispatch everywhere?
Avatar
everywhere where*
19:17
because it's fastβ„’
19:17
the slowness/code size doesn't show up in microbenchmarks
19:17
I mean it's why C++ can be faster than C
19:18
in microbenchmarks
Avatar
(dynamic dispatch is actually quite fast in the cases where the compiler can reason about the type allowing devirtualization)
Avatar
which I wouldn't rely on
19:19
since it's halting problem hard, in general
Avatar
I would, problems don't need to be solved for every instance to be practically useful
19:20
I rely on the compiler optimizing my code to an acceptable degree, even though that problem is halting problem hard too
Avatar
hmm. but I can reason about local code optimizations
19:21
isn't the devirtualization a rather global optimization?
19:21
if you get it from a struct field, the compiler has to ensure that nowhere else is this field assigned
Avatar
No, the compiler needs to locally know the dynamic type of the instance
Avatar
okay, so you can assume it works for things you just instantiated
Avatar
Or it needs to know that there are no overrides, so I guess it is a tad global
19:24
Anyway, indeed std::sort<int> and std::sort<float> can't be optimized together
19:25
So I guess it's fair to say generics will always imact binary size
19:25
impact*
19:29
We should benchmark this stuff on something like a c64
19:30
Modern computers are just way too fast, way too spacious to even observe these things πŸ˜„
Avatar
it is possible to teleport player from one tile to another tile simply without using the current tile because I don't want the "number" system πŸ˜„
19:53
something like if (m_TileIndex == TILE_TELEIN_1) { m_Core.m_Pos = TILE_TELEOUT_1; }
Avatar
actually no
Avatar
@Deleted User ye, you can do something like that. but m_Core.m_Pos needs to be set to a position, not a tile index
Avatar
You might also need to update the position of the entity aswell, not just the core, no?
Avatar
@Learath2 don't think there's a separate position(?)
Avatar
I've finally hit an error I can't even read πŸ˜„ https://paste.pr0.tips/GO
Avatar
can u show more code?
Avatar
Avatar
heinrich5991
@Learath2 don't think there's a separate position(?)
um, CEntity has an m_Pos and CCharacter : CEntity so it has an m_Pos absolutely no idea if we use it though, don't really remember
Avatar
hm ok
Avatar
@Learath2 iirc async functions need 'static lifetimes
20:53
idk
Avatar
pub async fn sql_start_transaction<'a, T: Acquire<'a>>(c: T) -> Result<Transaction<'a, T::Database>, sqlx::Error> { c.acquire().await?.begin().await }
Avatar
pub async fn sql_start_transaction<T: Acquire<'static>>(c: T) -> Result<Transaction<'static, T::Database>, sqlx::Error> { c.acquire().await?.begin().await }
20:54
does this work?
20:54
xd
20:54
ok idk
Avatar
I can try in a couple minutes, but not sure if that makes sense, the lifetime parameter within acquire seems to be the lifetime of the connection
Avatar
ok i think i can ty it locally
Avatar
i think its cuz .await requires a static lifetime
Avatar
on what though?
21:33
The future itself? It's output?
Avatar
idk dont mind me xd
Avatar
Avatar
Deleted User
should be same as the body
was correct btw, thanks ^^ do you also happen to know the size of the hook pieces? I'm once again looking at the render code in game/client/components/players.cpp but fail to see the size
Avatar
Have you tried same as the body? πŸ˜„
Exported 240 message(s)