digitalmars.dip.ideas - safe by default
- Atila Neves (2/2) May 30 https://github.com/atilaneves/DIPs/blob/safe-by-default/safe-by-default....
- Richard (Rikki) Andrew Cattermole (3/3) May 30 Looks good.
- bachmeier (6/8) May 30 How do you turn off safe by default? With a compiler switch? I
- Atila Neves (4/9) May 30 ```
- monkyyy (2/7) May 30 please no
- Nick Treleaven (27/38) May 31 For extern(D), there will be a linker error if a protoype is
- Nick Treleaven (6/15) May 31 Sorry, that doesn't compile even with -dip1000. But this does:
- Dukc (6/10) May 31 I agree in principle, but note this is orthogonal to the DIP. D allows
- Atila Neves (8/18) May 31 This. I don't think we can stop programmers intent on lying to
- Nick Treleaven (14/22) May 31 I agree my argument is not necessarily an impediment to this DIP,
- jmh530 (27/29) May 31 I was glad to see some compromise on this. I'm still not 100%
- Atila Neves (3/15) May 31 It wouldn't compile because of the intrinsics? Wouldn't the fix
- jmh530 (12/15) May 31 Actually it may compile in this case since it looks like they
- Atila Neves (2/16) Jun 03 Fair enough.
- Paul Backus (45/47) May 31 I agree completely that "having [@safe] be opt-in makes it hard
- Jonathan M Davis (29/35) May 31 I think that you will have a hard time finding a consensus on the idea t...
- Atila Neves (13/51) May 31 It might be; it's something Walter and I have discussed before,
- Guillaume Piolat (8/10) May 31 Neutral.
- Timon Gehr (17/20) Jun 01 - I think even more important than the default is the ability to change
- Atila Neves (6/23) Jun 03 That's a good point, but: do we only do it for this attribute or
- Timon Gehr (2/12) Jun 06 Why is this an issue?
- Atila Neves (3/15) Jun 06 The compiler would have access to the body and so would verify
- Timon Gehr (7/24) Jun 07 A function prototype does not have a body and the actual body may be in
- Dukc (9/35) Jun 07 When Átila wrote his last reply I was still agreeing with him. Why? I
- Quirin Schroll (21/23) Jun 03 Because of a lack of mangling, `extern(X)` where `X` isn’t `D`
- Atila Neves (3/9) Jun 03 I could see changing it to this; but what if it's writen in D and
- Quirin Schroll (27/38) Jun 04 TBH, I don’t know what .di files really are. AFAIK, they’re
- Richard (Rikki) Andrew Cattermole (17/36) Jun 04 .di files are currently all hand written.
- Quirin Schroll (31/59) Jun 10 I’m not referring to `extern(D)` functions. I knew those have
- Quirin Schroll (8/50) Jun 10 Missing bits:
- Mathias Lang (15/17) Jun 06 I think it should eventually happen, but we are not ready for it.
Looks good. This is everything I have argued /needs/ to happen (although I'd prefer inferred instead).
May 30
On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/safe-by-default/safe-by-default.md Destroy!How do you turn off safe by default? With a compiler switch? I know some folks think it's good to punish people for writing unsafe code, as became clear in the earlier discussions, but safe by default is of no benefit to me, and I don't want to have to clutter my code with a bunch of boilerplate for no reason.
May 30
On Thursday, 30 May 2024 at 19:41:26 UTC, bachmeier wrote:On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:``` system: ```https://github.com/atilaneves/DIPs/blob/safe-by-default/safe-by-default.md Destroy!How do you turn off safe by default?
May 30
On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/safe-by-default/safe-by-default.md Destroy!All declarations (i.e. functions with no body) must have exactly one of the safe/ trusted/ system annotations or the module that contains them will fail to compileplease no
May 30
On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/safe-by-default/safe-by-default.md Destroy!If there is no body, the compiler cannot verify the safety of the function and in those cases this DIP proposes that there will be no default. All declarations (i.e. functions with no body) must have exactly one of the safe/ trusted/ system annotationsFor extern(D), there will be a linker error if a protoype is safe but the implementation is system. For other linkage, that case would silently link with no error. That breaks the principle of being able to grep for trusted to find an *accidental* safety violation. (Deliberate violation with pragma(mangle) is less serious as that is intentional and stands out more to a reviewer). Module 1: ```d import core.stdc.stdio; system extern(C) void ext(int* p) { p++; printf("%d\n", *p); } ``` Module 2: ```d safe extern(C) void ext(int* p); void main() // implicitly safe { int i; ext(&i); // boom } ``` safe should mean mechanically checked for accidental memory-safety violations - that is a more useful definition. Allowing non-extern(D) linkage prototypes to be safe breaks that principle and makes safe prototypes a minefield.This DIP makes no distinction between extern(D), extern(C), and extern(C++) functions. Although the latter two usually apply to functions written in C or C++ respectively, that is not necessarily the caseA non-extern(D) prototype can be trusted, and its implementation in D can be safe, so the implementation is mechanically checked.
May 31
On Friday, 31 May 2024 at 09:18:17 UTC, Nick Treleaven wrote:Module 2: ```d safe extern(C) void ext(int* p); void main() // implicitly safe { int i; ext(&i); // boom } ```Sorry, that doesn't compile even with -dip1000. But this does: ```d auto p = new int; ext(p); // boom ```
May 31
Nick Treleaven kirjoitti 31.5.2024 klo 12.18:safe should mean mechanically checked for accidental memory-safety violations - that is a more useful definition. Allowing non-extern(D) linkage prototypes to be safe breaks that principle and makes safe prototypes a minefield.I agree in principle, but note this is orthogonal to the DIP. D allows declaring external C functions as ` safe` right now. The DIP should not make it any worse, and it also doesn't prevent a separate proposal that would say that external non-D linked functions must be either ` trusted` or ` system`.
May 31
On Friday, 31 May 2024 at 11:42:13 UTC, Dukc wrote:Nick Treleaven kirjoitti 31.5.2024 klo 12.18:This. I don't think we can stop programmers intent on lying to the compiler. As mentioned there's already `pragma(mangle)`, they can write assembly, ... I think that if there's a body written in D somewhere, it's unlikely someone will manually write a declaration and use the wrong attribute by mistake. And if there isn't, then they will have had to deliberately have picked an attribute.safe should mean mechanically checked for accidental memory-safety violations - that is a more useful definition. Allowing non-extern(D) linkage prototypes to be safe breaks that principle and makes safe prototypes a minefield.I agree in principle, but note this is orthogonal to the DIP. D allows declaring external C functions as ` safe` right now. The DIP should not make it any worse, and it also doesn't prevent a separate proposal that would say that external non-D linked functions must be either ` trusted` or ` system`.
May 31
On Friday, 31 May 2024 at 16:32:37 UTC, Atila Neves wrote:This.I agree my argument is not necessarily an impediment to this DIP, but it is closely related.I don't think we can stop programmers intent on lying to the compiler. As mentioned there's already `pragma(mangle)`,Which sticks out in a review, and is clearly intentional not accidental (as I already said).they can write assembly, ...Actually that supports my case, ` safe` annotated `asm` is deprecated: https://dlang.org/deprecate.html#unannotated%20asm%20blocks You have to write ` trusted` instead, *because it's not mechanically checked*.I think that if there's a body written in D somewhere, it's unlikely someone will manually write a declaration and use the wrong attribute by mistake. And if there isn't, then they will have had to deliberately have picked an attribute.Not convinced it's unlikely - the implementation may be safe when the prototype is written, then the implementation is changed to system and the prototype is forgotten. No reason not to require trusted for prototypes.
May 31
On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/safe-by-default/safe-by-default.md Destroy!I was glad to see some compromise on this. I'm still not 100% behind it, but it is less objectionable than before, IMO. In terms of qualms, here is an example of a module that contains a mix of code, some of which is bringing in compiler intrinsics that don't have function bodies and part of it is additional functions: https://github.com/libmir/mir-core/blob/master/source/mir/math/common.d Under this DIP, this would no longer compile, which is fine it isn't hard to fix. My problem is with your recommendation elsewhere on the thread to add ` system:` at the top. Since the module mixes the intrinsics and functions together, that alone is not sufficient. The templates then would become system instead of having their attributes inferred. One way forward is to move everything without a body into a separate module with ` system:` at the top and publicly import that here. That's ok, although it separates the documentation. The other option is to go function by function to add the system to each function. I think some people have proposed solutions to this issue in the past when this comes up. I think it can't hurt to give some more thought to any improvements that can be brought to bear before this is adopted. You're still potentially in for a lot of code breakage that could keep a lot of people on the old edition for a while. Hopefully the edition approach is able to make ease this transition, although it's hard to ignore the risk of bifurcation.
May 31
On Friday, 31 May 2024 at 12:50:55 UTC, jmh530 wrote:On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:It wouldn't compile because of the intrinsics? Wouldn't the fix then be to add attributes to them?https://github.com/atilaneves/DIPs/blob/safe-by-default/safe-by-default.md Destroy!I was glad to see some compromise on this. I'm still not 100% behind it, but it is less objectionable than before, IMO. In terms of qualms, here is an example of a module that contains a mix of code, some of which is bringing in compiler intrinsics that don't have function bodies and part of it is additional functions: https://github.com/libmir/mir-core/blob/master/source/mir/math/common.d Under this DIP, this would no longer compile,
May 31
On Friday, 31 May 2024 at 16:36:08 UTC, Atila Neves wrote:[snip] It wouldn't compile because of the intrinsics? Wouldn't the fix then be to add attributes to them?Actually it may compile in this case since it looks like they already have attributes at the top of the version block for them. I was trying to use this as an example of a file that has a mix of functions without bodies and templated functions that would have inference. It was meant as a criticism of your idea of putting ` system:` at the top of files as solution to the problem. As I said later in that post, putting ` system:` at the top would force the templated functions to be ` system` too instead of getting inferred. One solution is going function by function as I said in my post, but just putting it at the top isn't a solution.
May 31
On Friday, 31 May 2024 at 17:45:44 UTC, jmh530 wrote:On Friday, 31 May 2024 at 16:36:08 UTC, Atila Neves wrote:Fair enough.[...]Actually it may compile in this case since it looks like they already have attributes at the top of the version block for them. I was trying to use this as an example of a file that has a mix of functions without bodies and templated functions that would have inference. It was meant as a criticism of your idea of putting ` system:` at the top of files as solution to the problem. As I said later in that post, putting ` system:` at the top would force the templated functions to be ` system` too instead of getting inferred. One solution is going function by function as I said in my post, but just putting it at the top isn't a solution.
Jun 03
On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/safe-by-default/safe-by-default.md Destroy!I agree completely that "having [ safe] be opt-in makes it hard to use in practice" and that "defaults matter". However, I think that implementing [Universal Function Attribute Inference][1] would be a better way to address the shortcomings of the current defaults. In ["Thoughts on Backward Compatibility"][2], I tried to figure out why some breaking changes succeed and others fail. The conclusion I came to was that breaking changes are most successful when: 1. Migration is easy, or 2. The change serves a goal that has strong buy-in from users While there is a vocal minority in the D community who strongly support safe (a group in which I include myself), **I do not believe that safe has strong buy-in from D programmers as a whole.** In other words, this proposal cannot satisfy condition (2). It follows that, if we would like it to succeed, it *must* satisfy condition (1). Sadly, I do not think migration to `-preview=safedefault` will be particularly easy. By the DIP's own admission, it "will likely break a lot of code". Even if editions allow us to mix pre-migration and post-migration code in the same project, the burden of migrating to `-preview=safedefault` will likely hurt the adoption of new editions, and cause projects that would otherwise upgrade to get "stuck" in the system-by-default edition. (It is also conceivable that new projects started by D programmers who don't care about safe will choose the old, system-by-default edition specifically to avoid the hassle of adding explicit system attributes to their code.) Universal inference avoids these problems. In most cases, it requires zero manual intervention to migrate existing code (that is, it Just Works™). The only major obstacle it faces is build performance when using separate compilation, and this obstacle can be overcome with toolchain improvements. Inference also solves the wrong-default problem for nogc, nothrow, and pure, in addition to safe, without the need for any additional -preview switches or migrations. Asking users to migrate from system-by-default to safe-by-default may be doable, but can we really ask them to do the same thing *three more times* for the other attributes? [1]: https://forum.dlang.org/thread/pfawiqhppkearetcrkno forum.dlang.org [2]: https://forum.dlang.org/post/axvuuknmtxpmuirbbgax forum.dlang.org
May 31
On Friday, May 31, 2024 7:06:16 AM MDT Paul Backus via dip.ideas wrote:Inference also solves the wrong-default problem for nogc, nothrow, and pure, in addition to safe, without the need for any additional -preview switches or migrations. Asking users to migrate from system-by-default to safe-by-default may be doable, but can we really ask them to do the same thing *three more times* for the other attributes?I think that you will have a hard time finding a consensus on the idea that any of those should be the default. It may be that most folks would agree that safe should be the default, but I'd be _very_ surprised to see a consensus on the others (especially nogc). Personally, I'm increasingly of the opinion that most attributes are actively detrimental rather than beneficial, and I don't want to see them be forced or for them become the default. I think that there's a good argument for making safe the default given that you usually do want most code to be safe, and trusted makes it fairly easy to have system code be used by safe code, but the others often simply do not work with code and get in the way of making changes - especially with larger code bases. So, I very much hope that we don't change the default attributes beyond possibly safe. And considering that DIP 1000 is a thing, I'm definitely concerned about what the repercussions of making safe the default are, since DIP 1000 makes life _way_ too complicated IMHO, and inference will trigger it in a number of cases (to the point that I would be tempted to slap system on everything and give up on any benefits from safe just to escape having to deal with DIP 1000). If DIP 1000 weren't a thing, then I'd probably be okay with safe being the default, but I think that all of these attempts to make malloc safe instead of just saying that if you want safe without trusted, you use the GC, are adding way too much complexity to the language, and making safe the default potentially forces you into that mess - either that or forces you to slap system all over the place. Having more attribute inference may help with some of these issues, but personally, I just want to avoid most attributes in general and not have to deal with stuff like pure, because inevitably, at some point, you have to figure out how to strip it from your code to get something to work. - Jonathan M Davis
May 31
On Friday, 31 May 2024 at 13:06:16 UTC, Paul Backus wrote:On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:It might be; it's something Walter and I have discussed before, and the reason that didn't go forward is due to the potential compile-time performance penalties. If it's doable in a fast way it would kill two birds with one stone, for sure.https://github.com/atilaneves/DIPs/blob/safe-by-default/safe-by-default.md Destroy!I agree completely that "having [ safe] be opt-in makes it hard to use in practice" and that "defaults matter". However, I think that implementing [Universal Function Attribute Inference][1] would be a better way to address the shortcomings of the current defaults.In ["Thoughts on Backward Compatibility"][2], I tried to figure out why some breaking changes succeed and others fail. The conclusion I came to was that breaking changes are most successful when: 1. Migration is easy, or 2. The change serves a goal that has strong buy-in from users While there is a vocal minority in the D community who strongly support safe (a group in which I include myself), **I do not believe that safe has strong buy-in from D programmers as a whole.** In other words, this proposal cannot satisfy condition (2). It follows that, if we would like it to succeed, it *must* satisfy condition (1). Sadly, I do not think migration to `-preview=safedefault` will be particularly easy. By the DIP's own admission, it "will likely break a lot of code". Even if editions allow us to mix pre-migration and post-migration code in the same project, the burden of migrating to `-preview=safedefault` will likely hurt the adoption of new editions, and cause projects that would otherwise upgrade to get "stuck" in the system-by-default edition. (It is also conceivable that new projects started by D programmers who don't care about safe will choose the old, system-by-default edition specifically to avoid the hassle of adding explicit system attributes to their code.)I was going to write that I don't understand why anyone would want system-by-default until I realised that calling legacy code, including dub packages, might be a pain. Hmm.Universal inference avoids these problems. In most cases, it requires zero manual intervention to migrate existing code (that is, it Just Works™). The only major obstacle it faces is build performance when using separate compilation, and this obstacle can be overcome with toolchain improvements.I'm all for not having to write attributes the compiler can infer itself and having them "only" show up in .di files. As long as build speeds aren't affected, since it's too slow as it is for me. Do I like writing ` safe nogc pure nothrow scope const`? No, but that's what I have to do right now.
May 31
On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/safe-by-default/safe-by-default.md Destroy!Neutral. I think safe by default is of no benefit to me. However I'd support this change (as an edition) since there are easy ways out and default do matter, I've remarked if you don't write safe right from the start it's not going to happen afterwards (but this is also a testament to how relatively useless it is to be safe in the first place imo).
May 31
On 5/30/24 20:35, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/safe-by-default/safe-by-default.md Destroy!- I think even more important than the default is the ability to change the default (e.g. `default( safe):`). This does not exist currently, but it would be required for easy migration. - There is not really any value in being able to write ` safe extern(C)/extern(C++)` prototypes. It's wrong and any linter would need to have a warning for it. I would just require an explicit ` system` or ` trusted` annotation. Note that for `extern(C)/extern(C++)` prototypes, ` safe` and ` trusted` have _the same semantics and interpretation_, but only one of them looks adequately dangerous and is easy to grep. - The DIP should clarify whether annotations like ` safe:` apply to prototypes or whether prototypes always need an individual annotation. - N.B.: OpenD has been experimenting with changing the default safety level behavior to be a distinct category from the other three. (It enables checks on pointer arithmetic, but is not transitive and does not include DIP1000 checks.) It does not guarantee memory safety but can catch bugs.
Jun 01
On Saturday, 1 June 2024 at 21:06:05 UTC, Timon Gehr wrote:On 5/30/24 20:35, Atila Neves wrote:That's a good point, but: do we only do it for this attribute or for the others as well?https://github.com/atilaneves/DIPs/blob/safe-by-default/safe-by-default.md Destroy!- I think even more important than the default is the ability to change the default (e.g. `default( safe):`). This does not exist currently, but it would be required for easy migration.- There is not really any value in being able to write ` safe extern(C)/extern(C++)` prototypes. It's wrong and any linter would need to have a warning for it. I would just require an explicit ` system` or ` trusted` annotation. Note that for `extern(C)/extern(C++)` prototypes, ` safe` and ` trusted` have _the same semantics and interpretation_, but only one of them looks adequately dangerous and is easy to grep.I get this, but the issue is that those functions might actually be written in D.- The DIP should clarify whether annotations like ` safe:` apply to prototypes or whether prototypes always need an individual annotation.Added.
Jun 03
On 6/3/24 17:55, Atila Neves wrote:Why is this an issue?- There is not really any value in being able to write ` safe extern(C)/extern(C++)` prototypes. It's wrong and any linter would need to have a warning for it. I would just require an explicit ` system` or ` trusted` annotation. Note that for `extern(C)/extern(C++)` prototypes, ` safe` and ` trusted` have _the same semantics and interpretation_, but only one of them looks adequately dangerous and is easy to grep.I get this, but the issue is that those functions might actually be written in D.
Jun 06
On Thursday, 6 June 2024 at 17:01:05 UTC, Timon Gehr wrote:On 6/3/24 17:55, Atila Neves wrote:The compiler would have access to the body and so would verify its safe-ness.Why is this an issue?- There is not really any value in being able to write ` safe extern(C)/extern(C++)` prototypes. It's wrong and any linter would need to have a warning for it. I would just require an explicit ` system` or ` trusted` annotation. Note that for `extern(C)/extern(C++)` prototypes, ` safe` and ` trusted` have _the same semantics and interpretation_, but only one of them looks adequately dangerous and is easy to grep.I get this, but the issue is that those functions might actually be written in D.
Jun 06
On 6/7/24 02:58, Atila Neves wrote:On Thursday, 6 June 2024 at 17:01:05 UTC, Timon Gehr wrote:A function prototype does not have a body and the actual body may be in another compilation unit. For `extern(D)` the mangled name gives some assurances, but not for `extern(C)` and `extern(C++)`. I guess maybe an additional alternative name can be given to ` safe` `extern(C)` functions, but I doubt that linker errors are a great UX for safety checks.On 6/3/24 17:55, Atila Neves wrote:The compiler would have access to the body and so would verify its safe-ness.Why is this an issue?- There is not really any value in being able to write ` safe extern(C)/extern(C++)` prototypes. It's wrong and any linter would need to have a warning for it. I would just require an explicit ` system` or ` trusted` annotation. Note that for `extern(C)/extern(C++)` prototypes, ` safe` and ` trusted` have _the same semantics and interpretation_, but only one of them looks adequately dangerous and is easy to grep.I get this, but the issue is that those functions might actually be written in D.
Jun 07
Timon Gehr kirjoitti 7.6.2024 klo 17.25:On 6/7/24 02:58, Atila Neves wrote:When Átila wrote his last reply I was still agreeing with him. Why? I missed that you, in your earlier post, wrote specifically about function prototypes, not any C/C++ linked functions. I guess Átila did too - I can't see why else he would have thought the compiler has access to the function body. If I'm assessing this right, you're actually in agreement with each other. The only disagreement you maybe have is whether it's this DIP or some later alternative that should change the rules for those functions.On Thursday, 6 June 2024 at 17:01:05 UTC, Timon Gehr wrote:A function prototype does not have a body and the actual body may be in another compilation unit. For `extern(D)` the mangled name gives some assurances, but not for `extern(C)` and `extern(C++)`. I guess maybe an additional alternative name can be given to ` safe` `extern(C)` functions, but I doubt that linker errors are a great UX for safety checks.On 6/3/24 17:55, Atila Neves wrote:The compiler would have access to the body and so would verify its safe-ness.Why is this an issue?- There is not really any value in being able to write ` safe extern(C)/extern(C++)` prototypes. It's wrong and any linter would need to have a warning for it. I would just require an explicit ` system` or ` trusted` annotation. Note that for `extern(C)/extern(C++)` prototypes, ` safe` and ` trusted` have _the same semantics and interpretation_, but only one of them looks adequately dangerous and is easy to grep.I get this, but the issue is that those functions might actually be written in D.
Jun 07
On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/safe-by-default/safe-by-default.md Destroy!Because of a lack of mangling, `extern(X)` where `X` isn’t `D` shouldn’t ever be allowed to be annotated ` safe` unless it’s a definition. The right way: ```d module a; extern(C) int f(int) trusted; extern(C) int f(int) safe; // compile error: `extern(C)` function cannot be verified ` safe`. Hint: If the implementation is written in D in another module, use ` trusted`. ``` ```d module b; extern(C) int f(int x) safe => x; // okay: implementation present ``` In this case, unfortunately, ` trusted` can mean two things: * The implementation is ` system`, but the developer verified it is fool-proof to use UB-free. * The developer verified the implementation is annotated ` safe`. In this case, a comment can be added to indicate this case.
Jun 03
On Monday, 3 June 2024 at 11:08:36 UTC, Quirin Schroll wrote:On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:I could see changing it to this; but what if it's writen in D and someone wants to use a .di file?[...]Because of a lack of mangling, `extern(X)` where `X` isn’t `D` shouldn’t ever be allowed to be annotated ` safe` unless it’s a definition. [...]
Jun 03
On Monday, 3 June 2024 at 15:56:05 UTC, Atila Neves wrote:On Monday, 3 June 2024 at 11:08:36 UTC, Quirin Schroll wrote:TBH, I don’t know what .di files really are. AFAIK, they’re basically what a header file in C/C++ is. They contain declarations. The biggest difference to C/C++ is that .di files are compiler generated and a programmer might occasionally read them, but essentially never write or edit one. Correct me if I’m wrong. For `extern(C/C++)` functions implemented in D, whether the .di file contains contains ` safe` or ` trusted` declarations doesn’t really make a difference. For callers, they’re the same. They also mangle the same. There may be a difference what reflection sees, though. I notice one issue, that ` trusted` is not the same as ` safe` from the caller perspective. In `extern(D)`, they also mangle differently, which is fine but weird. I noticed that this does not compile: ```d extern(C) void f() trusted; extern(C) void f() safe { } void main() { f(); } // error: `f` ambiguous ``` This could be an issue for the D module that defines the function, maybe it isn’t. If it is, I guess that could be changed, i.e. for `extern(C/C++)` make the compiler realize that function declarations only differing in attributes refer to the same function. I cannot imagine someone relies on this being an error.On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:I could see changing it to this; but what if it's writen in D and someone wants to use a .di file?[...]Because of a lack of mangling, `extern(X)` where `X` isn’t `D` shouldn’t ever be allowed to be annotated ` safe` unless it’s a definition. [...]
Jun 04
On 05/06/2024 12:13 AM, Quirin Schroll wrote:On Monday, 3 June 2024 at 15:56:05 UTC, Atila Neves wrote:.di files are currently all hand written. The only thing special about them is the convention that they should have methods discarded and that they get priority over .d files. In all other ways the are the same as .d files. The .di generator currently runs _before_ semantic, this means no inferred attributes get emitted. If you move it to after semantic (assuming no other issues lol) scope and return will be emitted in the wrong order messing up mangling. Basically right now the .di generator can't be used. I am working on fixing most of the blocking issues, but unfortunately I am going to hand it off due to some semantic rewrites that I cannot fix. A quick look on ABI page, both `` safe`` and `` trusted`` get name mangled differently. https://dlang.org/spec/abi.html#FuncAttrTrusted So yes we'd have to allow `` safe`` on function declarations without bodies unfortunately.On Monday, 3 June 2024 at 11:08:36 UTC, Quirin Schroll wrote:TBH, I don’t know what .di files really are. AFAIK, they’re basically what a header file in C/C++ is. They contain declarations. The biggest difference to C/C++ is that .di files are compiler generated and a programmer might occasionally read them, but essentially never write or edit one. Correct me if I’m wrong.On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:I could see changing it to this; but what if it's writen in D and someone wants to use a .di file?[...]Because of a lack of mangling, `extern(X)` where `X` isn’t `D` shouldn’t ever be allowed to be annotated ` safe` unless it’s a definition. [...]
Jun 04
On Tuesday, 4 June 2024 at 20:33:07 UTC, Richard (Rikki) Andrew Cattermole wrote:On 05/06/2024 12:13 AM, Quirin Schroll wrote:I’m not referring to `extern(D)` functions. I knew those have attributes mangled into them, so you’ll get linker errors on an attribute mismatch between a function’s prototype and its definition. The issue is, for `extern(C/C++)` functions, attributes aren’t mangled into it, so the linker is blind to the mismatch. Of course, linker errors aren’t great, but still a lot better than UB at runtime. If .di files are hand-written, we must absolutely not allow ` safe` annotations on `extern(C/C++)` function declarations. Those must all be ` trusted`, even if the validation by the programmer only requires grepping the function name and observing that the function definition (the implementation) is annotated ` safe`, so the actual, difficult validation is done by the compiler. However, ` trusted` is warranted, as when the implementation isn’t annotated ` safe` (either because it’s not annotated or is in another language entirely), it simply may not be safe, and therefore, a ` safe` function declaration in a .di file would be a lie, and the bad thing about that is that it’s not going to be caught by the compiler or linker. The ` trusted` attribute only means that *some* programmer-side verification established the function is actually safe. It does not mean the verification can’t be as simple as a grep. In fact, if .di files are hand written, changing ` safe` to ` trusted` after copying a function signature isn’t too wild to ask. The simple fact is, on non-D functions, ` safe` can’t be verified except on function definitions, and therefore can’t be used. Átila: Making exceptions to ` safe` so that it isn’t fool-proof would be a disaster to D’s marketability.On Monday, 3 June 2024 at 15:56:05 UTC, Atila Neves wrote:.di files are currently all hand written. […] A quick look on ABI page, both `` safe`` and `` trusted`` get name mangled differently. https://dlang.org/spec/abi.html#FuncAttrTrusted So yes we'd have to allow `` safe`` on function declarations without bodies unfortunately.On Monday, 3 June 2024 at 11:08:36 UTC, Quirin Schroll wrote:TBH, I don’t know what .di files really are. AFAIK, they’re basically what a header file in C/C++ is. They contain declarations. The biggest difference to C/C++ is that .di files are compiler generated and a programmer might occasionally read them, but essentially never write or edit one. Correct me if I’m wrong.On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:I could see changing it to this; but what if it's writen in D and someone wants to use a .di file?[...]Because of a lack of mangling, `extern(X)` where `X` isn’t `D` shouldn’t ever be allowed to be annotated ` safe` unless it’s a definition. [...]
Jun 10
On Monday, 10 June 2024 at 15:12:28 UTC, Quirin Schroll wrote:On Tuesday, 4 June 2024 at 20:33:07 UTC, Richard (Rikki) Andrew Cattermole wrote:Addendum to:On 05/06/2024 12:13 AM, Quirin Schroll wrote:On Monday, 3 June 2024 at 15:56:05 UTC, Atila Neves wrote:.di files are currently all hand written. […] A quick look on ABI page, both `` safe`` and `` trusted`` get name mangled differently. https://dlang.org/spec/abi.html#FuncAttrTrusted So yes we'd have to allow `` safe`` on function declarations without bodies unfortunately.On Monday, 3 June 2024 at 11:08:36 UTC, Quirin Schroll wrote:TBH, I don’t know what .di files really are. AFAIK, they’re basically what a header file in C/C++ is. They contain declarations. The biggest difference to C/C++ is that .di files are compiler generated and a programmer might occasionally read them, but essentially never write or edit one. Correct me if I’m wrong.On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:I could see changing it to this; but what if it's writen in D and someone wants to use a .di file?[...]Because of a lack of mangling, `extern(X)` where `X` isn’t `D` shouldn’t ever be allowed to be annotated ` safe` unless it’s a definition. [...]If .di files are hand-written, we must absolutely not allow ` safe` annotations on `extern(C/C++)` function declarations. Those must all be ` trusted`, even if the validation by the programmer only requires grepping the function name and observing that the function definition (the implementation) is annotated ` safe`, so the actual, difficult validation is done by the compiler.Missing bits: This affects all attributes, not just ` safe`. The compiler might be able to do the grepping. By that I mean not actual grepping, it must be fool-proof, i.e. use the D parser and make sure the symbols are really the same. Other than that, I see no way to allow non-D prototypes be annotated ` safe`.
Jun 10
On Thursday, 30 May 2024 at 18:35:36 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/safe-by-default/safe-by-default.md Destroy!I think it should eventually happen, but we are not ready for it. The real problem is that it is currently hard to compose with attributes. The problem is most evident with ` safe`, but happens with `nothrow`, `pure`, etc... Until we solve this problem, ` safe`-by-default would just be trading one pain for another, and breaking the ecosystem in the process. We saw what happened with DIP1000... Provided the issue with composition of attribute is fixed, I would make a suggestion to the DIP: Remove ` safe` entirely. Others have hinted at it, and it seems the solution is simple: Un-annotated definitions are ` safe`, definitions can be annotated to be ` system` or ` trusted`, and `extern` definitions MUST be annotated. It is also changing the perception - ` safe` is not an add-on anymore.
Jun 06