Skip to content
This repository has been archived by the owner on Apr 5, 2024. It is now read-only.

Unsafe Mutability Polymorphism #31

Open
arielb1 opened this issue Sep 25, 2016 · 1 comment
Open

Unsafe Mutability Polymorphism #31

arielb1 opened this issue Sep 25, 2016 · 1 comment

Comments

@arielb1
Copy link
Contributor

arielb1 commented Sep 25, 2016

One popular example of code where we are not certain about its UB status is mutability polymorphism:

struct BTree<K, V> { /* .. */ }

impl<K: Ord, V> BTree<K, V> {
    fn get<'a>(&'a self, key: &K) -> Option<&'a V> { /* ... */ }

    fn get_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V> {
        self.get(key).map(|v| unsafe { &mut *v })
    }

    // <or vice-versa>
}

Of course, the usage pattern is calling get_mut and then mutating the value. However, with both the ACA and CA models, a reference derived from an &-reference has no write permissions, and writing through it causes self-aliasing-violation and UB.

OTOH, having get call get_mut rather than vice-versa does not seem to create UB under both rules (because the reference is asserted only for reading), but without write-asserts to arguments we have the write-not-in-program issue.

Still, having one of these cases UB and the other well-defined is ugly, and hard to tell to users.

@RalfJung
Copy link
Member

OTOH, having get call get_mut rather than vice-versa does not seem to create UB under both rules (because the reference is asserted only for reading), but without write-asserts to arguments we have the write-not-in-program issue.

Notice that this would be a violation of the types that are given; get_mut may assume that nobody else has any pointer to self (nor to anything owned or uniquely borrowed by self) and may hence optimize accordingly. I take it that's not captured by ACA/CA because get_mut does not actually mutate anything -- no assertion happens just by the mere presence of an argument of a given type (with the type implying some capabilities).

Could one argue that, when get is called with more capabilities than are needed (i.e., from get_mut), those additional capabilities flow through the function and the returned pointer actually carries the capability to mutate, and hence is safe to cast to a mutable borrow?

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

No branches or pull requests

2 participants