-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ghost Constraint Stabilization (#1271)
* recognize and reject extern specs which define bodies for their methods * support multiple constraints in ghost constraints * correctly support purity ghost constraints turns out the previous implementation was flawed in that it made the function pure whether or not the constraint held * require at least one bound for ghost constraints * report example structure only when it makes sense * add compiletests for ghost constraint purity * auto-format prusti-specs crate * unify handling of bodies in extern specs and check more places * add unit test for bodies in extern specs * update unit tests * parse new syntax for ghost constraints/conditional spec refinements * add failing test for extraneous comma before specs * update example in error note * remove ghost constraint feature flag you can still introduce unsound behavior with them, but they're far from the only way to do so, and absolutely necessary for prusti std * rename ghost constraints to conditional spec refinements in user-facing strings & comments * formatting * address clippy's concerns * add unit test for trait impls with generic arguments removed a check preventing use of this feature previously; this effectively formalizes it as working * improve test * desugaring fixes expressions are not implicitly in parentheses, creating very strange errors when desugaring e.g. a + b to &a + b * conditional spec refinements -> type-conditional spec refinements * rename ghost constraints to type-conditional spec refinements everywhere * update test to reflect that generics are supported not thoroughly tested, but let's not let perfect be the enemy of good enough * update test to reflect that generics are supported not thoroughly tested, but let's not let perfect be the enemy of good enough * adjust join_spans testing-specific behavior testing-specific workaround is now only present when cfg(test) is active * make typecondspec parser more robust, require comma again * update overlooked holdover of old ghost constraint term * fix typo * update compiletests to new typecondspec syntax * update preparser tests to include the new parentheses * update cargo test * update more compiletests * update more compiletests * allow merge clauses for extern trait specs implemented by simply tacking on our bound to the existing clause * allow extern_spec to take a module argument & apply to free functions the module argument is not valid on impls, since those already work with qualified type paths * update tests * allow trailing commas in where clauses on extern specs on traits * ignore lifetimes in pure function substs * ignore lifetimes in extern spec sanity check too * always use lifetimes from args instead of generics generic lifetimes are erased during trait impl resolution * clippy * update user guide with new typecondspec syntax * add regression test for trait resolution with references * update broken link * use lifetimes from substs when possible * erase lifetimes only when resolved method differs * tiny fix got lost in the refactor; i blame copilot lol * fix some test indentation * remove unnecessary derive * rename missed test folders * improve generic trait tests * update comment * drop unhelpful comment * remove outdated comment better no information than inaccurate information! * fix spans for binary ops while preserving the safety of parenthesizing incoming LHS/RHS * obsolete #[generic]/#[concrete] for traits the latter didn't work anyway, and now that we have type-cond-specs, we know we won't need it, so we can drop the annotations entirely. * update tests for trait parameter attribute removal * update preparser cfg tests * rewrite self type in newly-allowed where clauses where clauses on traits * bump cache version we were getting spurious failures for the core proof tests from old data * mangle function names for extern specs * flatten extern spec modules it's like they were never there! no more use crate::*; * update tests * only mangle free functions keep the changes to a minimum
- Loading branch information
1 parent
3b66dee
commit 87351cc
Showing
122 changed files
with
1,871 additions
and
1,395 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Type-Conditional Spec Refinement | ||
|
||
When specifying trait methods or generic functions, there is often a special case that allows for more complete specification. In these cases, you can attach a type-conditional spec refinement attribute to the function in question, spelled e.g. `#[refine_spec(where T: A + B, U: C, [requires(true), pure])]` | ||
|
||
For example, one could use this to specify a function like `core::mem::size_of` by defining a trait for types whose size we'd like to specify: | ||
|
||
```rust | ||
#[pure] | ||
#[refine_spec(where T: KnownSize, [ | ||
ensures(result == T::size()), | ||
])] | ||
fn size_of<T>() -> usize; | ||
|
||
pub trait KnownSize { | ||
#[pure] | ||
fn size() -> usize; | ||
} | ||
``` | ||
|
||
> Note that the involved functions are marked as `pure`, allowing them to be used within specifications. This is another common use case, because functions can only be `pure` if their parameters and result are `Copy`, so it is often useful to specify something like `#[refine_spec(where T: Copy, [pure])]`. | ||
There are some marker traits which simply modify the behavior of methods in their super-traits. For instance, consider the `PartialEq<T>` and `Eq` traits. In order to consider this additional behavior for verification, we can refine the contract of `PartialEq::eq` when the type is known to be marked `Eq`: | ||
|
||
```rust | ||
pub trait PartialEq<Rhs: ?Sized = Self> { | ||
#[refine_spec(where Self: Eq, [ | ||
ensures(self == self), // reflexive | ||
// we could write more specs here | ||
])] | ||
#[ensures(/* partial equivalence formulas */)] | ||
fn eq(&self, other: &Rhs) -> bool; | ||
} | ||
``` | ||
|
||
Thus, any client implementing `Eq` on a custom type can take advantage of the additional semantics of the total equivalence. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.