Quantcast

Declaring the API unsafe while keeping the internal safety checks

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Declaring the API unsafe while keeping the internal safety checks

Vladimir Pouzanov
I had this idea for some time and I'd like to discuss it to see if it is something reasonable to be proposed for rust to implement or there are other ways around the problem.

Let's say I have a low level function that manipulates the hardware clock using some platform-specific argument. Internally this function will do an unsafe volatile mem write to store value in the register, but this is the only part of the code that is unsafe compiler-wise, whatever else is in there in the function is safe and I want the compiler to warn me if any other unsafe operation happens.

Now, given that this function is actually unsafe in terms of its realtime consequences (it does not do any validation of the input for speed) I want to mark it as unsafe fn and make a safer wrapper for end users, while keeping this for the little subset of users that will need the actual speed benefits.

Unfortunately, marking it unsafe will now allow any other unsafe operation in the body of the function, when what I wanted is just to force users of it to be aware of unsafety via compiler validation.

A safe {} block could have helped me in this case. But is it a good idea overall?

Some pseudo-code to illustrate

pub unsafe fn set_clock_mode(mode: uint32) {
  // ...
  // doing some required computations
  // this code must be 'safe' for the compiler
  unsafe {
    // ...
    // writing the value to mmaped register, this one is unsafe but validated by programmer
  }
}

pub fn set_clock_mode_safe(mode: uint32) -> bool {
  // ...
  // validate input
  unsafe {
    // I want this call to require unsafe block
    set_clock_mode(mode);
  }
}

--
Sincerely,
Vladimir "Farcaller" Pouzanov
http://farcaller.net/

_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Declaring the API unsafe while keeping the internal safety checks

Manish Goregaokar
It should be reasonably easy to write a lint as a compiler plugin such that the following function:

#[unsafe_specific]
unsafe fn foo () {
 #[allowed_unsafe] { // or just #[allow(unsafe_something_something)]
  // do unsafe things here
 }
 // no unsafe blocks or functions allowed here.
}

would not compile with any unsafe code in the latter half of the function.

Alternatively:

unsafe fn foo() {
 fn bar() {
  unsafe {
    // unsafe stuff here
  }
  // no unsafe stuff here
 }
 bar();
}

-Manish Goregaokar

On Thu, Jan 1, 2015 at 4:47 PM, Vladimir Pouzanov <[hidden email]> wrote:
I had this idea for some time and I'd like to discuss it to see if it is something reasonable to be proposed for rust to implement or there are other ways around the problem.

Let's say I have a low level function that manipulates the hardware clock using some platform-specific argument. Internally this function will do an unsafe volatile mem write to store value in the register, but this is the only part of the code that is unsafe compiler-wise, whatever else is in there in the function is safe and I want the compiler to warn me if any other unsafe operation happens.

Now, given that this function is actually unsafe in terms of its realtime consequences (it does not do any validation of the input for speed) I want to mark it as unsafe fn and make a safer wrapper for end users, while keeping this for the little subset of users that will need the actual speed benefits.

Unfortunately, marking it unsafe will now allow any other unsafe operation in the body of the function, when what I wanted is just to force users of it to be aware of unsafety via compiler validation.

A safe {} block could have helped me in this case. But is it a good idea overall?

Some pseudo-code to illustrate

pub unsafe fn set_clock_mode(mode: uint32) {
  // ...
  // doing some required computations
  // this code must be 'safe' for the compiler
  unsafe {
    // ...
    // writing the value to mmaped register, this one is unsafe but validated by programmer
  }
}

pub fn set_clock_mode_safe(mode: uint32) -> bool {
  // ...
  // validate input
  unsafe {
    // I want this call to require unsafe block
    set_clock_mode(mode);
  }
}

--
Sincerely,
Vladimir "Farcaller" Pouzanov
http://farcaller.net/

_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev



_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Declaring the API unsafe while keeping the internal safety checks

Vladimir Pouzanov
Sounds reasonably simple, thanks for the idea!

On Thu, Jan 1, 2015 at 11:46 AM, Manish Goregaokar <[hidden email]> wrote:
It should be reasonably easy to write a lint as a compiler plugin such that the following function:

#[unsafe_specific]
unsafe fn foo () {
 #[allowed_unsafe] { // or just #[allow(unsafe_something_something)]
  // do unsafe things here
 }
 // no unsafe blocks or functions allowed here.
}

would not compile with any unsafe code in the latter half of the function.

Alternatively:

unsafe fn foo() {
 fn bar() {
  unsafe {
    // unsafe stuff here
  }
  // no unsafe stuff here
 }
 bar();
}

-Manish Goregaokar

On Thu, Jan 1, 2015 at 4:47 PM, Vladimir Pouzanov <[hidden email]> wrote:
I had this idea for some time and I'd like to discuss it to see if it is something reasonable to be proposed for rust to implement or there are other ways around the problem.

Let's say I have a low level function that manipulates the hardware clock using some platform-specific argument. Internally this function will do an unsafe volatile mem write to store value in the register, but this is the only part of the code that is unsafe compiler-wise, whatever else is in there in the function is safe and I want the compiler to warn me if any other unsafe operation happens.

Now, given that this function is actually unsafe in terms of its realtime consequences (it does not do any validation of the input for speed) I want to mark it as unsafe fn and make a safer wrapper for end users, while keeping this for the little subset of users that will need the actual speed benefits.

Unfortunately, marking it unsafe will now allow any other unsafe operation in the body of the function, when what I wanted is just to force users of it to be aware of unsafety via compiler validation.

A safe {} block could have helped me in this case. But is it a good idea overall?

Some pseudo-code to illustrate

pub unsafe fn set_clock_mode(mode: uint32) {
  // ...
  // doing some required computations
  // this code must be 'safe' for the compiler
  unsafe {
    // ...
    // writing the value to mmaped register, this one is unsafe but validated by programmer
  }
}

pub fn set_clock_mode_safe(mode: uint32) -> bool {
  // ...
  // validate input
  unsafe {
    // I want this call to require unsafe block
    set_clock_mode(mode);
  }
}

--
Sincerely,
Vladimir "Farcaller" Pouzanov
http://farcaller.net/

_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev





--
Sincerely,
Vladimir "Farcaller" Pouzanov
http://farcaller.net/

_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Declaring the API unsafe while keeping the internal safety checks

Huon Wilson
In reply to this post by Manish Goregaokar
Attributes cannot (yet) be attached to blocks so this can't work atm, e.g.

    fn main() {
        #[whoops] { /* ... */ }
    }

gives

    <anon>:2:13: 2:14 error: expected item after attributes
    <anon>:2     #[whoops] { /* ... */ }
                         ^

It possibly makes sense to have a distinction between "functions that are unsafe to call" and "functions that can call unsafe functions internally", i.e. have `unsafe fn foo() { ... }` *not* be the same as `unsafe fn foo() { unsafe { ... } }`, although I imagine that this may make certain cases rather uglier.

Huon

On 01/01/15 22:46, Manish Goregaokar wrote:
It should be reasonably easy to write a lint as a compiler plugin such that the following function:

#[unsafe_specific]
unsafe fn foo () {
 #[allowed_unsafe] { // or just #[allow(unsafe_something_something)]
  // do unsafe things here
 }
 // no unsafe blocks or functions allowed here.
}

would not compile with any unsafe code in the latter half of the function.

Alternatively:

unsafe fn foo() {
 fn bar() {
  unsafe {
    // unsafe stuff here
  }
  // no unsafe stuff here
 }
 bar();
}

-Manish Goregaokar

On Thu, Jan 1, 2015 at 4:47 PM, Vladimir Pouzanov <[hidden email]> wrote:
I had this idea for some time and I'd like to discuss it to see if it is something reasonable to be proposed for rust to implement or there are other ways around the problem.

Let's say I have a low level function that manipulates the hardware clock using some platform-specific argument. Internally this function will do an unsafe volatile mem write to store value in the register, but this is the only part of the code that is unsafe compiler-wise, whatever else is in there in the function is safe and I want the compiler to warn me if any other unsafe operation happens.

Now, given that this function is actually unsafe in terms of its realtime consequences (it does not do any validation of the input for speed) I want to mark it as unsafe fn and make a safer wrapper for end users, while keeping this for the little subset of users that will need the actual speed benefits.

Unfortunately, marking it unsafe will now allow any other unsafe operation in the body of the function, when what I wanted is just to force users of it to be aware of unsafety via compiler validation.

A safe {} block could have helped me in this case. But is it a good idea overall?

Some pseudo-code to illustrate

pub unsafe fn set_clock_mode(mode: uint32) {
  // ...
  // doing some required computations
  // this code must be 'safe' for the compiler
  unsafe {
    // ...
    // writing the value to mmaped register, this one is unsafe but validated by programmer
  }
}

pub fn set_clock_mode_safe(mode: uint32) -> bool {
  // ...
  // validate input
  unsafe {
    // I want this call to require unsafe block
    set_clock_mode(mode);
  }
}

--
Sincerely,
Vladimir "Farcaller" Pouzanov
http://farcaller.net/

_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev




_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev


_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Declaring the API unsafe while keeping the internal safety checks

David Henningsson-2
In reply to this post by Vladimir Pouzanov


On 2015-01-01 12:17, Vladimir Pouzanov wrote:

> I had this idea for some time and I'd like to discuss it to see if it is
> something reasonable to be proposed for rust to implement or there are
> other ways around the problem.
>
> Let's say I have a low level function that manipulates the hardware
> clock using some platform-specific argument. Internally this function
> will do an unsafe volatile mem write to store value in the register, but
> this is the only part of the code that is unsafe compiler-wise, whatever
> else is in there in the function is safe and I want the compiler to warn
> me if any other unsafe operation happens.
>
> Now, given that this function is actually unsafe in terms of its
> realtime consequences (it does not do any validation of the input for
> speed) I want to mark it as unsafe fn and make a safer wrapper for end
> users, while keeping this for the little subset of users that will need
> the actual speed benefits.
>
> Unfortunately, marking it unsafe will now allow any other unsafe
> operation in the body of the function, when what I wanted is just to
> force users of it to be aware of unsafety via compiler validation.

I would typically do:

#[inline]
fn do_some_required_computations() { /* execute safe code here */ }

pub unsafe fn set_clock_mode(mode: uint32) {
     do_some_required_computations();
     // write the value to mmaped register
}

That said, I believe Rust's idea of what is "unsafe" is pretty
restricted to memory safety, and one would not typically mark things
that are unsafe by other means as "unsafe".

>
> A safe {} block could have helped me in this case. But is it a good idea
> overall?
>
> Some pseudo-code to illustrate
>
> pub unsafe fn set_clock_mode(mode: uint32) {
>    // ...
>    // doing some required computations
>    // this code must be 'safe' for the compiler
>    unsafe {
>      // ...
>      // writing the value to mmaped register, this one is unsafe but
> validated by programmer
>    }
> }
>
> pub fn set_clock_mode_safe(mode: uint32) -> bool {
>    // ...
>    // validate input
>    unsafe {
>      // I want this call to require unsafe block
>      set_clock_mode(mode);
>    }
> }
>
> --
> Sincerely,
> Vladimir "Farcaller" Pouzanov
> http://farcaller.net/
>
>
> _______________________________________________
> Rust-dev mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/rust-dev
>

--
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic
_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Declaring the API unsafe while keeping the internal safety checks

David Henningsson
In reply to this post by Vladimir Pouzanov


On 2015-01-01 12:17, Vladimir Pouzanov wrote:

> I had this idea for some time and I'd like to discuss it to see if it is
> something reasonable to be proposed for rust to implement or there are
> other ways around the problem.
>
> Let's say I have a low level function that manipulates the hardware
> clock using some platform-specific argument. Internally this function
> will do an unsafe volatile mem write to store value in the register, but
> this is the only part of the code that is unsafe compiler-wise, whatever
> else is in there in the function is safe and I want the compiler to warn
> me if any other unsafe operation happens.
>
> Now, given that this function is actually unsafe in terms of its
> realtime consequences (it does not do any validation of the input for
> speed) I want to mark it as unsafe fn and make a safer wrapper for end
> users, while keeping this for the little subset of users that will need
> the actual speed benefits.
>
> Unfortunately, marking it unsafe will now allow any other unsafe
> operation in the body of the function, when what I wanted is just to
> force users of it to be aware of unsafety via compiler validation.

I would typically do:

#[inline]
fn do_some_required_computations() { /* execute safe code here */ }

pub unsafe fn set_clock_mode(mode: uint32) {
     do_some_required_computations();
     // write the value to mmaped register
}

That said, I believe Rust's idea of what is "unsafe" is pretty
restricted to memory safety, and one would not typically mark things
that are unsafe by other means as "unsafe".

>
> A safe {} block could have helped me in this case. But is it a good idea
> overall?
>
> Some pseudo-code to illustrate
>
> pub unsafe fn set_clock_mode(mode: uint32) {
>    // ...
>    // doing some required computations
>    // this code must be 'safe' for the compiler
>    unsafe {
>      // ...
>      // writing the value to mmaped register, this one is unsafe but
> validated by programmer
>    }
> }
>
> pub fn set_clock_mode_safe(mode: uint32) -> bool {
>    // ...
>    // validate input
>    unsafe {
>      // I want this call to require unsafe block
>      set_clock_mode(mode);
>    }
> }
>
> --
> Sincerely,
> Vladimir "Farcaller" Pouzanov
> http://farcaller.net/
>
>
> _______________________________________________
> Rust-dev mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/rust-dev
>

--
David Henningsson, Canonical Ltd.
https://launchpad.net/~diwic
_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Declaring the API unsafe while keeping the internal safety checks

Kevin McGuire
In reply to this post by Vladimir Pouzanov

Yes unsafe is primarily for memory safety. However! Your idea is good. It would be really good if you could have something like that. I am just not sure what the best way to do it is. It could be done by an attribute and lint with the ability to toggle it off with a module level, function level, or scope level second attribute, lol, possibilities are endless.

But indeed unsafe is likely only, currently, for memory safety.

Still I like the idea! I love the idea. I read your email earlier today but only shortly ago I realize what you mean.

On Jan 1, 2015 5:17 AM, "Vladimir Pouzanov" <[hidden email]> wrote:
I had this idea for some time and I'd like to discuss it to see if it is something reasonable to be proposed for rust to implement or there are other ways around the problem.

Let's say I have a low level function that manipulates the hardware clock using some platform-specific argument. Internally this function will do an unsafe volatile mem write to store value in the register, but this is the only part of the code that is unsafe compiler-wise, whatever else is in there in the function is safe and I want the compiler to warn me if any other unsafe operation happens.

Now, given that this function is actually unsafe in terms of its realtime consequences (it does not do any validation of the input for speed) I want to mark it as unsafe fn and make a safer wrapper for end users, while keeping this for the little subset of users that will need the actual speed benefits.

Unfortunately, marking it unsafe will now allow any other unsafe operation in the body of the function, when what I wanted is just to force users of it to be aware of unsafety via compiler validation.

A safe {} block could have helped me in this case. But is it a good idea overall?

Some pseudo-code to illustrate

pub unsafe fn set_clock_mode(mode: uint32) {
  // ...
  // doing some required computations
  // this code must be 'safe' for the compiler
  unsafe {
    // ...
    // writing the value to mmaped register, this one is unsafe but validated by programmer
  }
}

pub fn set_clock_mode_safe(mode: uint32) -> bool {
  // ...
  // validate input
  unsafe {
    // I want this call to require unsafe block
    set_clock_mode(mode);
  }
}

--
Sincerely,
Vladimir "Farcaller" Pouzanov
http://farcaller.net/

_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev


_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Declaring the API unsafe while keeping the internal safety checks

Vladimir Pouzanov
Well, strictly speaking it *is* memory safety, as it all gets down to an unsafe volatile store. Although I think I extend the 'unsafety' a bit by considering code that can cause CPU to halt as unsafe too.

On Fri, Jan 2, 2015 at 2:11 AM, Kevin McGuire <[hidden email]> wrote:

Yes unsafe is primarily for memory safety. However! Your idea is good. It would be really good if you could have something like that. I am just not sure what the best way to do it is. It could be done by an attribute and lint with the ability to toggle it off with a module level, function level, or scope level second attribute, lol, possibilities are endless.

But indeed unsafe is likely only, currently, for memory safety.

Still I like the idea! I love the idea. I read your email earlier today but only shortly ago I realize what you mean.

On Jan 1, 2015 5:17 AM, "Vladimir Pouzanov" <[hidden email]> wrote:
I had this idea for some time and I'd like to discuss it to see if it is something reasonable to be proposed for rust to implement or there are other ways around the problem.

Let's say I have a low level function that manipulates the hardware clock using some platform-specific argument. Internally this function will do an unsafe volatile mem write to store value in the register, but this is the only part of the code that is unsafe compiler-wise, whatever else is in there in the function is safe and I want the compiler to warn me if any other unsafe operation happens.

Now, given that this function is actually unsafe in terms of its realtime consequences (it does not do any validation of the input for speed) I want to mark it as unsafe fn and make a safer wrapper for end users, while keeping this for the little subset of users that will need the actual speed benefits.

Unfortunately, marking it unsafe will now allow any other unsafe operation in the body of the function, when what I wanted is just to force users of it to be aware of unsafety via compiler validation.

A safe {} block could have helped me in this case. But is it a good idea overall?

Some pseudo-code to illustrate

pub unsafe fn set_clock_mode(mode: uint32) {
  // ...
  // doing some required computations
  // this code must be 'safe' for the compiler
  unsafe {
    // ...
    // writing the value to mmaped register, this one is unsafe but validated by programmer
  }
}

pub fn set_clock_mode_safe(mode: uint32) -> bool {
  // ...
  // validate input
  unsafe {
    // I want this call to require unsafe block
    set_clock_mode(mode);
  }
}

--
Sincerely,
Vladimir "Farcaller" Pouzanov
http://farcaller.net/

_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev




--
Sincerely,
Vladimir "Farcaller" Pouzanov
http://farcaller.net/

_______________________________________________
Rust-dev mailing list
[hidden email]
https://mail.mozilla.org/listinfo/rust-dev
Loading...