Forums before death by AOL, social media and spammers... "We can't have nice things"
|    comp.programming    |    Programming issues that transcend langua    |    57,431 messages    |
[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]
|    Message 57,405 of 57,431    |
|    Dan Cross to david.brown@hesbynett.no    |
|    Re: Rust vs Hype (was Re: Informal discu    |
|    04 Aug 25 22:33:36    |
      [continued from previous message]              >> a vtable. How do you do it? This is an area where C++       >> basically forces you to use a pointer; even if you try to put a       >> `unique_ptr` into the vector, those can still own a `nullptr`.       >       >Sure, there are still occasions when you need raw pointers in C++. It       >is far from a "perfect" language, and suffers greatly from many of its       >good ideas being add-ons rather than in the original base language,       >meaning the older more "dangerous" styles being still available (and       >indeed often the default). But just as you should not need raw pointers       >in most of your Rust programming, you should not need raw pointers in       >most of your C++ programming.              Except that you do, if you want to do (say) dynamic method       dispatch across a collection of objects. If you don't use       inheritence you don't have to care, but that's a pretty       fundamental part of the language.              I'd say this is qualitatively different than the situation in       Rust, where most of the time you don't need the dangerous thing,       while it's baked into core language features in C++.              >>> So while I appreciate that comparing these two projects might be more       >>> useful than many vague "C vs. Rust" comparisons, it is still a       >>> comparison between a 10-20 year old C project and a modern Rust design.       >>>       >>> The most immediate first-impression difference between the projects is       >>> that the Rust version is sensibly organised in directories, while the C       >>> project jumbles OS code and user-land utilities together. That has,       >>> obviously, absolutely nothing to do with the languages involved. Like       >>> so often when a Rust re-implementation of existing C code gives nicer,       >>> safer, and more efficient results, the prime reason is that you have a       >>> re-design of the project in a modern style using modern tools with the       >>> experience of knowing the existing C code and its specifications (which       >>> have usually changed greatly during the lifetime of the C code). You'd       >>> get at least 90% of the benefits by doing the same re-write in modern C.       >>       >> Not really. rxv64 has a very specific history: we were working       >> on a new (type-1) hypervisor in Rust, and bringing new engineers       >> who were (usually) very good C and C++ programmers onto the       >> project. While generally experienced, these folks had very       >> little experience with kernel-level programming, and almost none       >> in Rust. For the OS bits, we were pointing them at MIT's course       >> materials for the 6.828 course, but those were in C and for       >> 32-bit x86, so I rewrote it in Rust for x86_64.       >>       >> In doing so, I took care to stay as close as I reasonably could       >> to the original. Obviously, some things are different (most       >> system calls are implemented as methods on the `Proc` type, for       >> example, and error handling is generally more robust; there are       >> some instances where the C code will panic in response to user       >> action because it's awkward to return an error to the calling       >> process, but I can bubble thus back up through the kernel and       >> into user space using the `Result` type), but the structure is       >> largely the same; my only real conceit to structural change in       >> an effort to embrace modernity was the pseudo-slab allocator for       >> pipe objects. Indeed, there are some things where I think the       >> rewrite is _less_ elegant than the original (the doubly-linked       >> list for the double-ended queue of free buffers in the block       >> caching layer, for instance: this was a beautiful little idea in       >> early Unix, but its expression in Rust -- simulated using       >> indices into the fixed-size buffer cache -- is awkward).       >       >I can certainly see that some things are more inconvenient to write in       >C, even in modern C standards and styles - Rust's Result types are much       >nicer to use than a manual struct return in C. (C++ has std::expected<>       >that is very similar to Result, though Result has some convenient       >shortcuts and is much more pervasive in Rust.)              Yeah. I want to like `std::expected`, but its use is awkward       without the syntactic sure of the `?` operator. There's the old       saw about syntactic sugar and cancer of the semicolon, but in       this case, I think they got it mostly right.              >> The Rust port did expose a few bugs in the original, which I       >> fixed and contributed back to MIT. And while it's true that the       >> xv6 code was initially written in the mid 00's, it is still very       >> much used and maintained (though MIT has moved on to a variant       >> that targets RISC-V and sunsetted the x86 code). Also, xv6 has       >> formed the basis for several research projects, and provided a       >> research platform that has resulted in more than one       >> dissertation. To say that it is not representative of modern C       >> does not seem accurate; it was explicitly written as a modern       >> replacement for 6th Edition Unix, after all. And if it is not       >> considered modern, then what is?       >       >Modern C would, IMHO, imply C99 at the very least. It would be using       >C99 types, and it would be declaring local variables only when they can       >be properly initialised - and these would often be "const". It would be       >using enumerated types liberally, not a bunch of #define constants. It       >would not be declaring "extern" symbols in C files and other scattered       >repeated declarations - rather, it would be declaring exported       >identifiers once in an appropriately named header and importing these       >when needed so that you are sure you have a single consistent       >definition, checked by the compiler. It would not be using "int" as a       >boolean type, returning 0 or -1, or when an error enumeration type would       >be appropriate. It would be organised into directories, rather than       >mixing the OS code, build utilities, user-land programs, and other files       >in one directory. Header files - at a minimum, those that might be used       >by other code - would have guards and include any other headers needed.       >Files would have at least a small amount of documentation or       >information. All functions would be either static to their files, or       >declared "extern" in the appropriate header.              Much of this is, as you say, stylistic. Enumerations for       constants might be an improvement, I suppose, but in C they       confer few benefits beyond `#define`; they're basically `int`s       up through C18, and still default to `int` unless defined with a       fixed underlying type in C23.              That said, I mostly agree with you; certainly, using       appropriately sized types everywhere would already been a       considerable improvement.              >And for code like this that is already compiler-specific, I would also       >want to see use of compiler extensions for additional static error       >checking - at least, if it is reasonable to suppose a compiler that is       >modern enough for that.              This I must push back on. This code is or (or, rather, should       not) be _compiler specific_ so much as _ABI specific_.              There seem to be a handful of specific compiler attributes used       here: mostly in marking bits of code `__attribute__((noreturn))`       (though we have a standard way to write that now) and aligned       (we also have a standard way to do that now, too). There's a       small amount of inline assembly, which _could_ just be in a `.S`       file, and a coule of calls to `__sync_synchronize()` intrinsics,       which could be replaced with some sort of atomic barrier, I'd       imagine.              But herein lies another problem with this approach: once you       start using a lot of compiler-specific extensions, you're not              [continued in next message]              --- SoupGate-Win32 v1.05        * Origin: you cannot sedate... all the things you hate (1:229/2)    |
[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]
(c) 1994, bbs@darkrealms.ca