You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In specifying the standard library (#1249), I wanted to mark e.g. PartialEq::eq as pure by default (perhaps with an auto trait so people can opt out of that). However, I had to drop this spec due to unfortunate interaction with derive(PartialEq), a very common way for people to implement this for their types. Here is a snippet producing the error in combination with the specs in #1249:
Unlike pre- and postconditions, purity is not applied to/inherited by trait implementations by default, requiring users to annotate them manually. This same issue arises for other commonly-derived traits, including PartialOrd and Default (though for the latter I decided to include the spec anyway, as it's significantly less common.) A workaround is to provide an extern spec for this:
It is not reasonable to expect users to annotate all their derived implementations like this, especially for more complex ones like PartialOrd.
We lose the usual transparency feature of purity, where Prusti understands the contents of the function, so Special::default().x == 0 cannot be verified like this.
There are a few possible solutions:
Accept that users have to write this boilerplate. This is obviously problematic because derive implementations exist to avoid this kind of boilerplate.
Switch from an opt-out mechanism (auto trait) to an opt-in mechanism (non-auto trait) for this spec. This is undesirable because the point of making it opt-out is that it can reasonably be expected of most implementations.
Add a derive macro for each such trait that users simply have to add to the list, e.g. #[derive(Default, PureDefault)]. This could be a no-op when the prusti feature is not active.
Make methods inherit not just pre-/postconditions but also purity from the trait member they implement. I'm not sure about the soundness implications of this, but it feels like a simple, consistent solution.
The above, but hardcoded or otherwise made to apply only to certain traits. This could also be an "argument" to pure, e.g. pure(inherited = true), or perhaps inherited_pure, probably better than hardcoding.
Personally, I think 4. or 5. would make the most sense, and I would even slightly favor 4., though as said it's possible there's a major flaw with it in general.
The text was updated successfully, but these errors were encountered:
In specifying the standard library (#1249), I wanted to mark e.g.
PartialEq::eq
aspure
by default (perhaps with an auto trait so people can opt out of that). However, I had to drop this spec due to unfortunate interaction withderive(PartialEq)
, a very common way for people to implement this for their types. Here is a snippet producing the error in combination with the specs in #1249:Unlike pre- and postconditions, purity is not applied to/inherited by trait implementations by default, requiring users to annotate them manually. This same issue arises for other commonly-derived traits, including
PartialOrd
andDefault
(though for the latter I decided to include the spec anyway, as it's significantly less common.) A workaround is to provide an extern spec for this:This has two main caveats:
PartialOrd
.Special::default().x == 0
cannot be verified like this.There are a few possible solutions:
derive
implementations exist to avoid this kind of boilerplate.#[derive(Default, PureDefault)]
. This could be a no-op when theprusti
feature is not active.pure
, e.g.pure(inherited = true)
, or perhapsinherited_pure
, probably better than hardcoding.Personally, I think 4. or 5. would make the most sense, and I would even slightly favor 4., though as said it's possible there's a major flaw with it in general.
The text was updated successfully, but these errors were encountered: