-
Notifications
You must be signed in to change notification settings - Fork 348
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
FR: Procedural macro to derive ContentHash for structs and enums #3054
Comments
emesterhazy
added a commit
that referenced
this issue
Feb 15, 2024
This is a pure refactor with no behavior changes. #3054
emesterhazy
added a commit
that referenced
this issue
Feb 15, 2024
This is a pure refactor with no behavior changes. #3054
emesterhazy
added a commit
that referenced
this issue
Feb 16, 2024
This is a no-op in terms of function, but provides a nicer way to derive the ContentHash trait for structs using the `#[derive(ContentHash)]` syntax used for other traits such as `Debug`. This commit only adds the macro. A subsequent commit will replace uses of `content_hash!{}` with `#[derive(ContentHash)]`. The new macro generates nice error messages, just like the old macro, although they are slightly different. Before: ``` error[E0277]: the trait bound `NotImplemented: content_hash::ContentHash` is not satisfied --> lib/src/content_hash.rs:242:30 | 242 | struct Broken{t: NotImplemented} | ^^^^^^^^^^^^^^ the trait `content_hash::ContentHash` is not implemented for `NotImplemented` | = help: the following other types implement trait `content_hash::ContentHash`: bool i32 i64 u8 std::collections::HashMap<K, V> BTreeMap<K, V> std::collections::HashSet<K> content_hash::tests::test_struct_sanity::Foo and 38 others ``` After: ``` error[E0277]: the trait bound `NotImplemented: content_hash::ContentHash` is not satisfied --> lib/src/content_hash.rs:247:13 | 247 | t: NotImplemented, | ^ the trait `content_hash::ContentHash` is not implemented for `NotImplemented` | = help: the following other types implement trait `content_hash::ContentHash`: bool i32 i64 u8 std::collections::HashMap<K, V> BTreeMap<K, V> std::collections::HashSet<K> content_hash::tests::test_struct_sanity::Foo and 38 others For more information about this error, try `rustc --explain E0277`. error: could not compile `jj-lib` (lib test) due to 2 previous errors ``` This commit does two things to make proc macros re-exported by jj_lib useable by deps: 1. jj_lib needs to be able refer to itself as `jj_lib` which it does by adding an `extern crate self as jj_lib` declaration. 2. jj_lib::content_hash needs to re-export the `digest::Update` type so that users of jj_lib can use the `#[derive(ContentHash)]` proc macro without directly depending on the digest crate. This is done by re-exporting it as `DigestUpdate`. #3054
emesterhazy
added a commit
that referenced
this issue
Feb 16, 2024
emesterhazy
added a commit
that referenced
this issue
Feb 16, 2024
Here's an example of what the derived output looks like for an enum: ```rust pub enum TreeValue { File { id: FileId, executable: bool }, Symlink(SymlinkId), Tree(TreeId), GitSubmodule(CommitId), Conflict(ConflictId), } #[automatically_derived] impl ::jj_lib::content_hash::ContentHash for TreeValue { fn hash(&self, state: &mut impl digest::Update) { match self { Self::File { id, executable } => { state.update(&0u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(id, state); ::jj_lib::content_hash::ContentHash::hash(executable, state); } Self::Symlink(field_0) => { state.update(&1u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(field_0, state); } Self::Tree(field_0) => { state.update(&2u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(field_0, state); } Self::GitSubmodule(field_0) => { state.update(&3u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(field_0, state); } Self::Conflict(field_0) => { state.update(&4u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(field_0, state); } } } } ``` #3054
emesterhazy
added a commit
that referenced
this issue
Feb 16, 2024
This is a pure refactor with no behavior changes. #3054
emesterhazy
added a commit
that referenced
this issue
Feb 16, 2024
This is a pure refactor with no behavior changes. #3054
emesterhazy
added a commit
that referenced
this issue
Feb 16, 2024
This is a pure refactor with no behavior changes. #3054
emesterhazy
added a commit
that referenced
this issue
Feb 16, 2024
This is a pure refactor with no behavior changes. #3054
emesterhazy
added a commit
that referenced
this issue
Feb 17, 2024
This is a pure refactor with no behavior changes. #3054
emesterhazy
added a commit
that referenced
this issue
Feb 20, 2024
This is a no-op in terms of function, but provides a nicer way to derive the ContentHash trait for structs using the `#[derive(ContentHash)]` syntax used for other traits such as `Debug`. This commit only adds the macro. A subsequent commit will replace uses of `content_hash!{}` with `#[derive(ContentHash)]`. The new macro generates nice error messages, just like the old macro: ``` error[E0277]: the trait bound `NotImplemented: content_hash::ContentHash` is not satisfied --> lib/src/content_hash.rs:265:16 | 265 | z: NotImplemented, | ^^^^^^^^^^^^^^ the trait `content_hash::ContentHash` is not implemented for `NotImplemented` | = help: the following other types implement trait `content_hash::ContentHash`: bool i32 i64 u8 u32 u64 std::collections::HashMap<K, V> BTreeMap<K, V> and 38 others ``` This commit does two things to make proc macros re-exported by jj_lib useable by deps: 1. jj_lib needs to be able refer to itself as `jj_lib` which it does by adding an `extern crate self as jj_lib` declaration. 2. jj_lib::content_hash needs to re-export the `digest::Update` type so that users of jj_lib can use the `#[derive(ContentHash)]` proc macro without directly depending on the digest crate. This is done by re-exporting it as `DigestUpdate`. #3054
emesterhazy
added a commit
that referenced
this issue
Feb 20, 2024
This is a pure refactor with no behavior changes. #3054
emesterhazy
added a commit
that referenced
this issue
Feb 20, 2024
This is a no-op in terms of function, but provides a nicer way to derive the ContentHash trait for structs using the `#[derive(ContentHash)]` syntax used for other traits such as `Debug`. This commit only adds the macro. A subsequent commit will replace uses of `content_hash!{}` with `#[derive(ContentHash)]`. The new macro generates nice error messages, just like the old macro: ``` error[E0277]: the trait bound `NotImplemented: content_hash::ContentHash` is not satisfied --> lib/src/content_hash.rs:265:16 | 265 | z: NotImplemented, | ^^^^^^^^^^^^^^ the trait `content_hash::ContentHash` is not implemented for `NotImplemented` | = help: the following other types implement trait `content_hash::ContentHash`: bool i32 i64 u8 u32 u64 std::collections::HashMap<K, V> BTreeMap<K, V> and 38 others ``` This commit does two things to make proc macros re-exported by jj_lib useable by deps: 1. jj_lib needs to be able refer to itself as `jj_lib` which it does by adding an `extern crate self as jj_lib` declaration. 2. jj_lib::content_hash needs to re-export the `digest::Update` type so that users of jj_lib can use the `#[derive(ContentHash)]` proc macro without directly depending on the digest crate. This is done by re-exporting it as `DigestUpdate`. #3054
emesterhazy
added a commit
that referenced
this issue
Feb 20, 2024
emesterhazy
added a commit
that referenced
this issue
Feb 20, 2024
emesterhazy
added a commit
that referenced
this issue
Feb 20, 2024
Here's an example of what the derived output looks like for an enum: ```rust pub enum TreeValue { File { id: FileId, executable: bool }, Symlink(SymlinkId), Tree(TreeId), GitSubmodule(CommitId), Conflict(ConflictId), } #[automatically_derived] impl ::jj_lib::content_hash::ContentHash for TreeValue { fn hash(&self, state: &mut impl digest::Update) { match self { Self::File { id, executable } => { state.update(&0u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(id, state); ::jj_lib::content_hash::ContentHash::hash(executable, state); } Self::Symlink(field_0) => { state.update(&1u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(field_0, state); } Self::Tree(field_0) => { state.update(&2u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(field_0, state); } Self::GitSubmodule(field_0) => { state.update(&3u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(field_0, state); } Self::Conflict(field_0) => { state.update(&4u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(field_0, state); } } } } ``` #3054
emesterhazy
added a commit
that referenced
this issue
Feb 20, 2024
Here's an example of what the derived output looks like for an enum: ```rust pub enum TreeValue { File { id: FileId, executable: bool }, Symlink(SymlinkId), Tree(TreeId), GitSubmodule(CommitId), Conflict(ConflictId), } #[automatically_derived] impl ::jj_lib::content_hash::ContentHash for TreeValue { fn hash(&self, state: &mut impl digest::Update) { match self { Self::File { id, executable } => { state.update(&0u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(id, state); ::jj_lib::content_hash::ContentHash::hash(executable, state); } Self::Symlink(field_0) => { state.update(&1u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(field_0, state); } Self::Tree(field_0) => { state.update(&2u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(field_0, state); } Self::GitSubmodule(field_0) => { state.update(&3u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(field_0, state); } Self::Conflict(field_0) => { state.update(&4u32.to_le_bytes()); ::jj_lib::content_hash::ContentHash::hash(field_0, state); } } } } ``` #3054
emesterhazy
added a commit
that referenced
this issue
Feb 20, 2024
This is a pure refactor with no behavior changes. #3054
emesterhazy
added a commit
that referenced
this issue
Feb 20, 2024
This is a pure refactor with no behavior changes. #3054
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've already implemented this feature, I'm just creating a bug to collect all of the commits in one place.
Related issues:
PRs, in order:
The text was updated successfully, but these errors were encountered: