digitalmars.D.announce - D Language Foundation April 2024 Monthly Meeting Summary
- Mike Parker (614/614) Jul 30 The D Language Foundation's monthly meeting for April 2024 was
- jmh530 (2/5) Jul 30 Thanks for the detailed write-up!
- Abdulhaq (2/4) Jul 30 very interesting thanks
- An Pham (4/9) Jul 30 Suggest to add setting to sc.ini for default edition (only affect
- Dukc (52/105) Jul 31 Unfortunately, this is likely only the tip of an iceberg. I don't think
- Dennis (16/33) Jul 31 There's nothing wrong with that, it's even the current situation.
- Jonathan M Davis (32/44) Jul 31 DIP 1000 is attempting to make more stuff @safe than it is now -
- Dukc (10/17) Jul 31 We also need to disable taking a pointer of a struct field, if that
- Jonathan M Davis (18/35) Jul 31 Not really, since with DIP 1000, the compiler infers scope in some cases...
- Sebastiaan Koppe (19/30) Jul 31 Unfortunately that leads to certain patterns that are safe using
- Anonymouse (2/3) Jul 31 Thanks!
The D Language Foundation's monthly meeting for April 2024 was held on Friday the 12th. It lasted an hour and 20 minutes. The following people attended: * Paul Backus * Walter Bright * Jonathan M. Davis * Timon Gehr * Dennis Korpel * Átila Neves * Mike Parker * Robert Schadek Jonathan said Adam Wilson had set up [the Phobos v3 repository](https://github.com/LightBender/phobos) to use dub. That wasn't a big deal since we weren't distributing it yet, but we hadn't yet agreed on how it would be built for distribution. Although there wasn't a lot of code there yet, it would be nice if the CI could run the tests on what was there so that we could catch breakage. He'd tried to add the dub test stuff to the normal makefile targets to get it to run as part of the CI. It worked locally on his machine, but most of the test runners didn't have dub, so it didn't work in the repo. BuildKite did have dub, but it was failing there, too. He said that either the test runners needed to be updated to work with dub, and he didn't know how to do that, or the Phobos v3 build needed to be altered so it wasn't using dub. Dennis said he had set up a `dub.sdl` to build DMD with dub and the CI had failed there, too. His solution was to make his own workflow, [a separate YAML file for GitHub Actions](https://github.com/dlang/dmd/blob/master/.github/workflows build_with_dub.yml) which used the standard D community setup that installed everything, including dub. He said he also didn't know the details of all the CI workflows or how to integrate this neatly, so he was just kind of improvising. Jonathan said he'd tried to add the dub test stuff just to get it in there and building without mucking with all the makefile stuff. He expected that long term we wouldn't want to be using dub here, but he didn't know. He'd just wanted to get it working with minimal effort without spending time on building stuff he wasn't familiar with. Dennis suggested it might be possible to just use `dmd -i -run` with a module that imported all the Phobos modules. That would probably work since it was just a collection of source files. Jonathan said he would have to dig into that and figure it out. Walter said that [the ownership/borrowing system](https://dlang.org/blog/2019/07/15/ownership-and-borrowing-in-d/), ` live`, was about two-thirds implemented. It had sat around for years with little or zero interest. He'd set it aside because of all the DIP 1000 bugs. DIP 1000 was required for it to work. However, something had changed in the industry. The government had said that programs should be written in memory-safe languages. This was causing a shift away from C++ toward Rust. We didn't have a story there. We couldn't really say we were memory-safe, although we were 90 or 95% there with DIP 1000. We had a preview switch that turned on the ` live` checks, but he felt that was preventing people from using it. It had taken him a while to figure out which switch it was, and as he was talking about it here he couldn't remember the name. Dennis said it was `-preview=dip1021`. Walter said that was it, and the issue was that DIP 1021 was a different DIP that wasn't about ` live`, but it was the switch that enabled it. He said that ` live` didn't change any semantics. It only added an extra layer of checks on functions tagged with ` live`. So right now you could mark functions with ` live` all you wanted and nothing would happen until you turned the switch on. He felt the switch was a pointless barrier and should be made the default. Historically, there had only been 15 or so bugs for ` live` and all but one had been fixed. In fixing a couple of them recently, he'd discovered a couple more gaps in what the ownership and borrowing system did. He was working on fixing them. He proposed that we turn on ` live` by default so people might be more inclined to try it and file bug reports on it. In the long run, the point was that we needed D to be a memory-safe programming language. That was the most important thing. He noted that there had been repeated requests to do null tracking. There had been constant complaints about class references being default initialized to null, then someone would try to call a member function and get a segfault. Walter still believed that wasn't actually a problem, but the ` live` code could be enhanced to do null tracking. If it were on by default, then he'd be willing to make the enhancement. He'd implement it such that it would only trip if it were sure that a null reference was being made, and wouldn't trip in ambiguous cases. He thought this was the last step to being able to say that D was a memory-safe language, and we'd be able to do it without the ugliness of Rust. He thought Rust was ugly to look at and that memory-safe code didn't need to be ugly. Timon said that maybe we could enable it, but his issue was that ` live` by itself didn't improve memory safety. Walter said he knew that was Timon's position, but he didn't understand it. He said that the cases it was supposed to work on, it *did* work on. No matter how convoluted your code, it correctly detected if you'd borrowed something or not and would give you errors if you didn't dispose of it before the end of the function. It did what it was supposed to do. As Walter recalled, Timon wanted two kinds of pointers---ownership/borrowing pointers and GC pointers. Walter had objected to that based on how disruptive it would be to how the compiler worked internally. He noted that Microsoft had created Managed C++, which had two kinds of pointers---GC pointers and non-GC pointers. Though they still maintained it, it had vanished from the conversation. He considered Managed C++ and their approach to be a failure because of it. Timon said the general issue was that ` live` wasn't properly modular. It only added some checks. It didn't ensure invariants. To improve memory safety, you needed a type system to ensure invariants that improve memory safety. He thought we did have a memory-safe language and the best way to write memory-safe code today was to disable DIP 1000 and use the garbage collector. DIP 1000 introduced additional cases of memory unsafety, so just disabling it and using the GC with ` safe` would enable memory safety. Walter said it had been brought up before that DIP 1000 didn't work. Several bugs were filed. He and Dennis had fixed a long list of them and hadn't yet found one problem with DIP 1000 that couldn't be fixed. Timon said that was a reflection of the current state. Eventually, maybe enabling DIP 1000 and using the GC when it didn't work would be the way forward. But ` live` didn't do anything in ` safe` code because ` safe` code was already memory safe. Walter said ` safe` did not guarantee memory safety. What ` live` did was let you know if you malloced a pointer and never freed it. DIP 1000 couldn't help with that. Timon said you couldn't call `malloc` in ` safe` code, so that wasn't the context. Walter said he understood that D was memory-safe if you GC'ed everything, but we couldn't GC everything and have a systems programming language. To have memory safety and be a systems programming language, you had to track where the pointers came from and where they went. You couldn't free a pointer twice. Timon said you needed to know those things, maybe, but ` live` didn't add this to ` safe`. It would do those checks, but it didn't ensure invariants. It wasn't because of bugs, but because it was a function attribute. Walter said it worked within the function. Within the function, everything was checked by the ownership/borrowing rules and it worked. If you malloced a pointer twice, it would give you an error. If you malloced a pointer and didn't free it, it would give you an error. If you malloced a pointer and freed it twice, it would give you an error. If you malloced a pointer, freed it, and then used the pointer again, it would give you an error. Timon said he agreed, but for example, C++ would give you a compiler error if you assigned an integer to a pointer. That didn't make it memory-safe. Walter said he didn't understand what was memory-unsafe about ` live`. Timon said it didn't improve safety guarantees. There was no sound checking. Walter said it guaranteed that you had to free anything you malloced. Timon said you could use aliasing in some other part of the program. Walter said the more of your code you marked as ` live`, the more checking you would get. It was up to the programmer to decide which functions were checked. He noted that even Rust didn't have memory safety everywhere. Anything marked as unsafe wasn't checked. Dennis said the premise of ` live` was that it added safety. That was just false. We already had a safe language per the spec if you ignored the implementation bugs, via ` safe` and the garbage collector, but you could do manual freeing. As the language was defined, manual freeing couldn't be annotated ` safe`. So the argument that could be made for ` live` was that it made manual freeing possible in safe code. To do that, you had to properly prove that it satisfied the constraint that you couldn't call `free` in the wrong place and corrupt memory. With the current design, that wasn't the case. There were cases in ` safe live` code where you could free a pointer allocated with a different allocator and have memory corruption that way, or in other cases where you called a non-` live` function from an ` live` function and it would do something. So with the current definition of ` safe live`, it didn't add any safety. It only added checks to catch some mismatched `malloc` and `free` pairs. It didn't add to which code was safe code. We already had ` safe` for the garbage collected/stack allocated part of D, but not for the malloc/free part. There was a whole discussion to be had about how we could do that. Walter said the malloc/free part was critical because that was part of what D was. If you couldn't do malloc/free, then...? Dennis said it didn't have to be done by ` live`. It could be done by a container library or something. Walter said it couldn't. Dennis said that we should then explore ways to do it. He said Paul was working on that now, how to use allocator interfaces to create safe data structures. Paul said that Walter had once written that C's biggest mistake was conflating arrays and pointers. When you passed an array to a function in C, the information about its length was discarded. Paul thought the fundamental issue with ` live` was a very similar mistake: if you passed a pointer from an ` live` function to a non-` live` function, then all of the information about its ownership status was discarded. That meant if you wanted a memory-safe program rather than just a single memory-safe function, then everything had to be ` live` or it wouldn't work. The consequence of that was that you'd then have to cut yourself off from the entire existing ecosystem of non-` live` code and start from scratch. Walter said he didn't understand why. You could incrementally add ownership/borrowing checks to your code where and when you wanted. If you didn't add ` live`, you didn't get the checks. He didn't understand how you could get a memory-safe language just by fiddling with the allocators. You had to solve the problem. Paul said it wasn't by fiddling with the allocators, but by having the containers do the ownership/borrowing checks. By using both `scope` (DIP 1000) and ` system` variables (DIP 1035) together, it was possible, ignoring implementation bugs, to write containers that manually allocated and freed memory and were safe because they used runtime checks to ensure that pointers could only be freed when they were not borrowed or aliased. He had written code that did this. He had a work-in-progress implementation of a unique pointer in D that used these kinds of checks. There were some UX issues with it. You had to use callbacks in places. If you wanted to prevent references from escaping, you could pass a scope reference or pointer down the stack, but if you returned one up the stack, then it was game over. It could escape and there was nothing you could do about it, so you had to use callbacks to access the contents of the container, meaning either a function that you passed a lambda to or an `opApply`. But it did work, modulo implementation bugs, and it worked using features that were already designed and partially implemented. And it worked in a way that was compatible with the entire existing ecosystem of D code, including existing ` safe` code, and did not require you to incrementally transition your entire program over to this new set of semantics to reap the benefits. Walter said that was what C++ did. If you stuck with the C++ library, your memory was safe. But that wasn't acceptable. That just hadn't worked out in the real world. Paul said that C++ had a unique pointer and a shared pointer, but it had no way to prevent you from holding onto a pointer to the memory managed by those objects and using them after that memory had been freed. With DIP 1000 and ` system` variables, it was possible to prevent ` safe` code from doing a use after free like that. Walter asked, "How about failure to free?" Paul said that was the halting problem. Your program could enter an infinite loop and never call `free`. Walter brought up Rust, and Paul said Rust didn't do that. Rust allowed memory leaks, but they'd free memory in their destructors, so it was as reliable as their destructors were. Walter said he took issue with that. When you reached the end of a function in Rust and had an owned pointer that hadn't been disposed of, you got an error. You got an error in ` live` functions, too, and he believed you got the same error in Rust. You couldn't just have an owner that ran off the end of the function. You had to do something with it. Timon said that Rust had multiple pointer types. One was the standard pointer with the star. Those couldn't be accessed in safe Rust code at all. Those were the pointers that you malloced and freed. The safety of those operations was ensured by their library implementation. The users only got borrowed pointers out of that, and those pointers were returned before those library containers got destroyed. It wasn't clear-cut what was the library and what was the language, but that was what it did. Walter thanked Timon for the explanation but said you still had to check that. He didn't think the language, by using RAII, was completely able to check that stuff. Timon said it had the borrow checker. It didn't check on plain pointers. ` live` checked on plain pointers. In Rust, plain pointers were unsafe territory. Robert said everyone was wrong and were all talking past each other. Any academic arguments about this were irrelevant, and Walter's definition of a safe language didn't match the marketing hype of all the other safe languages. The biggest complaint Rust got as a memory-safe language was that it was too complicated. basically invented an async syntax to avoid callbacks because jQuery or JavaScript callbacks the way node.js did them was terrible. We had to make it simple. If you had to know what a ` system` variable was, or a container, or had to write a callback, it was dead on arrival. And if it was so easy to get around the ` live` checking to call a function that wasn't marked ` live`, then we weren't adding anything. He thought the term "systems programming language" was also not what people wanted. There were always places where you had to do something unsafe to map a file to a CPU register or something, but 99.9999% of the time, nobody wanted to handle a pointer. At least, he would have never met anybody or hired anybody who wanted to shuffle pointers around. The world at this point was ruled by Python, and they didn't even have that concept. He reiterated that we needed to make it simple. If he had to know ` system` variables and functions annotated with ` live`, then no. He was just going to tell the person working on his project not to take the address of that thing, just pass a reference down, or make it a class, or a global array, and have a nice day. Jonathan said that DIP 1000 alone already increased complexity considerably. That didn't mean we shouldn't have it, but he'd specifically avoided using it in anything he'd dealt with because it was too hard to understand as it was. So if we were worried about people being able to understand this so that they could easily use it, then DIP 1000 on its own was already too much. For some people, the easiest was just going to be using the GC and not worrying about the rest of it. For a lot of stuff, that would be enough. He didn't know what we needed to do about `malloc` and `free`. He was fine just saying you'd have to use ` trusted` with that stuff. He didn't know enough about all of this to say if we needed ` live` or not, but the complexity was already pretty high. He thought we'd have a problem getting people to actually use it no matter how good it was. Walter said that having ` live` was a marketing point. His impression was that a lot of people who wrote Rust code didn't actually want to deal with the borrow checker, so they would just mark everything unsafe and then brag about their program being in Rust and everyone was happy with it. He thought that was a perfectly reasonable way to program: just don't worry about any of this stuff and write your code the way you want. But for the people who demanded this sort of protection, we needed to have a mechanism for it. Átila thought ` live` had a few issues, but one of them was the focus on `malloc` and `free`. Nobody should be calling those anyway. Why would you be doing that? Just use a smart pointer, a container, or something. We needed to focus on whatever language changes were necessary to enable writing those types in a way that they couldn't be escaped, and not focus on whether they freed a thing or not. Walter said he never understood smart pointers in C++. The layers and layers of templates with those things in C++ gave him a headache. So he was with Robert on that. He wasn't interested in the complexity. Timon said he could accept the argument that Walter wanted to make a marketing point, but then we'd attract people who were fine with engaging in some sort of cargo cult. Walter said a cargo cult was chasing a false god. ` live` would actually work. Timon said it would do the checks, but it wouldn't give you the guarantees. He said Walter had started the conversation by talking about why the government wanted people to use memory-safe languages. Timon thought they were talking about the guarantees. Robert said he'd bet Timon drinks forever that they weren't talking about guarantees. The word "should" was probably in there somewhere. If you had to build a drone and you didn't have the budget in your embedded CPU... There was always going to be that weird little thing that wasn't memory-safe because of reality. Timon said that if you wanted to have ` live` as a linting tool for ` system` functions, that was fine. We could market it that way. Robert thanked him. He said we should have safe by default. If you wanted a footgun, then maybe ` live` was a tool that would help you shoot off only one toe rather than the whole foot. Timon said there was some wiggle room. Depending on how exactly we developed ` live`, either it didn't improve safe capabilities or it made it safe and sound. Robert disagreed. If you could have more checks to give you more checks that were technically correct, then you had more. It wasn't removing anything at that point. Timon said that was exactly right, you could have more checks. That was one of the options. But then that meant that less code was accepted. And the code that wasn't accepted was not memory-unsafe, because it was in an ` safe` function in the past. Robert said it would still be theoretically possible to write unsafe code, but in practice, most things would be stopped by the hammer. Paul said if the purpose of ` live` was to exist for marketing and box-ticking, then he couldn't make an argument against it. But he wanted to point out that there were a lot of things on our TODO list, a lot of ongoing projects, things we could be spending our time and effort on. Maybe a feature whose only purpose was to tick a box on a marketing checklist wasn't the best place to allocate our resources if we had to choose. Walter said he'd set it aside for four years to work on other issues. He had thought ImportC was a much more important project, and he still believed it, but it was working now. There was also the long list of DIP 1000 problems, and he thought that was under control now. But with the government declaration, he believed we needed something to reassure people that they could write memory-safe code in D and that they didn't necessarily have to use the GC to do it. Paul said he would question if DIP 1000 was really taken care of. He had been working on code that attempted to rely on it and had run into some serious issues with it. In its current state, he thought nobody should be using it for anything outside of experimental or toy code. Walter asked if Paul had reported the issues he'd encountered. Paul said he had. He'd talked to Dennis about some of them, and Dennis had told him that DIP 1000 had been put on pause until editions were figured out. Dennis said that fixing those issues was hard when some of the existing BuildKite projects were already relying on those DIP 1000 quirks. It was hard to navigate around the breakage with those fixes. Editions would help, but that was kind of slowly trotting along. Paul thought we should remove any BuildKite tests that relied on DIP 1000. It was an unstable feature. If you depended on an unstable feature, your code was going to break. We should not and could not guarantee that code would continue to build. Dennis said we had encouraged people to use DIP 1000 for the new safety. If they had put in all that effort and then we just pulled the rug out from under them... He said it was used extensively in the Mir container types. Paul said it had been a mistake to encourage people to use it. We should just say we're sorry. The longer we waited to bite the bullet, the worse it was going to be. At this point, I suggested we table this topic for future discussion at a planning session or something. Átila was in Seattle, and he and Walter were going to talk about it that evening. He didn't expect they'd resolve anything, but he hoped to make progress. I asked them to let me know when they were ready to call a broader meeting about it. __Addendum__ Walter said that Robert had previously pitched suggestions on several features to remove or block in ` safe` code and asked Robert to send him a list of all of them. Átila recalled that he'd posted something about this in the forums and that Paul had replied with some issues about it, but he couldn't remember the details. Paul said that whether we ended up heading in Robert's desired direction of making ` safe` more restrictive, or the current direction with DIP 1000 and patching all the holes with it and ` safe` by adding new features, either way was going to be disruptive and break existing code. He said that one of the things he liked about D was its power and expressiveness. If the decision were up to him, he'd choose the direction that made it more powerful and expressive rather than less. He emphasized that this was just his opinion and he didn't speak for everyone. Ultimately, the final decision would be with Walter and Átila. He added that he could see the merit in Robert's position. In working on an ` safe` container library and implementing code for the callback API, he could see how ugly it was. It worked, but it wasn't pretty. He would love it if there were a way to make it pretty without a ton of complexity. I reminded everyone that part of our vision statement was "to enable the realization of ideas by shifting the way programmers think." That was our yardstick. If any of this stuff aligned with that, then we should continue considering it. Otherwise, we should discuss if we really needed it. I asked everyone to keep that in mind since we'd all gone in on adhering to a vision statement. Before we moved on, Walter let Timon know that although he was arguing with Timon on this, he appreciated Timon's perspective and insight, and valued his input. Timon said he wasn't arguing to be annoying, but because there was a difference of opinion. Walter just wanted to make sure Timon didn't get the wrong impression and think his opinion wasn't valued. Timon said that since DConf Online, he'd gotten tuple unpacking to pass the compiler tests. Compilation tests now sometimes failed in different ways, but the others were passing. Tuple unpacking now worked inside functions and foreach statements. I told everyone that I'd abandoned my hopes to find a sponsor for BeerConf at DConf this year. The per night cost for a pub hire was prohibitively expensive. Last year had been much more expensive than 2022, so it wasn't feasible to do it then. This year things were even higher. The cheapest we could find was £5500 for three nights. If I were going to ask any D shops for that kind of money, it would be much better spent if we put it into speaker/staff reimbursements. Especially since travel and lodging expenses were up significantly more this year over last year. I explained that we had a minimum revenue target every year to cover at least 40% of the reimbursements. Symmetry covered the rest as part of their overall budget and typically expected to pay no more than 60%. Ideally, we'd be able to pay 100% of reimbursements from revenue, but that had never happened. (__UPDATE__: Later, I was contacted by an anonymous donor looking to sponsor BeerConf this year. The donation was enough to cover one night, so on September 17th, we'll be able to have a few free rounds at [the Trinity Bell on Mitre Street](https://dconf.org/2024/index.html#beerconf), not too far from the venue. If you're there, please raise a glass to our anonymous donor! Additionally, we received a significant amount of funding from Weka, with additional support from Decard. I'm also expecting to finalize some support from Funkwerk soon. With this support, we were able to significantly exceed our minimum revenue target, which in turn allowed us to set the General registration rate to the Early-Bird rate. Massive thanks to Weka, Decard, and Funkwerk for their support!) Next, I noted that all expenses were up this year. The venue was more expensive because we were hosting the conference in September. That wasn't not part of peak travel season, but spring and fall were peak conference seasons. Other costs were up, too, due to general inflation. Even the cost of the swag was up. Because of this, in a meeting with the Symmetry DConf liaison and our event planner, we discussed the idea of eliminating all the swag except the t-shirts. I'd heard from some people that they ended up losing or discarding their bags, and some regular attendees had asked me if we could do something other than coffee mugs. I asked everyone what they thought: should we just go with t-shirts only? Walter said he had the impression that the t-shirts were all that most people cared about anyway. Jonathan said he used the mugs, but he had a ton of mugs in general so wouldn't miss them. Robert said his wife would be happy he wasn't adding another mug to the cupboard. He liked them, but if he wanted another D mug, he could just order it online. I noted that most of mine had been broken, but I didn't know if I even had any of the swag bags anymore. I might have thrown them out. In the end, no one objected to having t-shirts only. So we'll give it a try this year and see what the feedback is. Átila said he'd been reviewing feedback on an email thread about his editions proposal. The original idea had been that editions were to be opt-in to avoid breakage. The default would be to always compile old code and only switch to an edition when it was part of the module declaration. But the majority of the feedback was that the compiler should always use the new edition and old code should be compiled via a compiler switch. He was stuck on how to proceed. If he abandoned the original plan and went with always using the latest as default, then why should we even have the edition attribute for the module declaration? At that point, since we'd require a compiler switch to compile old code, why not just rely on compiler switches for the editions? He also felt that if we went with the latest editon as the default, then we'd be defeating our goal of avoiding breakage, which was the whole point of editions in the first place. Jonathan said that the advantage of the module declaration was that you could just look at the code and know which edition it was intended to work with. Then the purpose of the compiler switch would be just to set what the default edition was. Átila noted that we relied on compiler switches for previews, and it turned out that people rarely used them and complained anyway. Jonathan said he agreed with those who insisted we needed to default to the latest edition if we didn't want this to be a mess, and noted that was going to require some support in dub. If we didn't do that, then we'd just end up with people compiling with the default old edition and complaining that we didn't use the latest one by default. Átila said they might do that, but they also might complain because their old code broke with the default edition and they had to use a switch to make it work. We just didn't know. Jonathan said if the latest wasn't the default, we'd be punishing people who were trying to do the right thing by shoving them into the old language by default. Átila said he just wasn't sure what to think of this or what to propose to the community at this point. He understood the arguments on both sides, but he didn't know which was the best way forward. Jonathan noted that Adam liked to point out that no other language defaulted to the oldest version with this stuff. Átila countered with C++. I suggested that a way to break the logjam might be to have a new module declaration. Then when the compiler saw the old `module foo`, it would use the old edition, but the new-stye declarations would trigger the latest edition. Átila said that was the proposal he put forth. I clarified that I wasn't talking about an annotation. The problem with that was that you had to tell people that they couldn't get new features unless they annotated the module declaration. I was talking about a completely new keyword. Tutorials, docs and such would be updated to teach the new keyword instead of the old `module`. Then it would become "all new D code uses this module declaration" rather than "you have to use this annotation on your module declaration to get the newest features". Dennis said he thought that only new features that introduced breaking changes would require editions. Non-breaking features wouldn't require you to have editions in your module. Átila said that was the case. Rust backported non-breaking features, too, so that was fine. But something like safe-by-default would have to be in an edition. Átila noted that since he'd been stuck with the editions proposal, he'd written a safe-by-default DIP. He said he'd send it to us for some feedback. Basically, ` safe` was the default unless a function had no body. In that case, you had to have either ` safe`, ` system`, or ` trusted` on it or it wouldn't compile. Jonathan asked if it was restricted to `extern(D)` functions. Átila said it wasn't. He said that `extern(D/C/C++)` only affected linkage and calling convention. People assumed that it meant the function was written in the respective language, but it didn't have to be. An `extern(C)` function could be a callback for C written in D, for example. If it was, then the compiler could verify if it was ` safe`. Linkage didn't enter into it. It was just a question of whether it had a body. Dennis said that linkage kind of did come into it because ` safe` was mangled in the name of `extern(D)` functions to prevent you from linking to an ` system` function. Átila agreed but said that, just to make it simpler, if a function had no body it wouldn't compile without one of the three safety annotations. Timon said that if you could add ` safe` to an `extern(C)` declaration with no body, then it would become ungreppable. Átila said he assumed they'd use ` trusted` in that case. But who knew what people would do? If they did use ` safe` there, it was on them because it was explicitly their declaration. Timon said that the selling point of ` trusted` was that the language was defined such that when you got a memory safety issue, it was a compiler bug or an issue with something that was annotated as ` trusted`. If you allowed ` safe` on `extern(C)`... Jonathan said that all we had to do was to disallow ` safe` on `extern(C)`. Timon agreed and said you could use ` trusted`. It had the same meaning in terms of the interface. The only difference between it and ` safe` was what it did to the function body. Átila said that was a good point. That was the kind of thing that would come from feedback anyway. Jonathan said that the fact that ` safe` and ` trusted` had different mangling was undesirable, though he didn't know if it was a big enough issue to change it. It didn't add any benefit, as it was the checking of the body that made the difference. This led to a debate about whether it mattered if a function prototype was declared ` safe` or ` trusted`. A prototype was just an interface, and from that perspective, there was no difference. In both cases, the interface was safe. Jonathan said that if he could suggest one thing, it would be to eliminate the mangling for ` safe` functions, then there would be no linking issues between ` safe` and ` trusted`. This mattered, for example, for delegates. If you used a delegate, you shouldn't have to care if it was ` safe` or ` trusted` because the interface was exactly the same, but you ended up having to care because of mangling. Timon said what could be done was to allow ` trusted` function pointers and delegate types to decay to ` safe`. Walter said that sounded like a good idea on first blush. Dennis brought up a compiler bug with mangling that existed because we had ` system` functions and default functions, which were ` system` by default. But if you called `getAttributes` on a function, whether you got ` system` or not depended on which one the compiler saw first, because ` system` functions were mangled with it and default functions were not. Walter said that was a good point and was glad Dennis had brought it up, as he'd overlooked it. The entire type system relied on the concept that if they mangled the same, then they were the same. Walter thought Timon's suggestion would help with Jonathan's issue. He suggested Jonathan try it out and see if it would work. (Update: At the end of May, Átila posted threads in the DIP Ideas forum for [his Editions proposal](https://forum.dlang.org/thread/tskwospngntbnqiuxbag forum.dlang.org) and [safe by default](https://forum.dlang.org/thread/uhmntnhqdwomdallfroo forum.dlang.org).) At this point, the meeting was over, but we spent the next few minutes chatting about some interesting topics that came up through small talk as we were winding down. We held our next meeting on May 10.
Jul 30
On Tuesday, 30 July 2024 at 11:50:50 UTC, Mike Parker wrote:The D Language Foundation's monthly meeting for April 2024 was held on Friday the 12th. It lasted an hour and 20 minutes. [snip]Thanks for the detailed write-up!
Jul 30
On Tuesday, 30 July 2024 at 11:50:50 UTC, Mike Parker wrote:The D Language Foundation's monthly meeting for April 2024 was held on Friday the 12th. It lasted an hour and 20 minutes.very interesting thanks
Jul 30
I suggested that a way to break the logjam might be to have a new module declaration. Then when the compiler saw the old `module foo`, it would use the old edition, but the new-stye declarations would trigger the latest edition. [...]Suggest to add setting to sc.ini for default edition (only affect module without edition attribute), DefaultEdition=Latest For old codes and failed to compile, add a bold suggestion to edit sc.ini and change it to DefaultEdition=
Jul 30
Mike Parker kirjoitti 30.7.2024 klo 14.50:The D Language Foundation's monthly meeting for April 2024 was held on Friday the 12th. It lasted an hour and 20 minutes.Wow, this has a lot to comment on!Historically, there had only been 15 or so bugs for ` live` and all but one had been fixed. In fixing a couple of them recently, he'd discovered a couple more gaps in what the ownership and borrowing system did. He was working on fixing them. He proposed that we turn on ` live` by default so people might be more inclined to try it and file bug reports on it.Unfortunately, this is likely only the tip of an iceberg. I don't think many people currently use ` live` since it has so few use cases. Hence bugs likely remain under the surface.He noted that Microsoft had created Managed C++, which had two kinds of pointers---GC pointers and non-GC pointers. Though they still maintained it, it had vanished from the conversation. He considered Managed C++ and their approach to be a failure because of it.There's a much better study case for this than Managed C++. Namely, Nim, probably the closest competitor of D. It also has different types for GC-managed and manually allocated pointers, unless my memory completely betrays me.He thought we did have a memory-safe language and the best way to write memory-safe code today was to disable DIP 1000 and use the garbage collector. DIP 1000 introduced additional cases of memory unsafety, so just disabling it and using the GC with ` safe` would enable memory safety.I though it was vice-versa - the language is unsafe *without* dip1000. Or does Timon mean implementation bugs in it? But I do agree that it's best to program mostly like DIP1000 didn't exists and just rely on the GC. DIP1000 is there to catch the case where you accidentally return a self-pointer from a member function or a slice of your static array on stack.Dennis said it didn't have to be done by ` live`. It could be done by a container library or something. Walter said it couldn't. Dennis said that we should then explore ways to do it. He said Paul was working on that now, how to use allocator interfaces to create safe data structures.Don't you remember? Timon [has already shown](https://forum.dlang.org/post/tr9j1h$1fvd$1 digitalmars.com) it can be done.Walter said he didn't understand why. You could incrementally add ownership/borrowing checks to your code where and when you wanted. If you didn't add ` live`, you didn't get the checks. He didn't understand how you could get a memory-safe language just by fiddling with the allocators. You had to solve the problem.To see why, try to write an userspace function that manually mallocates and frees. You can write only general-purpose ` trusted` and ` system` functions - meaning, something that could potentially get accepted to Phobos. All code tailored to the use case of the user needs to be 100% ` safe`. You may freely use or not use ` live` on any function as you see fit. If I'm on the map here, this can only be accomplished with Timon's trick I linked to, and it doesn't use ` live` at all. ` live` doesn't provide any additional means to do this.Robert said everyone was wrong and were all talking past each other. Any academic arguments about this were irrelevant, and Walter's definition of a safe language didn't match the marketing hype of all the other safe languages. The biggest complaint Rust got as a memory-safe language was that it was too complicated. And if we had to do callbacks...This is an important point, but I have a slightly different take. Any way these issues are going to be fixed (if they are to be) must stay out of the way of those who don't care. That is, if you happily let GC to do memory management for you, or are happy to manually review your mallocations and frees accepting the risks, your life must not get any more complicated. But if you want to have it all - both memory safety and no gc - that's a complex problem by definition. You can't expect to do that without a significant learning curve for your tool.Paul thought we should remove any BuildKite tests that relied on DIP 1000. It was an unstable feature. If you depended on an unstable feature, your code was going to break. We should not and could not guarantee that code would continue to build.Please don't. What's wrong with keeping DIP1000 optional until we have editions, and making it the default in the next edition? That way no-one has to migrate if they can't.He said that one of the things he liked about D was its power and expressiveness. If the decision were up to him, he'd choose the direction that made it more powerful and expressive rather than less. He emphasized that this was just his opinion and he didn't speak for everyone. Ultimately, the final decision would be with Walter and Átila.I also suggest this. Not because Robert's way would be worse than DIP1000 tricks, but because DIP1000 is a strict superset of Roberts proposal. You can totally keep DIP1000 as it exists enabled and program with no `scope` or `return` usage.Átila said they might do that, but they also might complain because their old code broke with the default edition and they had to use a switch to make it work.That's the case with pretty much anything. If I leave some work aside for a few years, install newer versions of the compilers and libraries I was using and then open up my work again, it's pretty likely I will have to open the docs and see how I'll migrate my work, regardless of the language/libraries. If the docs say "just add edition declaration to top of your file, or use a compiler switch", I'm actually lucky. It isn't realistic to expect better from any language or library that is still being developed.Dennis brought up a compiler bug with mangling that existed because we had ` system` functions and default functions, which were ` system` by default. But if you called `getAttributes` on a function, whether you got ` system` or not depended on which one the compiler saw first, because ` system` functions were mangled with it and default functions were not.Maybe related to https://issues.dlang.org/show_bug.cgi?id=24003 ?
Jul 31
On Wednesday, 31 July 2024 at 08:15:22 UTC, Dukc wrote:There's nothing wrong with that, it's even the current situation. But that doesn't change the Buildkite situation. To clarify, the problem is that some dub projects only compile with `dflags "-preview=dip1000"` and that any DMD pull request fixing DIP1000 bugs must ensure those dub projects continue to build with `-preview=dip1000`, even when they rely on those bugs.Paul thought we should remove any BuildKite tests that relied on DIP 1000. It was an unstable feature. If you depended on an unstable feature, your code was going to break. We should not and could not guarantee that code would continue to build.Please don't. What's wrong with keeping DIP1000 optional until we have editions, and making it the default in the next edition? That way no-one has to migrate if they can't.It's similar, but not related. Both issues are rooted in the type mangle not being a complete description of the type, but the mangle is still being used for equality. Therefore two types with slight differences may appear equal to the compiler. But in one case, the missing information is 'scope is inferred', and in the other situation, the missing information is ' system is explicit / default'. The summary is not entirely accurate by the way:But if you called `getAttributes` on a function, whether you got ` system` or not depended on which one the compiler saw first, because ` system` functions were mangled with it and default functions were not.Maybe related to https://issues.dlang.org/show_bug.cgi?id=24003 ?because ` system` functions were mangled with it and default functions were not.It should be:because ` system` functions and default functions are mangled exactly the same.
Jul 31
On Wednesday, July 31, 2024 2:15:22 AM MDT Dukc via Digitalmars-d-announce wrote:Mike Parker kirjoitti 30.7.2024 klo 14.50:DIP 1000 is attempting to make more stuff safe than it is now - particularly with regards to getting pointers to non-GC-allocated memory and having the compiler verify that they don't escape. So, with DIP 1000, less code has to be trusted, but it's not at all necessary to have safe code. DIP 1000 is completely unnecessary if we take the stance that if you want safe, you use the GC, and any code that you have which can't do that for some reason, you vet and mark as trusted. The whole reason that DIP 1000 and live and the like come into play is basically because Walter wants to try to make dealing with malloc-ed memory safe, but the cost in terms of language complexity is enormous (and it doesn't really solve the problem anyway, much as it does reduce it). So, DIP 1000 helps, but some of us think that it's far too complex given what it costs, and it's definitely not required to have a memory safe language. It's just that we need it (or something which fulfills a similar role) in order to make more stuff safe (rather than trusted) than we can currently do. Some stuff is going to need to be vetted by programmers and marked with trusted no matter what we do. The problem with slicing static arrays does exist without DIP 1000, but that can be solved by actually treating it as system like it should be (since it's basically just a different syntax for taking the address of a local variable for a specific type of variable). Removing implicit slicing of static arrays also improves the situation since then you don't get surprises where you're doing something system without realizing it. DIP 1000 is not required to solve that problem. Similarly, if there are any other cases where safe code is not currently guaranteed to be memory safe, it's either a bug in the implementation or in the design. DIP 1000 is a way to add more to what can be automatically treated as safe. It's not a way to make a language that isn't memory safe be memory safe. And it's primarily of value for folks who are actively trying to avoid the GC. - Jonathan M DavisHe thought we did have a memory-safe language and the best way to write memory-safe code today was to disable DIP 1000 and use the garbage collector. DIP 1000 introduced additional cases of memory unsafety, so just disabling it and using the GC with ` safe` would enable memory safety.I though it was vice-versa - the language is unsafe *without* dip1000. Or does Timon mean implementation bugs in it? But I do agree that it's best to program mostly like DIP1000 didn't exists and just rely on the GC. DIP1000 is there to catch the case where you accidentally return a self-pointer from a member function or a slice of your static array on stack.
Jul 31
Jonathan M Davis kirjoitti 31.7.2024 klo 19.00:The problem with slicing static arrays does exist without DIP 1000, but that can be solved by actually treating it as system like it should be (since it's basically just a different syntax for taking the address of a local variable for a specific type of variable). Removing implicit slicing of static arrays also improves the situation since then you don't get surprises where you're doing something system without realizing it. DIP 1000 is not required to solve that problem.We also need to disable taking a pointer of a struct field, if that struct is local or `ref` (including the `this` `ref`). But adding that, yes, works. This is exactly what Robert proposed at last DConf. I'm going to call his proposal Simple Safe D as per the title of the talk. It would keep the language as simple as it's without DIP1000 and would be memory safe, but it would break existing code just as hard as DIP1000 does. Plus, nothing in DIP1000 forces you to use it's extra features compared to Simple Safe D. You can avoid the compiler complaining by simply using the GC either way.
Jul 31
On Wednesday, July 31, 2024 12:50:39 PM MDT Dukc via Digitalmars-d-announce wrote:Jonathan M Davis kirjoitti 31.7.2024 klo 19.00:Not really, since with DIP 1000, the compiler infers scope in some cases, and then you're forced to deal with it whether you like it or not. Even though I don't normally use DIP 1000, I've found that in the cases where I've tried, I inevitably get cryptic complaints that I have to figure out how to fix with regards to scope (which is particularly annoying with templated code). Either way, my big problem with DIP 1000 is simply that it adds a ton of complexity to the language, and if that complexity is there, I'm going to have to deal with it at some point unless I'm only writing code for myself and never interact with anyone else's code (which obviously isn't realistic, especially if I use D professionally). I don't believe that that complexity pays for itself, and honestly, if it becomes the default, I'm going to be tempted to just slap system on everything and give up on safe entirely, because I simply don't want to deal with it - but even then, that won't work when dealing with code that I don't write. - Jonathan M DavisThe problem with slicing static arrays does exist without DIP 1000, but that can be solved by actually treating it as system like it should be (since it's basically just a different syntax for taking the address of a local variable for a specific type of variable). Removing implicit slicing of static arrays also improves the situation since then you don't get surprises where you're doing something system without realizing it. DIP 1000 is not required to solve that problem.We also need to disable taking a pointer of a struct field, if that struct is local or `ref` (including the `this` `ref`). But adding that, yes, works. This is exactly what Robert proposed at last DConf. I'm going to call his proposal Simple Safe D as per the title of the talk. It would keep the language as simple as it's without DIP1000 and would be memory safe, but it would break existing code just as hard as DIP1000 does. Plus, nothing in DIP1000 forces you to use it's extra features compared to Simple Safe D. You can avoid the compiler complaining by simply using the GC either way.
Jul 31
On Wednesday, 31 July 2024 at 16:00:21 UTC, Jonathan M Davis wrote:DIP 1000 is completely unnecessary if we take the stance that if you want safe, you use the GC, and any code that you have which can't do that for some reason, you vet and mark as trusted.Unfortunately that leads to certain patterns that are safe using dip1000 to now be trusted. Which might cascade into surrounding code needing to be trusted as well. Overall it's a loss. I understand not everyone uses those patterns, which are mostly focused on ownership and lifetime, but I have found them to enable so called pit-of-success apis more than anything else. Contrast that with more 'prescriptive' apis that for instance require a certain ordering of calls or require certain functions to be called at certain points, which are far easier to use incorrectly. Plus they often fail/assert at runtime.The whole reason that DIP 1000 and live and the like come into play is basically because Walter wants to try to make dealing with malloc-ed memory safeDon't forget the stack. Being able to safely use references to the stack brings at least as much value.but the cost in terms of language complexity is enormous (and it doesn't really solve the problem anyway, much as it does reduce it). So, DIP 1000 helps, but some of us think that it's far too complex given what it costsThe only two issues I have with dip1000 is that it a) sometimes requires its attributes in seemingly unrelated code, and b) can require some workarounds for its imperfect (practical?) tracking. Overall though, I have found it is a natural conclusion when you combine lexical lifetimes and references/borrows.
Jul 31
On Tuesday, 30 July 2024 at 11:50:50 UTC, Mike Parker wrote:[...]Thanks!
Jul 31