-
Notifications
You must be signed in to change notification settings - Fork 1
Various extensions #23
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
base: main
Are you sure you want to change the base?
Changes from all commits
794b95b
d4d3ea0
182f322
d351961
94cc4f8
245d9ce
3a448b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,7 +19,7 @@ trait Into<T> { | |
|
|
||
| /// See [`std::convert::From`] | ||
| #[hax_lib::attributes] | ||
| trait From<T> { | ||
| pub trait From<T> { | ||
| /// See [`std::convert::From::from`] | ||
| #[hax_lib::requires(true)] | ||
| fn from(x: T) -> Self; | ||
|
|
@@ -55,7 +55,12 @@ use crate::array::TryFromSliceError; | |
| impl<T: Copy, const N: usize> TryFrom<&[T]> for [T; N] { | ||
| type Error = TryFromSliceError; | ||
| fn try_from(x: &[T]) -> Result<[T; N], TryFromSliceError> { | ||
| if x.len() == N { | ||
| // Use the primitive length directly rather than `x.len()`: the latter | ||
| // extracts to a reference to `slice::Slice::len`, which (under | ||
| // `-core-models-lib`) Aeneas emits as an external-looking name with no | ||
| // dependency edge, producing a forward reference here (this `convert` | ||
| // module is extracted before `slice`). | ||
| if rust_primitives::slice::slice_length(x) == N { | ||
| Result::Ok(rust_primitives::slice::array_from_fn(|i| { | ||
| *rust_primitives::slice::slice_index(x, i) | ||
| })) | ||
|
|
@@ -80,14 +85,18 @@ impl<T> From<T> for T { | |
|
|
||
| /// See [`std::convert::AsRef`] | ||
| #[hax_lib::attributes] | ||
| trait AsRef<T> { | ||
| pub trait AsRef<T: ?Sized> { | ||
| /// See [`std::convert::AsRef::as_ref`] | ||
| #[hax_lib::requires(true)] | ||
| fn as_ref(self) -> T; | ||
| fn as_ref(&self) -> &T; | ||
| } | ||
|
|
||
| impl<T> AsRef<T> for T { | ||
| fn as_ref(self) -> T { | ||
| /// `impl AsRef<[T]> for [T]`. std exposes many concrete `AsRef` impls; the model | ||
| /// used a single `impl<T> AsRef<T> for T` blanket, but that can't cover the | ||
| /// unsized `[T]` (and Aeneas references the per-type impl name anyway), so we | ||
| /// provide the concrete slice impl. | ||
| impl<T> AsRef<[T]> for [T] { | ||
| fn as_ref(&self) -> &[T] { | ||
| self | ||
| } | ||
| } | ||
|
|
@@ -250,8 +259,9 @@ mod tests { | |
| } | ||
|
|
||
| #[test] | ||
| fn test_as_ref_identity(x in any::<u8>()) { | ||
| prop_assert_eq!(super::AsRef::as_ref(x.inject()), x); | ||
| fn test_as_ref_slice_identity(v in prop::collection::vec(any::<u8>(), 0..=8)) { | ||
| let s: &[u8] = &v[..]; | ||
| prop_assert_eq!(super::AsRef::as_ref(s), s); | ||
| } | ||
|
Comment on lines
261
to
265
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wasn't a test for Should we call |
||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,49 @@ | ||
| /// See [`std::hash::Hasher`] | ||
| pub trait Hasher {} | ||
| pub trait Hasher { | ||
| /// See [`std::hash::Hasher::finish`] | ||
| fn finish(&self) -> u64; | ||
| /// See [`std::hash::Hasher::write`] | ||
| fn write(&mut self, bytes: &[u8]); | ||
| } | ||
|
|
||
| /// See [`std::hash::Hash`] | ||
| #[hax_lib::attributes] | ||
| pub trait Hash { | ||
| /// See [`std::hash::Hash::hash`] | ||
| /// See [`std::hash::Hash::hash`]. As in the rest of the model, the hasher is | ||
| /// threaded by value (`h: H` in, `H` out) rather than by `&mut`. | ||
| #[hax_lib::requires(true)] | ||
| fn hash<H: Hasher>(&self, h: H) -> H; | ||
| } | ||
|
|
||
| // Temporary | ||
| impl<T> Hash for T { | ||
| fn hash<H: Hasher>(&self, h: H) -> H { | ||
| crate::panicking::internal::panic() | ||
| } | ||
| // The integer `Hash` impls that std keeps in `core::hash::impls`. The model's | ||
| // `Hasher` is abstract, so the hashed value is not meaningful — each impl just | ||
| // feeds a byte to `write` (a single cast byte keeps the bodies uniform without | ||
| // needing `to_ne_bytes`). | ||
| macro_rules! impl_hash_for_int { | ||
| ($($t:ty),*) => { | ||
| $( | ||
| #[hax_lib::attributes] | ||
| impl Hash for $t { | ||
| fn hash<H: Hasher>(&self, mut h: H) -> H { | ||
| h.write(&[*self as u8]); | ||
| h | ||
| } | ||
| } | ||
| )* | ||
| }; | ||
|
Comment on lines
+22
to
+33
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't we implement this correctly? Should we establish some way of keeping track where we intentionally deviate from the official implementation? |
||
| } | ||
|
|
||
| impl_hash_for_int!( | ||
| core::primitive::u8, | ||
| core::primitive::u16, | ||
| core::primitive::u32, | ||
| core::primitive::u64, | ||
| core::primitive::u128, | ||
| core::primitive::usize, | ||
| core::primitive::i8, | ||
| core::primitive::i16, | ||
| core::primitive::i32, | ||
| core::primitive::i64, | ||
| core::primitive::i128, | ||
| core::primitive::isize | ||
| ); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| /// See [`core::intrinsics::unreachable`]. Reaching this is undefined behaviour | ||
| /// in Rust; in the model we treat it as an (unreachable) panic, with a | ||
| /// `requires(false)` precondition so callers must prove it is never hit. | ||
| #[hax_lib::opaque] | ||
| #[hax_lib::requires(false)] | ||
| pub fn unreachable() -> ! { | ||
| panic!() | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like Claude felt a bit too chatty :-).
Does this need a comment at all? If so, I would write: "Use rust primitive instead of
x.len()to avoid forward reference in Lean."