May 28, 2016
On Saturday, 28 May 2016 at 13:03:10 UTC, Adam D. Ruppe wrote:
> What kind of pointer usage do you have? Remember that basic & and * operations ARE @safe.
>
> If you have more internally, you might be able to wrap them up in an @trusted function to again allow inference to work.

Ouch! I was under the impression that any pointer usage was forbidden in @safe code.

I have some structures holding pointers to other structures, and I'd like all of this structures being usable in @safe code. The problem of some structures being deallocated while others are holding pointers to them cannot exist in my scenario, so I'm sure that my code can be @trusted.

The only problem is that these structures are parameterized, and the type parameters may have unsafe operations that I use.
May 28, 2016
On Saturday, 28 May 2016 at 13:10:56 UTC, Lodovico Giaretta wrote:
> On Saturday, 28 May 2016 at 13:03:10 UTC, Adam D. Ruppe wrote:
>> What kind of pointer usage do you have? Remember that basic & and * operations ARE @safe.
>>
>> If you have more internally, you might be able to wrap them up in an @trusted function to again allow inference to work.
>
> Ouch! I was under the impression that any pointer usage was forbidden in @safe code.

 Pointers by themselves are safe (as they have to point to something valid to start with); It's manipulating pointers that's usually unsafe (and the easiest source of bugs with pointers involved).
May 28, 2016
On Saturday, 28 May 2016 at 13:10:56 UTC, Lodovico Giaretta wrote:
> The only problem is that these structures are parameterized, and the type parameters may have unsafe operations that I use.

 Do you still want the template i'm building? It doesn't like stack frame pointers, but will work with regular structs. I'm still new to using traits myself so why it's getting me i don't know.
May 28, 2016
On Saturday, 28 May 2016 at 14:01:35 UTC, Era Scarecrow wrote:
> On Saturday, 28 May 2016 at 13:10:56 UTC, Lodovico Giaretta wrote:
>> The only problem is that these structures are parameterized, and the type parameters may have unsafe operations that I use.
>
>  Do you still want the template i'm building? It doesn't like stack frame pointers, but will work with regular structs. I'm still new to using traits myself so why it's getting me i don't know.

Thank you very much for your effort.
Please if you don't need it, don't make it, because I don't know if I'll use it.
If I'll decide to go with it, I'll make it myself. I don't want to waste your time in something I may not use.

Sorry for using your time, and thank you again.
May 28, 2016
On Saturday, 28 May 2016 at 14:11:56 UTC, Lodovico Giaretta wrote:
> On Saturday, 28 May 2016 at 14:01:35 UTC, Era Scarecrow wrote:
>>  Do you still want the template i'm building?
>
> Thank you very much for your effort.
> Please if you don't need it, don't make it, because I don't know if I'll use it. If I'll decide to go with it, I'll make it myself. I don't want to waste your time in something I may not use.
>
> Sorry for using your time, and thank you again.

 It's very much a learning experience. I'll tinker with this more.
May 28, 2016
On 05/28/2016 02:43 PM, Lodovico Giaretta wrote:
> struct S1
> {
>      int doSomething() @safe
>      {
>          // do something safely
>          return 1;
>      }
> }
>
> struct S2
> {
>      int doSomething() @system
>      {
>          // do something usafe
>          return 2;
>      }
> }
>
> auto doSomethingDumb(T)(ref T t)
> {
>      T* pt = &t;
>      return pt.doSomething();
> }
>
> auto s1 = S1();
> auto s2 = S2();
> auto x = doSomethingDumb(s1); // this call should be possible in @safe code
> auto y = doSomethingDumb(s2); // this should only be possible in @system
> code

I'm not sure if should mention it, but there is this little trick:

----
auto doSomethingDumb(T)(ref T t)
{
    T* pt;
    () @trusted { pt = &t; } (); /* Ok, because the reference is never returned. NOTE: DON'T RETURN THIS POINTER! */
    return pt.doSomething();
}
----

Though in cases like this it's kind of an anti-pattern. The trusted code itself isn't actually safe, but the compiler thinks so. So you have to manually verify that doSomethingDumb is safe, even though it's not marked @trusted. That's pretty bug-prone.
May 28, 2016
On Saturday, 28 May 2016 at 14:11:56 UTC, Lodovico Giaretta wrote:
> On Saturday, 28 May 2016 at 14:01:35 UTC, Era Scarecrow wrote:
>>  Do you still want the template i'm building?
>
> Thank you very much for your effort.
> Please if you don't need it, don't make it, because I don't know if I'll use it.

 Well here's what i got. Maybe someone else will tell me how i did this wrong...

[code]
import std.traits;

template areAllFunctionsSafe(T)
if (!isNested!T) { //nested may be lifted later when i fix this
  enum areAllFunctionsSafe = check();

  bool check() {
    foreach(member; __traits(allMembers, T)) {
      static if(isCallable!(__traits(getMember, T, member))) {
        if (!isSafe!(__traits(getMember, T, member)))
          return false;
      }
    }
    return true;
  }
}

unittest {
  static struct S {
    int y;
    void foo() @safe {}
    void bar() @safe {}
  }
  static struct S2 {
    int y;
    void foo() @safe {}
    void bar() {}
  }

  assert(areAllFunctionsSafe!S);
  assert(!areAllFunctionsSafe!S2);
}
[/code]
May 29, 2016
On Saturday, 28 May 2016 at 14:54:13 UTC, Era Scarecrow wrote:
>  Well here's what i got. Maybe someone else will tell me how i did this wrong...

 Using the pragma to output how the lines were being generated i finally figured out why it kept complaining about the stack pointer and 'this'. So adding in a simple check to ignore 'this' entries.

So, final version:

bool areAllFunctionsSafe(T)() {
  foreach(member; __traits(allMembers, T)) {
    static if(member!="this" && isCallable!(__traits(getMember, T, member)))
      if (!isSafe!(__traits(getMember, T, member))) return false;
  }
  return true;
}

May 29, 2016
On 5/28/16 7:50 AM, Lodovico Giaretta wrote:
> Let's say I have a generic function that uses pointers. It will be
> inferred @system by the compiler, but I know that the pointer usage can
> be @trusted.
> The problem is that if I declare the function @trusted, I'm also
> implicitly trusting any call to @system methods of the template parameter.
>
> Dumb example (pointer usage can be trusted, but doSomething may not):
>
>     auto doSomethingDumb(T)(ref T t) // I want it @trusted if
> doSomething is at least @trusted
>     {
>         T* pt = &t;
>         return pt.doSomething();
>     }
>
> Is there any way around this? Any way to declare a function @trusted as
> long as the methods of the template argument are at least @trusted?
>
> Thank you in advance.

You can create a trusted expression by using a lambda and immediately calling it. ag0aep6g brought it up.

I would write it like this (untested, but I think this works):

return (()@trusted => &t)().doSomething();

The key is to limit your code that is tainted by @trusted to as little code as possible.

Note that doSomethingDumb will be inferred @safe and not @trusted. The compiler should NEVER infer @trusted (for obvious reasons).

-Steve
May 31, 2016
On Sunday, 29 May 2016 at 18:02:53 UTC, Steven Schveighoffer wrote:
> You can create a trusted expression by using a lambda and immediately calling it. ag0aep6g brought it up.
>
> I would write it like this (untested, but I think this works):
>
> return (()@trusted => &t)().doSomething();
>
> The key is to limit your code that is tainted by @trusted to as little code as possible.

This does indeed solve the problem without replicating code and costraints.
It allows to just trust the parts of the function that can be trusted.

Thank you very much.

Lodovico Giaretta


1 2
Next ›   Last »