December 08

What's wrong with using non@safe actions which creates and modifies some external objects?

class Layer {
    int index;
    string name;
    this(int index, string name) {

class SignalLayer : Layer {
class UserLayer : Layer {

class PCB {
    Layer[] layer;

PT _deflayer(PT)(PT p) {
    auto index = to!int(p.matches[0]);
    switch (p.matches[2]) {
    case "signal":
        pcb.layer ~= new SignalLayer(index, p.matches[1]); break;
    case "user":
        pcb.layer ~= new UserLayer(index, p.matches[1]); break;
    default:
        break;
    }
    return p;
}

mixin(grammar(`
    parser:
        kicad_pcb <  :l :'kicad_pcb' verzion host general page layers
        layers    <  :l :'layers' (deflayer {_deflayer})+ :r
        deflayer  <  :l unum layer ('signal'|'user') :r

../.dub/packages/pegged/0.4.9/pegged/pegged/peg.d(3049,19): Error: `@safe` function `pegged.peg.action!(wrapAround, _deflayer).action` cannot call `@system` function `kicad._deflayer!(ParseTree)._deflayer`
src/kicad.d(27,5):        which calls `kicad.SignalLayer.this`
src/kicad.d(68,4):        `kicad._deflayer!(ParseTree)._deflayer` is declared here
src/kicad.d-mixin-83(219,289): Error: template instance `pegged.peg.action!(wrapAround, _deflayer)` error instantiating
src/kicad.d-mixin-83(932,7):        instantiated from here: `Genericparser!(ParseTree)`
../.dub/packages/pegged/0.4.9/pegged/pegged/peg.d(544,20): Error: none of the overloads of `layers` are callable using argument types `(GetName)`
src/kicad.d-mixin-83(215,23):        Candidates are: `kicad.Genericparser!(ParseTree).Genericparser.parser.layers(ParseTree p)`
src/kicad.d-mixin-83(234,23):                        `kicad.Genericparser!(ParseTree).Genericparser.parser.layers(string s)`
../.dub/packages/pegged/0.4.9/pegged/pegged/peg.d(1598,24): Error: template instance `pegged.peg.getName!(layers)` error instantiating
src/kicad.d-mixin-83(183,436):        instantiated from here: `wrapAround!(named, layers, named)`
src/kicad.d-mixin-83(932,7):        instantiated from here: `Genericparser!(ParseTree)`
December 08
On Friday, December 8, 2023 10:13:21 AM MST Dmitry Ponyatov via Digitalmars-d- learn wrote:
> What's wrong with using non@safe actions which creates and modifies some external objects?
>
> ```D
> class Layer {
>      int index;
>      string name;
>      this(int index, string name) {
>
> class SignalLayer : Layer {
> class UserLayer : Layer {
>
> class PCB {
>      Layer[] layer;
>
> PT _deflayer(PT)(PT p) {
>      auto index = to!int(p.matches[0]);
>      switch (p.matches[2]) {
>      case "signal":
>          pcb.layer ~= new SignalLayer(index, p.matches[1]); break;
>      case "user":
>          pcb.layer ~= new UserLayer(index, p.matches[1]); break;
>      default:
>          break;
>      }
>      return p;
> }
>
> mixin(grammar(`
>      parser:
>          kicad_pcb <  :l :'kicad_pcb' verzion host general page
> layers
>          layers    <  :l :'layers' (deflayer {_deflayer})+ :r
>          deflayer  <  :l unum layer ('signal'|'user') :r
>
> ```
> ```
> ../.dub/packages/pegged/0.4.9/pegged/pegged/peg.d(3049,19):
> Error: `@safe` function `pegged.peg.action!(wrapAround,
> _deflayer).action` cannot call `@system` function
> `kicad._deflayer!(ParseTree)._deflayer`
> src/kicad.d(27,5):        which calls `kicad.SignalLayer.this`
> src/kicad.d(68,4):        `kicad._deflayer!(ParseTree)._deflayer`
> is declared here
> src/kicad.d-mixin-83(219,289): Error: template instance
> `pegged.peg.action!(wrapAround, _deflayer)` error instantiating
> src/kicad.d-mixin-83(932,7):        instantiated from here:
> `Genericparser!(ParseTree)`
> ../.dub/packages/pegged/0.4.9/pegged/pegged/peg.d(544,20): Error:
> none of the overloads of `layers` are callable using argument
> types `(GetName)`
> src/kicad.d-mixin-83(215,23):        Candidates are:
> `kicad.Genericparser!(ParseTree).Genericparser.parser.layers(ParseTree p)`
> src/kicad.d-mixin-83(234,23):
> `kicad.Genericparser!(ParseTree).Genericparser.parser.layers(string s)`
> ../.dub/packages/pegged/0.4.9/pegged/pegged/peg.d(1598,24):
> Error: template instance `pegged.peg.getName!(layers)` error
> instantiating
> src/kicad.d-mixin-83(183,436):        instantiated from here:
> `wrapAround!(named, layers, named)`
> src/kicad.d-mixin-83(932,7):        instantiated from here:
> `Genericparser!(ParseTree)`
> ```

Since I've never used pegged, I can't really comment on the specific semantics of what you're trying to do. However, any function which is marked as @safe cannot call any functions that are @system. So, if pegged is marking a function as @safe, and it is then trying to call your function, your function then needs to be @safe or @trusted, regardless of what it's actually doing, which means that you need to then make it so that your function either isn't doing anything that's @system so that it can be @safe, or you need to vet what it's doing to make sure that it's actually memory-safe in spite of the fact that the compiler can't verify it, in which case, you would need to mark it as @trusted.

The default for functions is @system, and none of the code you've shown is marked with @safe. Templated functions and functions which return auto will have their attributes inferred, which includes @safe, so if _deflayer is not calling any @system functions or doing any operations which are @system, it will be inferred as @safe. However, it looks like the constructors that it's calling are not marked with @safe and are not templated. So, they will not infer their attributes and will be @system, which will in turn mean that _deflayer gets inferred as @system. And if pegged is calling _deflayer from code that's marked with @safe, then you're going to get a compilation error.

So, based on what I can see here, it looks like you need to be marking your functions with @safe where you can, and if any of your code is doing stuff that isn't guaranteed to be memory-safe (and thus can't be @safe), then you'll need to make sure that what it's doing is actually memory-safe (in spite of the fact that the compiler can't guarantee it) and mark it with @trusted to indicate that you've verified it, and then @safe code can call it.

- Jonathan M Davis