Thread overview
Labelled @nogc Working With Inner Scopes
Aug 30, 2021
Benoît Dubreuil
Aug 30, 2021
Ali Çehreli
Aug 31, 2021
Benoît Dubreuil
Aug 31, 2021
Mike Parker
August 30, 2021

I've got the following module dummy.dummy.d:

module dummy;

@safe:
@nogc:

struct Dummy
{
    // TODO: Why do I need to repeat those? Aren't the formers still effective for inner scopes?
@safe:
@nogc:
    static const int MAX_MEMBER_INT = 3;

    int memberInt;
    string memberStr;

    this(int memberInt, string memberStr) nothrow
    in
    {
        assert(memberInt > MAX_MEMBER_INT);
    }
    out
    {
        assert(this.memberInt == memberInt);
        assert(this.memberStr == memberStr);
    }
    do
    {
        this.memberInt = memberInt;
        this.memberStr = memberStr;
    }

    int doStuff() pure nothrow
    {
        auto result = this.memberInt - 1;

        if (result <= MAX_MEMBER_INT)
            result = 1 + MAX_MEMBER_INT;

        return result;
    }
}

I've also got the following module dummy.test.d:

module test;

@safe:
@nogc:
private:

version (unittest)
{
    import dummy;

    /// Test [cg.math.dummy.dummy.Dummy.doStuff()]
    unittest
    {
        Dummy instance = Dummy(4, "A dummy string");
        assert(instance.doStuff() > Dummy.MAX_MEMBER_INT);
    }
}

My question is:

>

In the source file dummy.dummy.d, why the first labelled attributes @safe and @nogc have no effect inside the struct's scope? In other words, why do I need to repeat labelled attributes statements in order to affect inner scopes?

To test this, simply remove in dummy.dummy.d the TODO comment and its following labelled attributes.

August 30, 2021
I don't have a strong opinion on the question but I tend to agree with the current behavior because it's easy to add the attributes anyway.

Going off topic, I want to mention that the 'in' and 'out' contracts have a simpler syntax now and that the 'do' (or 'body') keyword is optional in that place:

struct Dummy
{
// ...

  this(int memberInt, string memberStr) nothrow
  in (memberInt > MAX_MEMBER_INT, "You can put a message here")
  out (; this.memberInt == memberInt, "etc.")
  out (; this.memberStr == memberStr, "etc.")
  {
    this.memberInt = memberInt;
    this.memberStr = memberStr;
  }
}

I am reminded that the semicolons in the 'out' contracts are necessary even for a function that does not return a value (like a constructor does not).

Ali

August 31, 2021

On Monday, 30 August 2021 at 20:26:46 UTC, Benoît Dubreuil wrote:

>

My question is:

>

In the source file dummy.dummy.d, why the first labelled attributes @safe and @nogc have no effect inside the struct's scope? In other words, why do I need to repeat labelled attributes statements in order to affect inner scopes?

To test this, simply remove in dummy.dummy.d the TODO comment and its following labelled attributes.

Attributes used to propagate into aggregate definitions, but it was changed a long time ago. I don't recall the reason why.

August 31, 2021

On Monday, 30 August 2021 at 20:58:01 UTC, Ali Çehreli wrote:

>

I don't have a strong opinion on the question but I tend to agree with the current behavior because it's easy to add the attributes anyway.

On Tuesday, 31 August 2021 at 00:36:46 UTC, Mike Parker wrote:

>

Attributes used to propagate into aggregate definitions, but it was changed a long time ago. I don't recall the reason why.

Thank you both for your answers. Subjectively, it seems easy to forget to manually repeat labelled attribute statements. I guess I'll just use attributes directly on declarations instead.

On Monday, 30 August 2021 at 20:58:01 UTC, Ali Çehreli wrote:

>

Going off topic, I want to mention that the 'in' and 'out' contracts have a simpler syntax now and that the 'do' (or 'body') keyword is optional in that place:

Great, thanks. I was also searching how to separate multiple contracts for the same function, so it answered this other question.