-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
get_impl_paths/recursion-checking does not handle Sync/Send inference #1335
Comments
this might be okay appealing to the coinductiveness of Send/Sync? I'm not sure. |
Not all cycles are unsound. For example, cycles through |
I'll try to write out a more rigorous analysis. This follows the OOPSLA paper and the comments in Note that we only have to translate the ghost code, not the exec code, since the exec code doesn't need to terminate. To extend this argument with traits, we encode traits using datatypes. Furthermore, if T has no exec values, there is no need for Nevertheless, just to spell out the argument carefully, and because I think non-termination for exec trait members is interesting, I'll write out the example above using an
This doesn't mean that we can ignore Send and Sync entirely in a proof of Verus's soundness (or Rust's soundness). If, for example, we wanted to prove that an Rc value was never accessed from two different threads, we'd need to make sure that the typing rules prohibited passing an Rc value from one thread to another. For this, we need to be able to mark types as sendable/syncable in the type system. I don't think it's likely that this would influence the CIC encoding used for termination, though. In particular, I don't think it's likely we would be passing around dictionaries to represent Send/Sync bounds in the CIC encoding, given that Send/Sync don't have any members that would make the dictionaries non-empty. Making this argument rigorous is hard without choosing a particular set of concurrency operations, since we could always contrive to invent some operations for which a single proof block would fail to terminate if there were a Send/Sync-based cycle in the trait graph. But I'll sketch out some simple extensions to the OOPSLA formalization to show why I think Send/Sync would not matter to the CIC encoding in most natural operations. The OOPSLA formalization contains a points-to type Now suppose we want to add Send/Sync to this formalization. Perhaps each address It's probably worth checking this for fancier, higher-order heap encodings as well, but my expectation is for the purpose of checking that single proof blocks terminate in one atomic step, Send and Sync can be omitted from the CIC encoding that is used to check this termination. I've been assuming in this discussion that we want to allow nontermination of exec code. In other discussions, we've talked about also checking exec code for termination, ranging from lightweight decreases checking for while loops (already supported) and of recursive functions, to heavyweight checking that guarantees no infinite executions or even guarantees non-blocking execution for primitive blocking operations. For heavyweight guaranteed exec termination of concurrent code, there are many concurrency operations we would have to consider more carefully, and it might be that Send/Sync matters again for this. Even if this is the case, though, I think we could coordinate the cycle checking policy for Send/Sync with the cycle checking policy for exec values in traits: if nonterminating exec code is allowed, then cycles are allowed through exec values in traits and are also allowed through the Send/Sync traits. |
Consider this variation of the recently added test
test_recursion_through_sync_impl_is_checked
from 4ab656f:The cycle has the dependency
Xinner<T, S>: Sync
-->X<T, S>: Sync
which is not covered byget_impl_paths
The text was updated successfully, but these errors were encountered: