Unnamed repository; edit this file 'description' to name the repository.
Implement `slice_get_unchecked` mir shim
| -rw-r--r-- | crates/hir-ty/src/mir/eval/shim.rs | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs index e569b32bd7..177b2c870f 100644 --- a/crates/hir-ty/src/mir/eval/shim.rs +++ b/crates/hir-ty/src/mir/eval/shim.rs @@ -1012,6 +1012,43 @@ impl<'a, 'db> Evaluator<'a, 'db> { let dst = Interval { addr: dst, size }; dst.write_from_interval(self, src) } + "slice_get_unchecked" => { + let [slice_ptr, index] = args else { + return Err(MirEvalError::InternalError( + "slice_get_unchecked args are not provided".into(), + )); + }; + let Some(ty) = generic_args.as_slice().get(2).and_then(|it| it.ty()) else { + return Err(MirEvalError::InternalError( + "slice_get_unchecked item type is not provided".into(), + )); + }; + let slice_ptr = slice_ptr.get(self)?; + let ptr_size = self.ptr_size(); + let Some(data) = slice_ptr.get(..ptr_size) else { + return Err(MirEvalError::InternalError( + "slice_get_unchecked slice pointer is too small".into(), + )); + }; + let Some(len) = slice_ptr.get(ptr_size..2 * ptr_size) else { + return Err(MirEvalError::InternalError( + "slice_get_unchecked slice metadata is missing".into(), + )); + }; + let slice_ptr = Address::from_bytes(data)?; + let len = from_bytes!(usize, len); + let index = from_bytes!(usize, index.get(self)?); + if index >= len { + return Err(MirEvalError::UndefinedBehavior(format!( + "slice_get_unchecked index {index} is out of bounds for slice of length {len}" + ))); + } + let size = self.size_of_sized(ty, locals, "slice_get_unchecked item type")?; + let offset = index* size; + let addr = slice_ptr.to_usize() + offset; + let addr = Address::from_usize(addr); + destination.write_from_bytes(self, &addr.to_bytes()[..destination.size]) + } "offset" | "arith_offset" => { let [ptr, offset] = args else { return Err(MirEvalError::InternalError("offset args are not provided".into())); |