www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - `static` on module-level functions

reply IchorDev <zxinsworld gmail.com> writes:
Can anyone point me to a part of the D spec that says what 
`static` means when applied to functions that are declared at 
module scope? (Other than module constructors, obviously)
I used to assume the property would do something, so I actually 
used it in a lot of my code when I was first learning D. Now 
someone I work with who’s newer to the language is now also going 
through this phase. The assumption of both me and them was that a 
static module-level function would more-or-less work like a 
function with `pragma(inline, true)`, which makes more sense if 
you overlook how `static` usually applies to *functions* and you 
instead look at how `static` applies to almost everything else: 
variables (their initialisation is compile-time), `if`, 
`foreach`, and `assert`. However, I haven’t seen *anything* to 
suggest that `static` even does anything at all in this case; it 
also doesn’t give you a compiler error or even a warning, is it 
like this to make automatic code generation easier, or does it 
actually do something? Maybe D’s spec could be tweaked to make 
this a bit clearer? On quite a few occasions I’ve searched for 
info about this and found nothing relevant.

P.S. If it doesn’t actually do anything, I wonder if something 
like the behaviour of “static import” would be desirable?
Jul 06 2023
parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
Yes, static on a free-function does not do anything.

```
; [#uses = 0]
; Function Attrs: uwtable

   ret void
}
```

```
; [#uses = 0]
; Function Attrs: uwtable

   ret void
}
```

Looks identical to me (LDC, LLVM IR).

As for inlining, backends like LLVM will freely inline if they feel it 
is a good idea. You don't need to use the pragma, it only overrides the 
logic.
Jul 06 2023
parent reply IchorDev <zxinsworld gmail.com> writes:
On Friday, 7 July 2023 at 03:18:53 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
 Yes, static on a free-function does not do anything.
Good to know. I think the D spec should definitely be amended to explicitly mention that static *can* be applied to them, but doesn't do anything.
Jul 07 2023
parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
Static does do something on functions when they are not free-functions.

https://dlang.org/spec/attribute.html#static

However yes, it does not describe what a free-function is there.

https://issues.dlang.org/show_bug.cgi?id=24038
Jul 07 2023
parent reply IchorDev <zxinsworld gmail.com> writes:
On Friday, 7 July 2023 at 10:01:41 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
 Static does do something on functions when they are not 
 free-functions.

 https://dlang.org/spec/attribute.html#static
Well yes, I even mentioned that in the OP. It's just that I'd expect using `static` "incorrectly" to cause an error, like `const` does. Instead, marking something as `static` *actually* does nothing, and nothing really tells you, so it causes a bit of a placebo effect.
 https://issues.dlang.org/show_bug.cgi?id=24038
Thank you! :)
Jul 07 2023
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/7/23 6:38 AM, IchorDev wrote:
 
 Well yes, I even mentioned that in the OP. It's just that I'd expect 
 using `static` "incorrectly" to cause an error, like `const` does. 
 Instead, marking something as `static` *actually* does nothing, and 
 nothing really tells you, so it causes a bit of a placebo effect.
D allows no-op attributes in many cases because you can possibly apply attributes to a group via `attribute:` or `attribute { ... }`, and you may not want to fine-tune which things can get the attribute to avoid errors. Here's a fun one: ```d enum foo() { return "what?"; } ``` What does this mean? `enum` is a storage class, and any storage class applied to a function is going to cause the function to be inferred return type. So effectively, the `enum` does nothing but take the place of `auto`. (`foo` is a function that returns `string`) However, I can't think of a valid reason to allow `static` on a module-level scope. Applying static to a declaration at module-level should be a no-op. So maybe that's one "use" of static that can be eliminated. -Steve
Jul 07 2023
next sibling parent Paul Backus <snarwin gmail.com> writes:
On Friday, 7 July 2023 at 13:31:59 UTC, Steven Schveighoffer 
wrote:
 However, I can't think of a valid reason to allow `static` on a 
 module-level scope. Applying static to a declaration at 
 module-level should be a no-op. So maybe that's one "use" of 
 static that can be eliminated.
Well, it can be used to work around this bug: https://issues.dlang.org/show_bug.cgi?id=17435 So we might want to fix that issue before we make module-level `static` an error.
Jul 07 2023
prev sibling parent IchorDev <zxinsworld gmail.com> writes:
On Friday, 7 July 2023 at 13:31:59 UTC, Steven Schveighoffer 
wrote:
 D allows no-op attributes in many cases because you can 
 possibly apply attributes to a group via `attribute:` or 
 `attribute { ... }`, and you may not want to fine-tune which 
 things can get the attribute to avoid errors.

 Here's a fun one:

 ```d
 enum foo() {
    return "what?";
 }
 ```

 What does this mean? `enum` is a storage class, and any storage 
 class applied to a function is going to cause the function to 
 be inferred return type. So effectively, the `enum` does 
 nothing but take the place of `auto`. (`foo` is a function that 
 returns `string`)

 However, I can't think of a valid reason to allow `static` on a 
 module-level scope. Applying static to a declaration at 
 module-level should be a no-op. So maybe that's one "use" of 
 static that can be eliminated.

 -Steve
Ah yes, that's another beginner's trap—`enum` functions. We should really make `enum` for functions mean "CTFE-only", or something similar. Granted, you can *kinda* do that already with lambda enums, as long as you make sure not to call them in runtime code. However, enum templates can't be implicitly instantiated from eponymous lambda parameters like with function templates, and getting errors about "`__lambda7`" instead of "`thisFnName`" isn't great either. As it is, it at least makes it possible for BetterC code to use compile-time GC for mixin generation, I just wish it was a little bit nicer.
Jul 09 2023