digitalmars.D - safe D requires which DIP switches?
- Bastiaan Veelo (7/7) Jan 03 2022 As far as I know `@safe` is only really safe with both DIP25 and
- 12345swordy (3/10) Jan 03 2022 Bugs, and lots of them.
- Bastiaan Veelo (8/21) Jan 03 2022 But are these bugs in the rigidity of the checks, or do other
- Paul Backus (6/22) Jan 03 2022 The problem is usually that the checks are too loose--they allow
- Dennis (36/40) Jan 04 2022 This is the situation on dmd's master branch:
- Bastiaan Veelo (3/38) Jan 04 2022 This is really helpful, thanks!
- Atila Neves (3/15) Jan 05 2022 I talked to Walter about this and I don't think it's the correct
- Dennis (15/17) Jan 05 2022 Why not? Given a signature like:
- Atila Neves (6/23) Jan 07 2022 You *can*, but it's likely that the vast majority of code
- bauss (7/9) Jan 07 2022 It would be a somewhat correct approach, because while in theory
- Dennis (9/12) Jan 07 2022 Printing the stack trace of an Exception can only happen when you
- Elronnd (5/11) Jan 08 2022 Exceptions can be modeled as return values. This is a strictly
- Nick Treleaven (4/8) Jan 08 2022 They can 'return' to a higher scope than the caller of the
- Nick Treleaven (4/5) Jan 08 2022 To be clear, I was talking about inferred scope parameters that
- Dennis (10/16) Jan 07 2022 I don't see a first option in your first paragraph. "it's likely
- Dukc (10/21) Jan 07 2022 There is one problem with this. The string could still be
- Dennis (7/9) Jan 08 2022 Yikes, that's another annoying oversight. I hope we don't have to
- ag0aep6g (7/9) Jan 03 2022 Conceptually, DIP 1000 does not make your existing @safe code any
- Atila Neves (4/11) Jan 04 2022 @safe is really safe - what DIPs 25 and 1000 do is make it so
- Bastiaan Veelo (4/7) Jan 04 2022 Great!
As far as I know ` safe` is only really safe with both DIP25 and DIP1000 in effect, and I thought that DIP25 has been integrated for a while now. Nonetheless, DIP25 still appears in the list of previews (`dmd -preview=help`) *as well as* being revertible (`dmd -revert=help`) which adds to the confusion. What is in the way of integrating DIP1000 by default? -- Bastiaan.
Jan 03 2022
On Monday, 3 January 2022 at 14:27:55 UTC, Bastiaan Veelo wrote:As far as I know ` safe` is only really safe with both DIP25 and DIP1000 in effect, and I thought that DIP25 has been integrated for a while now. Nonetheless, DIP25 still appears in the list of previews (`dmd -preview=help`) *as well as* being revertible (`dmd -revert=help`) which adds to the confusion. What is in the way of integrating DIP1000 by default? -- Bastiaan.Bugs, and lots of them. - Alex
Jan 03 2022
On Monday, 3 January 2022 at 15:19:22 UTC, 12345swordy wrote:On Monday, 3 January 2022 at 14:27:55 UTC, Bastiaan Veelo wrote:But are these bugs in the rigidity of the checks, or do other problems arise when DIP1000 is enabled? If it is just the former, there is little reason to not switch it on by default? Does it produce false negatives (requiring ` trusted` where unnecessary)? And does `-preview=dip25` make a difference or not? Still confused. --Bastiaan.As far as I know ` safe` is only really safe with both DIP25 and DIP1000 in effect, and I thought that DIP25 has been integrated for a while now. Nonetheless, DIP25 still appears in the list of previews (`dmd -preview=help`) *as well as* being revertible (`dmd -revert=help`) which adds to the confusion. What is in the way of integrating DIP1000 by default? -- Bastiaan.Bugs, and lots of them. - Alex
Jan 03 2022
On Monday, 3 January 2022 at 16:06:38 UTC, Bastiaan Veelo wrote:On Monday, 3 January 2022 at 15:19:22 UTC, 12345swordy wrote:The problem is usually that the checks are too loose--they allow undefined behavior in ` safe` code when `-preview=dip1000` is enabled. You can browse the list yourself here: https://issues.dlang.org/buglist.cgi?quicksearch=dip1000On Monday, 3 January 2022 at 14:27:55 UTC, Bastiaan Veelo wrote:But are these bugs in the rigidity of the checks, or do other problems arise when DIP1000 is enabled? If it is just the former, there is little reason to not switch it on by default? Does it produce false negatives (requiring ` trusted` where unnecessary)?What is in the way of integrating DIP1000 by default? -- Bastiaan.Bugs, and lots of them. - Alex
Jan 03 2022
On Monday, 3 January 2022 at 16:06:38 UTC, Bastiaan Veelo wrote:But are these bugs in the rigidity of the checks, or do other problems arise when DIP1000 is enabled?This is the situation on dmd's master branch: ✅ = correct, considering the current language design 🆗 = correct, but is more strict than necessary 💀 = incorrect, allows memory corruption | Action | no dip1000 | dip1000 | |--------------------------------|------------|----------------------------------------------------| | Take address of local variable | 🆗 Error | ✅ Allowed using `scope` when type has no pointers | | Make slice of local variable | 💀 Allowed | ✅ Allowed using `scope` when type has no pointers | | Take address of `ref` return | 💀 Allowed | 🆗 Allowed using `scope` when type has no pointers | | Make slice of `ref` return | 💀 Allowed | 💀 Allowed even when type has pointers | I'm trying to turn dip1000's 💀 into an 🆗, but Walter wants to go straight to a ✅: https://github.com/dlang/dmd/pull/13362#issuecomment-981181277 On top of this, dip1000 currently has a few more 💀s because: - parameters of `pure` functions can be incorrectly inferred `scope`, even when you can escape them with a thrown Exception. The fix is easy, but it requires updating Phobos and excel-d to pass the test suite, which is cumbersome. https://issues.dlang.org/show_bug.cgi?id=22221 - `inout` on struct member functions currently gives the permissions of `return` without the associated lifetime restrictions. https://issues.dlang.org/show_bug.cgi?id=20149 - Some checks are missing when using closures: https://issues.dlang.org/show_bug.cgi?id=22298And does `-preview=dip25` make a difference or not? Still confused.dip25 prevents returning a `ref` parameter by `ref`, unless you annotate it `return ref`. It's enabled by default, but only as a deprecation. `-preview=dip25` turns the deprecation into an error. `-preview=dip1000` implies `-preview=dip25`, so there's no need to use both switches.
Jan 04 2022
On Tuesday, 4 January 2022 at 11:57:41 UTC, Dennis wrote:This is the situation on dmd's master branch: ✅ = correct, considering the current language design 🆗 = correct, but is more strict than necessary 💀 = incorrect, allows memory corruption | Action | no dip1000 | dip1000 | |--------------------------------|------------|----------------------------------------------------| | Take address of local variable | 🆗 Error | ✅ Allowed using `scope` when type has no pointers | | Make slice of local variable | 💀 Allowed | ✅ Allowed using `scope` when type has no pointers | | Take address of `ref` return | 💀 Allowed | 🆗 Allowed using `scope` when type has no pointers | | Make slice of `ref` return | 💀 Allowed | 💀 Allowed even when type has pointers | I'm trying to turn dip1000's 💀 into an 🆗, but Walter wants to go straight to a ✅: https://github.com/dlang/dmd/pull/13362#issuecomment-981181277 On top of this, dip1000 currently has a few more 💀s because: - parameters of `pure` functions can be incorrectly inferred `scope`, even when you can escape them with a thrown Exception. The fix is easy, but it requires updating Phobos and excel-d to pass the test suite, which is cumbersome. https://issues.dlang.org/show_bug.cgi?id=22221 - `inout` on struct member functions currently gives the permissions of `return` without the associated lifetime restrictions. https://issues.dlang.org/show_bug.cgi?id=20149 - Some checks are missing when using closures: https://issues.dlang.org/show_bug.cgi?id=22298dip25 prevents returning a `ref` parameter by `ref`, unless you annotate it `return ref`. It's enabled by default, but only as a deprecation. `-preview=dip25` turns the deprecation into an error. `-preview=dip1000` implies `-preview=dip25`, so there's no need to use both switches.This is really helpful, thanks! -- Bastiaan.
Jan 04 2022
On Tuesday, 4 January 2022 at 11:57:41 UTC, Dennis wrote:On Monday, 3 January 2022 at 16:06:38 UTC, Bastiaan Veelo wrote:I talked to Walter about this and I don't think it's the correct fix. I've been looking at how to do it otherwise.But are these bugs in the rigidity of the checks, or do other problems arise when DIP1000 is enabled?I'm trying to turn dip1000's 💀 into an 🆗, but Walter wants to go straight to a ✅: https://github.com/dlang/dmd/pull/13362#issuecomment-981181277 On top of this, dip1000 currently has a few more 💀s because: - parameters of `pure` functions can be incorrectly inferred `scope`, even when you can escape them with a thrown Exception. The fix is easy, but it requires updating Phobos and excel-d to pass the test suite, which is cumbersome. https://issues.dlang.org/show_bug.cgi?id=22221
Jan 05 2022
On Wednesday, 5 January 2022 at 10:05:02 UTC, Atila Neves wrote:I talked to Walter about this and I don't think it's the correct fix. I've been looking at how to do it otherwise.Why not? Given a signature like: ```D int fun(string s) pure nothrow; ``` You can assume `s` is `scope`, because there's no channel to escape it: return value has no pointers, global variables are not accessible in a pure function, there are no other parameters to assign it to. But when the signature is this: ```D int fun(string s) pure; ``` You can assign `s` to an Exception that gets thrown. How would you prevent / detect that?
Jan 05 2022
On Wednesday, 5 January 2022 at 10:47:50 UTC, Dennis wrote:On Wednesday, 5 January 2022 at 10:05:02 UTC, Atila Neves wrote:You *can*, but it's likely that the vast majority of code *won't*. Changing this would break a lot of code, as seen by your attempts to fix Phobos. Another option is making it so pure functions can't throw, but that also probably introduces a lot of breakage.I talked to Walter about this and I don't think it's the correct fix. I've been looking at how to do it otherwise.Why not? Given a signature like: ```D int fun(string s) pure nothrow; ``` You can assume `s` is `scope`, because there's no channel to escape it: return value has no pointers, global variables are not accessible in a pure function, there are no other parameters to assign it to. But when the signature is this: ```D int fun(string s) pure; ``` You can assign `s` to an Exception that gets thrown. How would you prevent / detect that?
Jan 07 2022
On Friday, 7 January 2022 at 08:39:25 UTC, Atila Neves wrote:Another option is making it so pure functions can't throw, but that also probably introduces a lot of breakage.It would be a somewhat correct approach, because while in theory you can throw from pure functions, then you violate the purity by observing the thrown exception. So it doesn't really make much sense to throw in a pure function in itself, as using the exception will be a direct violation of purity.
Jan 07 2022
On Friday, 7 January 2022 at 08:46:27 UTC, bauss wrote:So it doesn't really make much sense to throw in a pure function in itself, as using the exception will be a direct violation of purity.Printing the stack trace of an Exception can only happen when you catch it in an impure function. In that case the side effects happen there, that doesn't make the function that threw the Exception impure. Catching the Exception in a `pure` function is not a violation either, whatever you do with the Exception object in the catch block is the same as what you could do if the Exception was returned instead of thrown.
Jan 07 2022
On Friday, 7 January 2022 at 08:46:27 UTC, bauss wrote:It would be a somewhat correct approach, because while in theory you can throw from pure functions, then you violate the purity by observing the thrown exception. So it doesn't really make much sense to throw in a pure function in itself, as using the exception will be a direct violation of purity.Exceptions can be modeled as return values. This is a strictly local rewrite. So it is no more a violation of purity than is writing to memory pointed to by passed-in pointers (and arguably less).
Jan 08 2022
On Saturday, 8 January 2022 at 13:33:26 UTC, Elronnd wrote:Exceptions can be modeled as return values. This is a strictly local rewrite. So it is no more a violation of purity than is writing to memory pointed to by passed-in pointers (and arguably less).They can 'return' to a higher scope than the caller of the function. Any stack memory from the caller's frame will be corrupted. safe cannot allow this.
Jan 08 2022
On Saturday, 8 January 2022 at 18:19:47 UTC, Nick Treleaven wrote:safe cannot allow this.To be clear, I was talking about inferred scope parameters that actually escape via a throwable, not about throwing from pure functions.
Jan 08 2022
On Friday, 7 January 2022 at 08:39:25 UTC, Atila Neves wrote:You *can*, but it's likely that the vast majority of code *won't*. Changing this would break a lot of code, as seen by your attempts to fix Phobos. Another option ...I don't see a first option in your first paragraph. "it's likely that the vast majority of code *won't*", sure, but scope inference needs to be 100%, 'likely `scope`' is not useful information for DMD.Another option is making it so pure functions can't throw, but that also probably introduces a lot of breakage.`pure` `nothrow` functions don't break, it's only `pure` functions that throw exceptions that lose their free `scope` inference. Disallowing `pure` `throw` functions entirely results in a strict superset of the breakage, on top of adding an arbitrary restriction to users.
Jan 07 2022
On Wednesday, 5 January 2022 at 10:47:50 UTC, Dennis wrote:On Wednesday, 5 January 2022 at 10:05:02 UTC, Atila Neves wrote:There is one problem with this. The string could still be assigned to a non-`Exception` `Throwable` and thrown. If the function implementation is also ` safe`, the compiler is going to wrongly prevent throwing the exception due to the automatically added `scope`. When you think of it, it means that `assert`s using `s` as the message would be forbidden. Or worse, they would be allowed but the assert failure printer would then try to access expired memory after such an assert has gone boom.I talked to Walter about this and I don't think it's the correct fix. I've been looking at how to do it otherwise.Why not? Given a signature like: ```D int fun(string s) pure nothrow; ``` You can assume `s` is `scope`, because there's no channel to escape it: return value has no pointers, global variables are not accessible in a pure function, there are no other parameters to assign it to.
Jan 07 2022
On Saturday, 8 January 2022 at 00:13:38 UTC, Dukc wrote:There is one problem with this. The string could still be assigned to a non-`Exception` `Throwable` and thrown.Yikes, that's another annoying oversight. I hope we don't have to do away with `pure` based `scope` inference entirely. Since Errors are only thrown once per program, it could be okay to make the assert handler's message string `scope` forcing it to copy it when it wants to back trace, but when throwing a custom `Throwable` class this is harder to enforce.
Jan 08 2022
On Monday, 3 January 2022 at 14:27:55 UTC, Bastiaan Veelo wrote:As far as I know ` safe` is only really safe with both DIP25 and DIP1000 in effectConceptually, DIP 1000 does not make your existing safe code any safer. It allows some code to be safe that had to be system before. If you just want to write safe code, and you don't care for `scope`, you can ignore DIP 1000. Any safety holes are just bugs, with and without `-preview=dip1000`.
Jan 03 2022
On Monday, 3 January 2022 at 14:27:55 UTC, Bastiaan Veelo wrote:As far as I know ` safe` is only really safe with both DIP25 and DIP1000 in effect, and I thought that DIP25 has been integrated for a while now. Nonetheless, DIP25 still appears in the list of previews (`dmd -preview=help`) *as well as* being revertible (`dmd -revert=help`) which adds to the confusion. What is in the way of integrating DIP1000 by default? -- Bastiaan.safe is really safe - what DIPs 25 and 1000 do is make it so more code can be safe. I'm currently working on making DIP1000 the default.
Jan 04 2022
On Tuesday, 4 January 2022 at 08:58:04 UTC, Atila Neves wrote:safe is really safe - what DIPs 25 and 1000 do is make it so more code can be safe.Thanks, that clears things up considerably.I'm currently working on making DIP1000 the default.Great! -- Bastiaan.
Jan 04 2022