Hackathon; or, various compiler improvements#272
Merged
Conversation
No functionality changes
NOTE: Not fully implemented. Will not work on Rational types until we
factor out literal->plaintext into a proper trait.
This allows, e.g.
```rust
fn simple_sum(a: Cipher<Signed>, b: Cipher<Signed>) -> Cipher<Signed> {
let mut sum = fhe_var(0);
sum = sum + a;
sum = sum + b;
fhe_out(sum)
}
````
These I think are typically ignored by default when consuming proc macros but might as well be explicit
Unsure how important this is, but see here: https://docs.rs/quote/latest/quote/macro.quote_spanned.html#syntax
So that token generation happens in helper methods, and the ultimate output() func is readable
samtay
commented
Jul 5, 2023
samtay
commented
Jul 5, 2023
samtay
commented
Jul 5, 2023
samtay
commented
Jul 5, 2023
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Improvements
Disallow mut
Previously this was allowed, nothing would go wrong, but it could be misleading for the end user, as FHE programs cannot mutate their inputs.
Disallow generics
Prior, you'd get some funky error messages, with nonsensical recommendations:
Now you get the issue up front:
Fix unrelated macro error from popping up
Resolved so that the user just sees
Fix compiler error on argument attributes
This one had the same issue as the previous error message, an unrelated note about macro invocations. Also, I made it so that the compiler error message targets the attribute instead of the argument identifier:
Better invalid return error message
Before:
Now they see the more succinct:
Marginally better invalid input error message
Similarly, you used to get something like this when passing an
i64argument:Now, you get the much more succinct issue, just the two missing impls necessary for
Input:Get rid of
.into_program_node()noiseI've made a
zkp_var!macro. I think this glorious commit sums it up. BasicallyReally,
zkp_varcan work as a function. But as a macro it does support things likezkp_var![0; 10]so that's nice.Allow "initialized" ciphertext variables
As we've discussed extensively in #fhe-compiler, there's kind of been this awkward dance when folding over ciphertexts. In math/haskell speak: ciphertexts formed a
Semigroupbut not quite aMonoid; these changes give us the requiredMonoid::mempty.Now you can:
Again,
fhe_varcan work as a function but this way we supportfhe_var![0; 10].Implementation note: I've done this as unobtrusively as possible, so that the only nodes for which we lose type-level invariants are on the newly added
Indeterminatenodes. We could add theenum Stage {Literal, Cipher}to allCiphernodes, and then all the types would be shared and we wouldn't have to juggle different node types. But that requires moving all those invariants to the value level (invariants like ciphertext addition vs. plaintext addition happening on the correct nodes).Another note: you can't use a binary operation on two of these
fhe_var!outputs. You can only mix them with ciphertexts. In order to support both (sanely) we need to first add plaintext/plaintext arithmetic operations. (Insanely, you could just make the appropriate impl and just panic if both vars are still plaintexts - but this is something I'd rather the user see at Rust compile time than FHE program compile time.)Auto
.into()Due to limitations of impls on foreign traits, this is done via a custom
Coercetrait for coercing types behindFheProgramNode. Essentially, all of your return values get an automatic.coerce()call, like.into(). We support the trivial identity coercion, of course, and the coercion from indeterminate nodes created withfhe_var!toCiphernodes. Additionally we provide impls for arrays of coercible values. This means you can return arbitrarily array-nested indeterminate nodes and coercion will still work. (However, you can't mix types within an array:[ciphertext_input, sum]is still illegal, since those values are of different types.)Refactored the
fhe_programproc macroApologies for adding this to the diff. It wasn't bad to begin with, but by the time I finished adding the nested function stuff to support the auto
.coerce(), it was getting unwieldy. It's more pleasant to read now.Leftovers
IndeterminateandStageetc. altogether, andfhe_var!could just create genuine Cipher nodes. This is probably the best thing we could do, both in terms of user experience and the easiest code to maintain.