Replies: 35 comments 9 replies
-
No, |
Beta Was this translation helpful? Give feedback.
-
But.. yeah. I see what you mean. I don't think unsafe derives are a thing yet, really? |
Beta Was this translation helpful? Give feedback.
-
Not yet rust-lang/rfcs#3715 |
Beta Was this translation helpful? Give feedback.
-
I think this should be mentioned in the documentation for both the Maybe the derive trait can be renamed to |
Beta Was this translation helpful? Give feedback.
-
What is the plan for implementing |
Beta Was this translation helpful? Give feedback.
-
Maybe that's just the solution. It's true that building any type of the deployments facet is inherently unsafe unless you know what you're doing? I don't know. Maybe the solution here is to expose some method to verify invariants? It wouldn't solve the naming issue or the documentation issue, but we could make I quite like this idea. In fact, it could be specified as an attribute in the derived macro, something like:
Or something. It could even return an error value instead of just a bool so we have a nice user experience. |
Beta Was this translation helpful? Give feedback.
-
Example: #[derive(Deserialize)]
#[serde(try_from = MaybeFive)]
struct NotFive {
int: i32,
}
#[derive(Deserialize)]
struct MaybeFive(i32);
impl TryFrom<MaybeFive> for NotFive {
type Err = FiveErr;
fn try_from(val: MaybeFive) -> Result<Self, Self::Err> {
if val.0 != 5 {
Ok(Self { int: val.0 })
} else {
Err(FiveErr)
}
}
struct FiveErr;
impl Display for FiveErr {...} |
Beta Was this translation helpful? Give feedback.
-
Should Such as: struct MyByteVec {
// Safety invariant: `ptr` points to `len` bytes of memory
ptr: *mut u8,
len: usize,
} I think |
Beta Was this translation helpful? Give feedback.
-
Yes, but not through the derive, if that makes sense? I really don't like the UX implications of renaming the derive macro to anything other than |
Beta Was this translation helpful? Give feedback.
-
I'm starting to change my mind. |
Beta Was this translation helpful? Give feedback.
-
I'm not sure I agree with the first example being the fault of the Are there other examples of |
Beta Was this translation helpful? Give feedback.
-
That's actually a really good argument! |
Beta Was this translation helpful? Give feedback.
-
It's also the logic Though a method for enforcing invariants during deserialization would be very nice. |
Beta Was this translation helpful? Give feedback.
-
Any ideas on how to allow returning errors there without falling into "no context" or "&'static str only" or "woops we require an allocator now"? It would be nice to get the details of what invariant failed.... maybe &'static str is not that bad. |
Beta Was this translation helpful? Give feedback.
-
I don't think I personally can think of anything except |
Beta Was this translation helpful? Give feedback.
-
I think so too. The other thing was mutation once something is already fully initialized. We don't want people to be able to just drop the poke and leave the original mutably borrowed value in some invalid state. I honestly don't know how to do this. I think the The version of |
Beta Was this translation helpful? Give feedback.
-
#188 landed, and it doesn't even allow direct mutation, only building from uninitiated to fully initialized. Invariants can be checked by adding a |
Beta Was this translation helpful? Give feedback.
-
Hi @fasterthanlime, I'm curious whether unsafe derives as in rust-lang/rfcs#3715 still be useful to you, or would they change the way you approached your implementation? Or did the way you ended up solving this feel unambiguously better to you? |
Beta Was this translation helpful? Give feedback.
-
I think so? I'm not entirely sure. I'm still torn because.. deriving |
Beta Was this translation helpful? Give feedback.
-
Yeah, violating internal invariants does not itself justify |
Beta Was this translation helpful? Give feedback.
-
I think an important difference between The
Even if a type has invariants, I don't see how deriving I see three options:
I think 3 would be the best to prevent footguns. |
Beta Was this translation helpful? Give feedback.
-
I think they both could be safe: when you’re deriving I’m not sure that’s the best solution though. The problem with the full reflection design like impl TypeImplementingFacet {
pub(crate) fn pub_crate() -> impl Facet;
fn priv() -> impl Facet;
} so to access information about private fields you have to go through |
Beta Was this translation helpful? Give feedback.
-
As for 4., it cannot be done in safe code at all in facet. Right now you can do it in that you can get the offset of the field, but then to write to it, you have to resort to unsafe. So I stand by my argument that, with the new Wip interface (it wasn't the case before), deriving |
Beta Was this translation helpful? Give feedback.
-
But what if I only want to derive |
Beta Was this translation helpful? Give feedback.
-
True :) |
Beta Was this translation helpful? Give feedback.
-
@tyilo @GoldsteinE what use-cases do you see for in-place mutation besides like.. debuggers? Which are inherently unsafe? It would be interesting if facet let crates annotate "this field is fine to change by yourself, here's the validation function" or something, but it's not... I feel It's not the primary objective. And it's not relevant to the discussion of whether deriving
So that settles that as far as I'm concerned — the rest I'm interested in discussing of course (but maybe separately).
Then (You can also just declare it as scalar/opaque and then there's no way to build it through Wip either.) |
Beta Was this translation helpful? Give feedback.
-
Note: I converted this to a discussion since I don't consider it an issue to fix, but there's interesting conversation I don't want to lose track of. |
Beta Was this translation helpful? Give feedback.
-
I’m sorry, I think I was unclear here: I’m not talking about in-place mutation here specifically: reflection is inherently a semver hazard, even if in-place mutation is not supported (in fact, in-place mutation could be emulated by constructing a new value with a changed field and then overwriting the old value). When you derive That said, this is not very far from the kinds of semver promises you make when you derive |
Beta Was this translation helpful? Give feedback.
-
Sorry to but in, but does this mean that if I make a type that has some internal invariant I should not derive |
Beta Was this translation helpful? Give feedback.
-
If I was thinking of this as a language feature, where perhaps something like
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Is it supposed to be safe to implement
Facet
with#[derive(Facet)]
for a type that has internal invariants?If so, then
facet_json::from_str
needs to be unsafe:Beta Was this translation helpful? Give feedback.
All reactions