Thread overview | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
December 18, 2018 Temporary @trusted scope | ||||
---|---|---|---|---|
| ||||
What's the preferred way of creating a temporary @trusted scope without writing a separate function? Similar to Rust's unsafe { /* unsafe stuff here */ } |
December 18, 2018 Re: Temporary @trusted scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Per Nordlöw | On Tuesday, December 18, 2018 3:14:50 AM MST Per Nordlöw via Digitalmars-d- learn wrote:
> What's the preferred way of creating a temporary @trusted scope without writing a separate function?
>
> Similar to Rust's
>
> unsafe { /* unsafe stuff here */ }
Unfortunately, D does not currently have a way to do that. Only functions can be marked with @trusted. However, the typical approach to this problem is to use a lambda, which is more or less syntactically the same except that it has some extra parens. e.g.
() @trusted { doUnsafe(); }();
or
auto result = () @trusted { getUnsafe:() }();
So, it's less than ideal, but it gets us close, and unless the code is long enough that maybe it should be in its own function, it's better than declaring a nested function, let alone declaring an entirely separate function at module scope.
- Jonathan M Davis
|
December 18, 2018 Re: Temporary @trusted scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Per Nordlöw | On Tuesday, 18 December 2018 at 10:14:50 UTC, Per Nordlöw wrote:
> What's the preferred way of creating a temporary @trusted scope without writing a separate function?
Jonathan's idea might also be encapsulated in a function, just like assumeUnique in Phobos:
import std.stdio;
template unsafe(alias fn) {
@trusted auto unsafe(T...)(T args) {
return fn(args);
}
}
@system void fun(int n) {
writeln("foo!");
}
@safe unittest {
unsafe!({
fun(2);
});
unsafe!fun(2);
}
--
Simen
|
December 18, 2018 Re: Temporary @trusted scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Tuesday, 18 December 2018 at 10:42:51 UTC, Jonathan M Davis wrote:
> Unfortunately, D does not currently have a way to do that. Only functions can be marked with @trusted. However, the typical approach to this problem is to use a lambda, which is more or less syntactically the same except that it has some extra parens. e.g.
>
> () @trusted { doUnsafe(); }();
Is there a performance hit when using this?
|
December 19, 2018 Re: Temporary @trusted scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Per Nordlöw | On 19/12/2018 1:34 AM, Per Nordlöw wrote:
> On Tuesday, 18 December 2018 at 10:42:51 UTC, Jonathan M Davis wrote:
>> Unfortunately, D does not currently have a way to do that. Only functions can be marked with @trusted. However, the typical approach to this problem is to use a lambda, which is more or less syntactically the same except that it has some extra parens. e.g.
>>
>> () @trusted { doUnsafe(); }();
>
> Is there a performance hit when using this?
Yes except for ldc with -O3.
But it is a function not a delegate so it should be all nicely prefetched and ready to go. So I wouldn't worry about it too much.
|
December 18, 2018 Re: Temporary @trusted scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | On 12/18/18 6:29 AM, Simen Kjærås wrote:
> On Tuesday, 18 December 2018 at 10:14:50 UTC, Per Nordlöw wrote:
>> What's the preferred way of creating a temporary @trusted scope without writing a separate function?
>
> Jonathan's idea might also be encapsulated in a function, just like assumeUnique in Phobos:
>
> import std.stdio;
>
> template unsafe(alias fn) {
> @trusted auto unsafe(T...)(T args) {
> return fn(args);
> }
> }
>
> @system void fun(int n) {
> writeln("foo!");
> }
>
> @safe unittest {
> unsafe!({
> fun(2);
> });
>
> unsafe!fun(2);
> }
Wow, I really like this. The only real problem is that one generally searches for @trusted when looking for unsafe code, but unsafe is pretty obvious too. Also, args should be auto ref.
Only thing better I can think of (for the second example) is to define a prototype with the correct information, only with @trusted (and specify the mangle). But any decent compiler should get rid of any overhead there.
-Steve
|
December 18, 2018 Re: Temporary @trusted scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Tuesday, 18 December 2018 at 13:52:29 UTC, Steven Schveighoffer wrote:
>> template unsafe(alias fn) {
>> @trusted auto unsafe(T...)(T args) {
>> return fn(args);
>> }
>> }
Very nice! What about proposing this for inclusion into `std.typecons` or `std.meta`?
|
December 18, 2018 Re: Temporary @trusted scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Tue, Dec 18, 2018 at 08:52:29AM -0500, Steven Schveighoffer via Digitalmars-d-learn wrote: > On 12/18/18 6:29 AM, Simen Kjærås wrote: > > On Tuesday, 18 December 2018 at 10:14:50 UTC, Per Nordlöw wrote: > > > What's the preferred way of creating a temporary @trusted scope without writing a separate function? > > > > Jonathan's idea might also be encapsulated in a function, just like assumeUnique in Phobos: > > > > import std.stdio; > > > > template unsafe(alias fn) { > > @trusted auto unsafe(T...)(T args) { > > return fn(args); > > } > > } > > > > @system void fun(int n) { > > writeln("foo!"); > > } > > > > @safe unittest { > > unsafe!({ > > fun(2); > > }); > > > > unsafe!fun(2); > > } > > Wow, I really like this. The only real problem is that one generally searches for @trusted when looking for unsafe code, but unsafe is pretty obvious too. Also, args should be auto ref. > > Only thing better I can think of (for the second example) is to define a prototype with the correct information, only with @trusted (and specify the mangle). But any decent compiler should get rid of any overhead there. [...] I'm not so sure I like this. @trusted bits of code really should have a safe API that cannot be called in a way that breaks @safe. Being able to essentially "cast away" @safe for arbitrary bits of code seems to me to be a rather scary, underhanded way of undermining @safe. OTOH, if your function is very large and only isolated bits are non-@safe, then a construct like this one could help, by making the code less noisy, and ensuring that the other parts of the code still remain @safe. (Though IMO in such cases the function may be better refactored to encapsulate away the @trusted bits in functions with safe APIs, and keep the @safe code all in one place.) T -- MASM = Mana Ada Sistem, Man! |
December 18, 2018 Re: Temporary @trusted scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On 12/18/18 10:53 AM, H. S. Teoh wrote: > On Tue, Dec 18, 2018 at 08:52:29AM -0500, Steven Schveighoffer via Digitalmars-d-learn wrote: >> On 12/18/18 6:29 AM, Simen Kjærås wrote: >>> On Tuesday, 18 December 2018 at 10:14:50 UTC, Per Nordlöw wrote: >>>> What's the preferred way of creating a temporary @trusted scope >>>> without writing a separate function? >>> >>> Jonathan's idea might also be encapsulated in a function, just like >>> assumeUnique in Phobos: >>> >>> import std.stdio; >>> >>> template unsafe(alias fn) { >>> @trusted auto unsafe(T...)(T args) { >>> return fn(args); >>> } >>> } >>> >>> @system void fun(int n) { >>> writeln("foo!"); >>> } >>> >>> @safe unittest { >>> unsafe!({ >>> fun(2); >>> }); >>> >>> unsafe!fun(2); >>> } >> >> Wow, I really like this. The only real problem is that one generally >> searches for @trusted when looking for unsafe code, but unsafe is >> pretty obvious too. Also, args should be auto ref. >> >> Only thing better I can think of (for the second example) is to define >> a prototype with the correct information, only with @trusted (and >> specify the mangle). But any decent compiler should get rid of any >> overhead there. > [...] > > I'm not so sure I like this. @trusted bits of code really should have a > safe API that cannot be called in a way that breaks @safe. Being able to > essentially "cast away" @safe for arbitrary bits of code seems to me to > be a rather scary, underhanded way of undermining @safe. You may not be realizing what the point of this is. Essentially, you replace your inline trusted lambda with this call. It's just nicer syntax/usage without all the extra parentheses. Other than that, every usage of it would need as much scrutiny as a trusted lambda. > OTOH, if your function is very large and only isolated bits are > non-@safe, then a construct like this one could help, by making the code > less noisy, and ensuring that the other parts of the code still remain > @safe. (Though IMO in such cases the function may be better refactored > to encapsulate away the @trusted bits in functions with safe APIs, and > keep the @safe code all in one place.) Yes, exactly. The point of trusted lambdas are so that only the parts you want to trust are actually trusted, the rest of the function is safe. It doesn't prevent you from having to locally verify that implementation leaks don't happen (for example, ()@trusted {free(ptr);}() can still leak dangling pointers out into the @safe portion), but it allows you to focus where your code is trusted. For more details, see this: https://dlang.org/blog/2016/09/28/how-to-write-trusted-code-in-d/ -Steve |
December 18, 2018 Re: Temporary @trusted scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Tuesday, 18 December 2018 at 13:52:29 UTC, Steven Schveighoffer wrote: > On 12/18/18 6:29 AM, Simen Kjærås wrote: >> On Tuesday, 18 December 2018 at 10:14:50 UTC, Per Nordlöw wrote: >>> What's the preferred way of creating a temporary @trusted scope without writing a separate function? >> >> Jonathan's idea might also be encapsulated in a function, just like assumeUnique in Phobos: >> >> import std.stdio; >> >> template unsafe(alias fn) { >> @trusted auto unsafe(T...)(T args) { >> return fn(args); >> } >> } >> >> @system void fun(int n) { >> writeln("foo!"); >> } >> >> @safe unittest { >> unsafe!({ >> fun(2); >> }); >> >> unsafe!fun(2); >> } > > Wow, I really like this. The only real problem is that one generally searches for @trusted when looking for unsafe code, but unsafe is pretty obvious too. Also, args should be auto ref. > > Only thing better I can think of (for the second example) is to define a prototype with the correct information, only with @trusted (and specify the mangle). But any decent compiler should get rid of any overhead there. > > -Steve I've been gathering assume related stuff like this in a lib under an "assume" template. You can generalize further with multiple attributes inside a non-eponymous thing and use them like: assume!fun.safe_(2); assume!fun.nogc_(2); I guess it's no very idiomatic D though, but I feel it reads better ... ok well maybe 🤷♂️: https://aliak00.github.io/bolts/bolts/assume/assume.html Easier to be more specific with searches for "assumeSafe" instead of just "assume!" though. Cheers, - Ali |
Copyright © 1999-2021 by the D Language Foundation