Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

static invariant{} should either work or not be valid syntax #17856

Open
dlangBugzillaToGithub opened this issue Apr 12, 2018 · 8 comments
Open

Comments

@dlangBugzillaToGithub
Copy link

FeepingCreature (@FeepingCreature) reported this on 2018-04-12T13:15:37Z

Transferred from https://issues.dlang.org/show_bug.cgi?id=18757

CC List

Description

Right now, you can define a struct to have a static invariant:

struct S {
  static invariant { assert(false); }
  static void foo() { }
}

But the invariant will not be checked when calling foo.

Either this should work, or "static invariant {}" should be a syntax error.
@dlangBugzillaToGithub
Copy link
Author

razvan.nitu1305 commented on 2018-04-16T12:42:26Z

(In reply to FeepingCreature from comment #0)
> Right now, you can define a struct to have a static invariant:
> 
> struct S {
>   static invariant { assert(false); }
>   static void foo() { }
> }
> 
> But the invariant will not be checked when calling foo.
> 
> Either this should work, or "static invariant {}" should be a syntax error.

Placing static in front of an invariant has no effect on the invariant. The problem with the above code is that the method foo is marked as static:

struct S
{
    invariant { (assert (false); }
    static void foo() {}
}

void main()
{
    S s;
    s.foo(); \\ invariant does not get called
}

while :

struct S
{
    static invariant { (assert (false); }
    void foo() {}
}

void main()
{
    S s;
    s.foo(); \\ invariant does get called
}

So we can conclude that invariants are not called for static functions. The spec does not mention anything about this so there are 2 possibilities :

1. Invariants were designed only for struct/class instances (in which case the bug report will be closed with a spec update)

2. Invariants should also be called when static methods are called (in which case this should be fixed)

@dlangBugzillaToGithub
Copy link
Author

default_357-line (@FeepingCreature) commented on 2018-04-16T13:43:21Z

In case 1, I maintain that this is a bug - the compiler should not smile-and-nod while silently ignoring syntax that hints at a semantic that does not apply.

@dlangBugzillaToGithub
Copy link
Author

uplink.coder commented on 2018-04-16T14:31:57Z

Well invariants cannot apply to static methods since they are only concerned about the object's state.
which by definition cannot be directly touched in static functions.
that's why it's not called.

I don't see that there is a basis to issue a warning.

@dlangBugzillaToGithub
Copy link
Author

razvan.nitu1305 commented on 2018-04-16T14:46:31Z

(In reply to uplink.coder from comment #3)
> Well invariants cannot apply to static methods since they are only concerned
> about the object's state.
> which by definition cannot be directly touched in static functions.
> that's why it's not called.
> 
> I don't see that there is a basis to issue a warning.

What about object that have static fields? If you have a static function which modify static fields? I would argue that an invariant might want to check whether a static function has modified the state of the object.

@dlangBugzillaToGithub
Copy link
Author

issues.dlang (@jmdavis) commented on 2018-04-16T16:07:00Z

(In reply to FeepingCreature from comment #2)
> In case 1, I maintain that this is a bug - the compiler should not
> smile-and-nod while silently ignoring syntax that hints at a semantic that
> does not apply.

The reality of the matter is that the compiler ignores attributes like statict all over the place (e.g. static on most things at module scope is allowed and ignored, and you can do something like put @safe on a member variable without complaint from the compiler). If anything, it's extremely typical for the compiler to ignore attributes that don't apply rather than to treat them as an error. In some ways, this can be annoying, but it does help avoid problems in generic code. So, whether an error should be given in this particular case and not others is up for debate, but it's par for the course around here.

(In reply to RazvanN from comment #4)
> What about object that have static fields? If you have a static function
> which modify static fields? I would argue that an invariant might want to
> check whether a static function has modified the state of the object.

We could certainly add a feature like that, but it's certainly not what invariant was designed for. Its purpose was specifically to verify the state of an object, and arguably, the static fields of an object aren't any different from those at module-sope except for the fact that they're scoped to be inside a struct or class. And as such, having an invariant for them would be pretty weird and is of pretty debatable value. If we went down that route, the question would become why we don't have module-level invariants.

@dlangBugzillaToGithub
Copy link
Author

default_357-line (@FeepingCreature) commented on 2018-04-16T17:43:06Z

In my opinion, static this sets the precedent that static + class-level feature = module-level feature.

@dlangBugzillaToGithub
Copy link
Author

bugzilla (@WalterBright) commented on 2018-04-16T18:32:11Z

A `static invariant` does not have special semantics distinct from `invariant` other than it does not have a `this` parameter. That fully explains the observed behavior. The `static` is not ignored:

  struct S {
    int i;
    static invariant { assert (i == 3); } // Error: need this for i of type int
    void foo() {}
  }

  void main() {
    S s;
    s.foo(); // invariant does get called
  }

Whether that is desirable behavior or not is another matter entirely. Our general practice when confronted with these sorts of issues is to make it an error until we figure out what is the best approach, if there even is one, rather than inventing arbitrary behavior without much of any supporting rationale or use cases.

@dlangBugzillaToGithub
Copy link
Author

andrei (@andralex) commented on 2018-04-16T18:47:01Z

The problem is that static methods don't call the static invariant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant