Stream: general

Topic: UB catched by Miri - no item to reborrow for Unique


lovecs0079 (May 10 2019 at 13:31, on Zulip):

Hi, I'm writing a solution for LeetCode Problem 19 - Remove Nth Node From End of List. I tried to use unsafe to implement a O(1) space-consuming O(n) time-consuming solution, however miri throws out an error and I found that this error means there is an illegal alias of a Box. How could I fix the mut_safe_wrapper function to pass miri's test? Thanks!
The code is here: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=0948f675999232949f3b0c37ecf4fde2

Jake Goulding (May 10 2019 at 14:42, on Zulip):

Related: How to remove the Nth node from the end of a linked list?

lovecs0079 (May 10 2019 at 15:09, on Zulip):

Related: How to remove the Nth node from the end of a linked list?

Thanks for the link, but I really want to write a fast-slow-link solution with an unsafe to safe wrapper.
BTW, my solution can be compiled and runs fine, however Miri indicates that there is an UB. I want to eliminate that.

Jake Goulding (May 10 2019 at 15:36, on Zulip):

runs fine [...] there is an UB

You can't have both ;-)

lovecs0079 (May 10 2019 at 15:39, on Zulip):

Miri said the UB comes from an alias of Box, I double checked my code dropping all const references before transmute to prevent aliases…

RalfJ (May 10 2019 at 17:11, on Zulip):

the UB seems to be inside an implicit drop

RalfJ (May 10 2019 at 17:14, on Zulip):

you are casting a shared ref to a mutable ref? I am wondering why this doesnt explode earlier^^

RalfJ (May 10 2019 at 17:20, on Zulip):

FWIW, drop(prev) cannot possible help, it can only harm. Dropping a mutable ref is basically a NOP, but also counts as a "use" of the ref and hence checks that the ref is still valid. Removing that doesn't help here though.

RalfJ (May 10 2019 at 17:20, on Zulip):

I am not sure what concretely is the cause here, but transmuting a shared ref to a mutable is a no-go

RalfJ (May 10 2019 at 17:20, on Zulip):

you cannot have mutable access to a shared ref

Jake Goulding (May 10 2019 at 17:42, on Zulip):

@RalfJ while I was writing a solution to this, I wanted to convert Option<Box<T>> into a *mut T — is there a straight-forward way of doing that?

RalfJ (May 10 2019 at 17:50, on Zulip):

hm. don't know. I'd start with .map(Box::into_raw_non_null)

RalfJ (May 10 2019 at 17:51, on Zulip):

there might be things between Option<NonNull<T>> and raw ptrs

Jake Goulding (May 10 2019 at 21:01, on Zulip):

into_raw... would take ownership, which I wouldn't want. I think that transmute may actually be the shortest point from A to B, which is rarely a good sign ;-)

nagisa (May 10 2019 at 23:55, on Zulip):

Once you have a raw pointer, you can copy it and reconstruct the box back.

Jake Goulding (May 11 2019 at 00:13, on Zulip):

true, but if I'm starting with e.g. &self i'd run into a problem. I could use as_ref / as_mut of course

lovecs0079 (May 11 2019 at 00:41, on Zulip):

you cannot have mutable access to a shared ref

Thank you Ralf, just known drop(prev) is not helpful

RalfJ (May 13 2019 at 13:11, on Zulip):

Ah, I think I finally understood why casting the shared ref to a mutable didn't explode earlier here... you are casting through a raw pointer, and this happens inside a Box. When you use the raw ptr to write to that Box, Miri thinks that this must be the raw ptr originally allocated by exchange_malloc (in Box::new) -- that is the only raw ptr in existence that you are allowed to use for writing. This of course invalidates all pointers created later, including the Box pointer that is later being used for dropping.

Last update: Nov 20 2019 at 13:00UTC