Unsafe functions are a strict super-set of safe functions. It seems like fns should freely coerce to the unsafe fn of the appropriate type (i.e. fn() -> () to unsafe fn() -> ()). See this playground link for an example. Is there any particular reason not to allow this?
fn() -> () coerces to unsafe fn() -> () right now. Modified example:
fn print_hello() -> () {
println!("Hello!");
}
// Calls an unsafe function
fn call_unsafe(func: unsafe fn() -> ()) -> () {
unsafe { func() }
}
fn main() {
call_unsafe(print_hello as fn() -> ()); // OK
}
The problem is that print_hello is not a function pointer fn() -> (), but a unique unnameable function type fn() -> () {print_hello} that can be coerced to fn() -> (), so coercion to unsafe fn() -> () actually requires two coercions, and transitive coercions don't work yet, but they are supposed to work eventually.
@petrochenkov Is it hard to add note to mention that as is required to make it?
Yeah, I'd at least like to figure out if we can change the compiler error that occurs at the callsite. I never would have thought to cast to fn() -> () in order to get an unsafe fn() -> (), especially since a cast directly to unsafe fn() -> () errors as a non-scalar cast.
@nikomatsakis Should we just allow reification from a safe function to an unsafe fn pointer?
@KalitaAlexey
Is it hard to add note to mention that as is required to make it?
I don't know exactly, but I suspect that simply adding a direct coercion fn() {f} -> unsafe fn() is not harder than adding the note.
@petrochenkov I think this is required some discussion between rust team. I'd like to have it because it doesn't do anything bad.
@eddyb I think so
This is just a matter of combining coerce_from_fn_item and coerce_from_fn_pointer here, right?
@cramertj Sort of, except the safe -> unsafe ptr case would have to also be safe -> safe in coerce_from_fn_item, so combining them might not work out that nicely.
Right-- there are three possible end types for a safe fn item, compared to the two that exist currently.
Most helpful comment
fn() -> ()coerces tounsafe fn() -> ()right now. Modified example:The problem is that
print_hellois not a function pointerfn() -> (), but a unique unnameable function typefn() -> () {print_hello}that can be coerced tofn() -> (), so coercion tounsafe fn() -> ()actually requires two coercions, and transitive coercions don't work yet, but they are supposed to work eventually.