Comment by antonvs
There are two issues here, and you're talking about a different one from the one I'm interested in. Your main issue seems to be this:
> If you convert a high level object into a low level one, and then back up as another type, then what exactly do you expect the language to do about that?
One answer to this would be "prevent it entirely". That's probably not practical for a language like Rust today, though, and I don't really care about that.
What I care about is that it's necessary to do this in the first place. The fact that doing this can be useful and necessary in a case like this suggests that it would be possible to design the types involved so that you don't need these low-level and runtime-unsafe conversions to get the job done.
> It sounds like you would prefer if UdpSocket From<OwnedFD> should run getsockname() or something to confirm it's of the expected type
No, I'm saying the types could be designed to prevent the need for doing this in the first place.
> What I care about is that it's necessary to do this in the first place.
I don't think it is. socket2::Socket has send_to() just as much as UdpSocket does.
(disclaimer: I only looked up the docs, I didn't try to modify the code to strip out needless UdpSocket)
> runtime-unsafe
That's not a thing. You always need to check for errors. seccomp could be blocking your syscalls. Hard drives break such that reads return error.
Getting an Err() from a function does not make it "unsafe", runtime or not.
> the types could be designed to prevent the need for doing this in the first place.
If your type system does not allow you to "bring your own fd (to be managed)", then it's not fit for purpose for the kind of problems Rust aims to solve.
A systems language needs to be able to receive a file descriptor from a C library, and work with it.