www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Problem with dmd-2.104.0 -dip1000 & safe

reply An Pham <home home.com> writes:
Getting with below error for following codes. Look like bug?
onlineapp.d(61): Error: scope variable `a` assigned to non-scope 
parameter `a` calling `foo`

      safe:

     struct A(S = string)
     {
      safe:
         S s;
         void delegate() c;
     }

     struct B(S = string)
     {
      safe:
          disable this();

         this(C!S c, A!S a)
         {
             this.c = c;
             this.a = a;
         }

         C!S foo()
         {
             return c;
         }

         A!S a;
         C!S c;
     }

     class C(S = string)
     {
      safe:
         C!S foo(A!S a)
         {
             auto o = new Object();
             return foo2(o, a);
         }

         C!S foo2(Object n, A!S a)
         {
             auto b = B!S(this, a);
          	return b.foo();
         }
     }

     unittest
     {
         static struct X
         {
          safe:
         	void foo3()
     		{
         	}
         }

         X x;
         A!string a;
         a.s = "foo";
         a.c = &x.foo3;
         auto c = new C!string();
         c.foo(a);
     }

void main()
{
}
Jun 08 2023
next sibling parent Dennis <dkorpel gmail.com> writes:
On Friday, 9 June 2023 at 04:05:27 UTC, An Pham wrote:
 Getting with below error for following codes. Look like bug?
Filed as https://issues.dlang.org/show_bug.cgi?id=23985 You can work around it by marking parameter `a` as `return scope`
Jun 10 2023
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 6/9/23 06:05, An Pham wrote:
 Getting with below error for following codes. Look like bug?
 onlineapp.d(61): Error: scope variable `a` assigned to non-scope 
 parameter `a` calling `foo`
 
       safe:
 
      struct A(S = string)
      {
       safe:
          S s;
          void delegate() c;
      }
 
      struct B(S = string)
      {
       safe:
           disable this();
 
          this(C!S c, A!S a)
          {
              this.c = c;
              this.a = a;
          }
 
          C!S foo()
          {
              return c;
          }
 
          A!S a;
          C!S c;
      }
 
      class C(S = string)
      {
       safe:
          C!S foo(A!S a)
          {
              auto o = new Object();
              return foo2(o, a);
          }
 
          C!S foo2(Object n, A!S a)
          {
              auto b = B!S(this, a);
               return b.foo();
          }
      }
 
      unittest
      {
          static struct X
          {
           safe:
              void foo3()
              {
              }
          }
 
          X x;
          A!string a;
          a.s = "foo";
          a.c = &x.foo3;
          auto c = new C!string();
          c.foo(a);
      }
 
 void main()
 {
 }
 
I think the behavior you are seeing here is by design. There are two things happening: - There is no `scope` inference for virtual methods, as it is impossible to get the inference right without knowing all overriding methods in advance. - You cannot mark the parameter `a` `scope`, because the lifetimes of `this` and `a` become conflated within `b` in the body of `foo2` when calling the constructor of `B!S`, and `this` is subsequently escaped. As Dennis points out, a workaround is to mark the parameter `a` `return scope`. However, this may lead to other problems down the line, as `a` is never actually escaped.
Jun 11 2023