Skip to content
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

Remove some uses of unsafe from Myers pattern matching and fastexp #398

Merged
merged 2 commits into from Jan 7, 2021

Conversation

huonw
Copy link
Contributor

@huonw huonw commented Dec 13, 2020

There's two uses of unsafe that aren't necessary for performance
or functionality:

The latter flags a minor safety issue: the
ShortTracebackHandler::column_slice method had an incorrect lifetime
in its return value. It was incorrectly suggesting that the returned
slice lived for longer than the self value. In particular, code
could write something like (in pseudo-Rust, with named lifetimes of
locals):

let states: &'outer [State<T, T::DistType>] = ...;
let column: &'outer [State<T, T::DistType>];
{
    let handler = ShortTracebackHandler::new(.., states);
    column = handler.column_slice(); // refers to handler.state
} // handler becomes invalid, as does handler.state

println!("{}", column); // invalid use of reference to handler.state

This method is private and explicitly designed for debugging use only,
and so (a) this minor safety issue probably doesn't cause issues in
practice, and (b) the fix doesn't break any existing code.

After this PR, the only two remaining uses of unsafe are the following, which are likely important for performance (#229 introduced them and states "Benchmarks are around 1.5 x faster when using unsafe").

#[inline]
fn set_max_state(&self, pos: usize, states: &mut [State<T, T::DistType>]) {
//states[pos] = State::max();
*unsafe { states.get_unchecked_mut(pos) } = State::max();
}
#[inline]
fn add_state(
&self,
source: &Self::TracebackColumn,
pos: usize,
states: &mut [State<T, T::DistType>],
) {
//states[pos] = source.clone();
*unsafe { states.get_unchecked_mut(pos) } = source.clone();
}

There's two uses of `unsafe` that aren't necessary:

- using a union to convert between raw bits in a f64 floating point
  format and f64 itself, because there's the safe f64::from_bits
  function in std

- using from_raw_parts to build a slice &[T] from a single &T, because
  there's the safe slice::from_ref function in std

The latter flags a minor safety issue: the
ShortTracebackHandler::column_slice method had an incorrect lifetime
in its return value. It was incorrectly suggesting that the returned
slice lived for longer than the `self` value. In particular, code
could write something like (in pseudo-Rust, with named lifetimes of
locals):

    let states: &'outer [State<T, T::DistType>] = ...;
    let column: &'outer [State<T, T::DistType>];
    {
        let handler = ShortTracebackHandler::new(.., states);
        column = handler.column_slice(); // refers to handler.state
    } // handler becomes invalid, as does handler.state

    println!("{}", column); // invalid use of reference to handler.state

This method is private and explicitly designed for debugging use only,
and so (a) this minor safety issue probably doesn't cause issues in
practice, and (b) the fix doesn't break any existing code.
@coveralls
Copy link

Coverage Status

Coverage increased (+0.02%) to 86.85% when pulling eb0f7ba on huonw:less-unsafe into 480872e on rust-bio:master.

Copy link
Contributor

@johanneskoester johanneskoester left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot, very good catch!

@johanneskoester johanneskoester merged commit 1cc6d16 into rust-bio:master Jan 7, 2021
@huonw huonw deleted the less-unsafe branch January 8, 2021 00:19
@huonw
Copy link
Contributor Author

huonw commented Jan 8, 2021

No worries, thanks for merging!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants