162306a36Sopenharmony_ci// SPDX-License-Identifier: Apache-2.0 OR MIT
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci// Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
462306a36Sopenharmony_ci//
562306a36Sopenharmony_ci// The idea is: The length field in SetLenOnDrop is a local variable
662306a36Sopenharmony_ci// that the optimizer will see does not alias with any stores through the Vec's data
762306a36Sopenharmony_ci// pointer. This is a workaround for alias analysis issue #32155
862306a36Sopenharmony_cipub(super) struct SetLenOnDrop<'a> {
962306a36Sopenharmony_ci    len: &'a mut usize,
1062306a36Sopenharmony_ci    local_len: usize,
1162306a36Sopenharmony_ci}
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ciimpl<'a> SetLenOnDrop<'a> {
1462306a36Sopenharmony_ci    #[inline]
1562306a36Sopenharmony_ci    pub(super) fn new(len: &'a mut usize) -> Self {
1662306a36Sopenharmony_ci        SetLenOnDrop { local_len: *len, len }
1762306a36Sopenharmony_ci    }
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci    #[inline]
2062306a36Sopenharmony_ci    pub(super) fn increment_len(&mut self, increment: usize) {
2162306a36Sopenharmony_ci        self.local_len += increment;
2262306a36Sopenharmony_ci    }
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci    #[inline]
2562306a36Sopenharmony_ci    pub(super) fn current_len(&self) -> usize {
2662306a36Sopenharmony_ci        self.local_len
2762306a36Sopenharmony_ci    }
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ciimpl Drop for SetLenOnDrop<'_> {
3162306a36Sopenharmony_ci    #[inline]
3262306a36Sopenharmony_ci    fn drop(&mut self) {
3362306a36Sopenharmony_ci        *self.len = self.local_len;
3462306a36Sopenharmony_ci    }
3562306a36Sopenharmony_ci}
36