Jonathan M Davis
Posted in reply to Walter Bright
| On Monday, August 26, 2024 12:20:18 AM MDT Walter Bright via Digitalmars-d wrote:
> On 8/25/2024 6:28 PM, Jonathan M Davis wrote:
> > I'm
> > perfectly fine with manually verifying the rare case where I need to take
> > the address of a local variable or slice a static array, and I do _not_
> > want to deal with figuring out where and how I need to slap scope
> > everywhere to make the compiler happy - especially when it's then going
> > to start complaining about stuff that worked perfectly fine and was quite
> > memory safe prior to scope getting involved.
>
> If you never take the address of a local, or a ref to a local, dip1000 is not going to complain about your code!
Sure, but in the cases where I do take the address of a local, I don't want to deal with the compiler inferring anything as scope. Then I'd have to start worrying about whether the functions that I pass the pointer to are scope, and if I mark up any code as scope to make the compiler happy, that quickly becomes viral, whereas right now, I can just take the address of a local and happily pass it around without any complaints. I just have to mark the function as @trusted, and if the code is complex enough that it's not easy to see whether a pointer is escaping, then I'm just not going to do something like take the address of a local.
Where it comes up more frequently for me though is static arrays. There are plenty of cases where it makes sense to create a static array to avoid allocations and slice it to actually operate on the data when there is no need to return any such slice, so it's easy to avoid any escaping. But using DIP 1000 means that scope has to be used all over the place. Part of the reason that I gave up on doing anything with DIP 1000 and dxml is because some of the tests use static arrays and slice them, and if DIP 1000 is enabled, then scope is needed all over the place. It's not helping. It just makes it so that I have to mark up a bunch of code with scope to make the compiler happy.
I don't want to have to mark up code with scope just to handle the case where someone might decide to do something like pass in the slice of a static array with code where it's obvious whether anything is escaping. It quickly becomes viral, and I'm not at all convinced that it's actually making things safer given that if the code is complex enough that you need the compiler to tell you that stuff isn't escaping, then the compiler is probably going to fail at figuring it out somewhere in the process anyway, forcing you to cast away scope. At that point, it's better to just not do something like take the address of a local or slice a static array.
And while to an extent, you can just avoid using scope, because DIP 1000 infers scope in various places, you sometimes end up with it whether you like it or not. So, if DIP 1000 ever becomes the default, it's going to affect folks who do not want the help.
I fully expect that if DIP 1000 becomes the default, I will either be casting away scope whenever it gets inferred, or if that's enough of a pain, with my own code, I'll just give up on @safe entirely and mark everything as @system. I very much like the idea of @safe catching cases where I accidentally do something @system, but I don't want to have to mark up my code all over the place just so that the compiler can make a bit more code @safe without @trusted. The ROI isn't even vaguely there IMHO - especially with a language that already makes it possible to make the vast majority of code @safe thanks to the GC. Right now, the issue of taking the address of locals is quite isolated, because it really only affects code around the place where you take the address (at the cost of some basic thinking to make sure that you're not doing something stupid with the pointer), whereas with DIP 1000, we're going to have cases where scope gets used all over the place just in case the pointer or array that's passed in has the address of a local variable. Instead of it being just the caller's problem, it becomes a problem for every function that's being called with that pointer or slice.
And the situation is going to be particularly bad for library writers, since then even if you don't want to bother with scope, it's going to cause problems for users of your library who do want to use scope if you don't go to the extra effort of using it anywhere and everywhere that might need it for the calling code to be able to pass in something that's scope. And the fact that scope gets inferred is likely to cause problems in templated code in particular, because then anyone who uses scope in their code and passes it to your library that doesn't use scope will get it inferred in some places (and potentially in a _lot_ of places if member functions are marked with scope), causing compilation errors. It seems to me that scope risks becoming an utter nightmare with ranges in particular if anyone decides that they want to mark any functions on their ranges with scope given how common it is for range-based code to wrap ranges with other ranges using templated code.
For my own libraries, I'll probably just say tough luck and say that folks will have to cast away scope or simply not use it if they want to use my libraries, whereas if I have to deal with it for Phobos, that will significantly reduce my interest in doing work for Phobos that I don't feel that I really need to do, because it's just going to be too much of a pain to deal with.
>From where I sit, DIP 1000 is an extremely viral feature that provides
minimal benefit. If anything, I'd like to see fewer attributes in D, not more, and while scope does technically already exist, its use is quite limited without DIP 1000, whereas with DIP 1000, there's a real risk that it's going to have to be used all over the place - particularly in library code.
- Jonathan M Davis
|