Context for those who don't follow Rust development closely:
This release stabilises Generic Associated Types (GATs), a limited form of Higher Kinded Types. This is only an MVP release, but it already includes enough to be useful, and has been a huge multi-year effort (the RFC for the feature dates to April 2016).
Novice users of Rust probably won't use this feature directly, but it gives a lot more power to library authors to write more flexible APIs while still keeping all of Rust's strict correctness guardrails (i.e. exposing a safe API). It will also form the basis of the upcoming "async functions in traits" feature.
This is probably the most significant Rust release in the last couple of years.
From that thread, a link https://www.fpcomplete.com/blog/monads-gats-nightly-rust/ to a comparison of GAT's w/ HKTs as seen in high-level functional languages. Note that the version of GAT's provided here is a MVP and might be unable to express some of these patterns.
This topic made me think that you'll eventually have to support all FP principles in a strongly type safe language like Rust which reminds me of Scala FP community. I'm not sure if it ended up being a good thing for Scala long-term.
I also wonder whether Linux kernel community would adapt these concepts or reject them for the sake of KISS.
I agree with the significance. I've liked the additions over the past few years of course, but the last time I felt a release was this significant was async, I believe 1.39, about 3 years ago.
And coincidentally, the times I've wanted to reach for GATs have been when dealing with Futures (specifically dealing with lifetimes of Futures produced by Fns; basically what gates async functions in traits). I'm excited to be able to finally use them in my APIs!
Not just yet, the two big blockers on async methods are:
1. The ability to use generics in associated types
2. The ability to use `impl Trait` in associated types
GATs provide the first, but the latter is still being worked on. The good news is that the implementation has matured greatly this year and appears to be in a state where stabilization could be considered. AFAICT this work is being done in the broader context of async methods, tracked here: https://github.com/rust-lang/rust/issues/91611
Except the let-else version has one big disadvantage. The 'match' version has bound the error to `e`, so you can log that error or inspect it. The 'let-else' version can't read the error, so its log message can't be as useful. You can't check if it's a specific error, or include the error in logged messages.
It's still convenient, but in really limited circumstances, AFAICT. This week I'll be going through the various Rust projects I maintain at work, seeing if there's useful places for let-else.
> This week I'll be going through the various Rust projects I maintain at work, seeing if there's useful places for let-else.
If you want help from automation, you can wait a few days until the manual_let_else clippy lint arrives on nightly. It's going to be one of the pedantic lints, and recognizes some obvious places where let else would make sense (not all but many). It should arrive in one week-ish, depending on when the next clippy update is in nightly.
Update: I did go through every `match` statement in my 16k-line Rust project at work, and I found a number of places where it was useful. My commit to use let-else had 10 files changed, 27 insertions(+), 48 deletions(-).
Yes, though that doesn't put the value of the `Ok` variant into any scope. At the end of the day, if you need maximum flexibility for whatever you're doing then you still need to reach for `match`, even if it's a bit more verbose.
I mean, in all cases `if let` is for when there's nothing in other constructors that you want to talk about. That'll be every time you match on `Option<T>`, `Result<T, ()>`, or `Result<(), T>`, all of which come up at least occasionally, and will occasionally be other cases.
Edited to add: I don't mean to imply that you should always use `if let` for those cases - that may be but I reserve judgement on it.
Swift has `guard else`, including `guard let else` for preconditions, where you only put the error responding code and where the compiler forces you to exit the current context (e.g. return a value, throw an error, etc).
It is nice for collapsing pyramids of doom that come from normal precondition checking. You can put multiple comparisons or variable assignments into a a single guard as well, separated by commas.
It does not support binding to the error in a Result though, so for these you usually still get more readable code handling these with try/catch, with the corresponding nested code block.
It's mostly about avoiding nesting. Honestly, I'm still pretty ambivalent about it. But, before you might do:
if let Some(x) = maybe_x {
// do stuff with x
} else {
return;
}
now, you'd do:
let Some(x) = maybe_x else {
return;
}
// do stuff with x
If you have several instances of this kind of thing, the nesting can be pretty ugly and hard to read, so we'd sometimes do janky things to avoid the nesting, like:
let x = if let Some(x) = maybe_x { x } else { return; };
or,
if let (Some(x), Some(y)) = (maybe_x, maybe_y) {
// do stuff with x and y with only one layer of nesting
} else {
return;
}
`let else` looks strange to my eyes on first glance, but I can remember many cases when it would have been nice to have. (Not to mention, all Rust syntax used to look strange to my eyes so that's not a very useful criterion).
Break from labeled blocks is a pretty niche thing. I can remember a few cases it would have been useful, but I'm not sure I'll remember the feature exists next time it comes up.
I'm glad that GATs are finally here. I tend to be wary of complex type-system things. I can remember being a new rust programmer around 1.0, dealing with some library with a perhaps-overly-clever API with complex traits and lifetimes and being very frustrated randomly changing code trying to get it to compile. It didn't help that rustc error messages and rustdoc weren't as good and we didn't have any sort of language server back then. Perhaps I'm just not very smart. But even with my focus on simply-typed APIs I've run into several cases where I couldn't do something the obvious way because it needed GATs.
I used to be a lot more involved with Rust, reading a lot of /r/rust and blog posts and issue trackers. I get a warm wistful feeling seeing things like GATs, rust-analyzer, and MIR inlining get stabilized after all these years.
> Break from labeled blocks is a pretty niche thing. I can remember a few cases it would have been useful, but I'm not sure I'll remember the feature exists next time it comes up.
Yeah, I feel like the vast majority of the time this would be better handled by splitting out that block into a function. There are situations where there the number of parameters needed to pass in would get unwieldy, but that is where I start thinking about if all that loose state is intrinsic to the problem, or a sign that I need to refactor my datastructures.
One reason to support this sort of feature is that it makes it easier to split changes into two reviewable steps: first make a minimal change that introduces some ugly thing like break-with-label, then clean it up with a no-change-of-behaviour commit.
Like with GAT, I think one of the major reasons to support this feature is because it feels consistent. "I can put generics here, but not there? I can break here but not there?". I've run into "accidentally" writing the equivalent of GAT before just because I had expected it to work.
The borrow checker is "smarter" within a single function body though, so factoring code into a separate function is not necessarily as easy as in other languages.
I ran into this issue years ago (possibly even before labeled exit from loops or even NLL, although I'd have to dig through some old code to confirm this). I had some logic that I wanted to short-circuit, but moving everything to a separate method call would have required an extra borrow that would not have been allowed. I don't think that I'll end up needing to use this feature much, but I'm glad to finally have it as an option for the rare cases when it will improve the readability of my code.
> `let else` looks strange to my eyes on first glance
AIUI, this is a rather specialized feature that only supports diverging code in the "else" block. I assume that the weird syntax was purposely chosen to suggest something like that.
I don't find the syntax weird, I think it's perfectly cromulent with the existing capabilities. To wit, pattern matching in `let` has always been possible:
let (x, y) = (1, 2);
...But only for patterns that can never fail. For enums, not all patterns are irrefutable:
let Some(x) = Some(42); // error, Rust can't tell that RHS isn't `None`
Note that some languages with pattern matching do allow the above, e.g. OCaml does, and just panics if the match doesn't succeed (so equivalent to `let x = Some(42).unwrap()` in Rust). But Rust favors exhaustive pattern matching, so that wasn't a good fit.
The way that Rust solves this is via `if`-style constructs. So you already have `if let`:
if let Some(x) = Some(42) {
// `x` exists in here
}
This produces an inner scope where the contents of the enum are bound. And you can use `else` here as well:
if let Some(x) = Some(42) {
// `x` exists in here
} else {
// branch where `x` doesn't exist
}
So the `let else` syntax feels like a natural continuation to me:
let Some(x) = Some(42) else {
// branch where `x` doesn't exist
}
// `x` exists here
This reduces the nesting required in several common cases of using enums, which makes code easier to read. (Of course, the interesting thing is that since `x` exists in the outer scope, the compiler requires the inner scope to never reach the outer scope (it must "diverge", by returning or panicking or infinite looping or whatever), which is an extra restriction above what a normal `if else` requires.)
> Libs: Don't generate PartialEq::ne in derive(PartialEq)
Meaning: Smaller generated code leading to faster compile times
> Cargo: Take priority into account within the pending queue.
When not enough CPUs are available (particularly CI), cargo will now prioritize crates with the longest dependency chain. We are wanting to be even smarter about which crates get priority but we still need to figure out what are acceptable heuristics (as we don't want to hard code crate names)
Apparently the PartialEq trait has two methods - eq and ne (equal and not-equal, == and != respectively). Normally you only implement eq, because ne has a default implementation that's just !self.eq(other). The docs even say:
> Implementations must ensure that eq and ne are consistent with each other
> The default implementation of ne provides this consistency and is almost always sufficient. It should not be overridden without very good reason.
So I'm guessing that `derive(PartialEq)` used to actually generate a fresh ne in each usage (even though presumably it was equivalent to !self.eq(other)), instead of just falling back to the default implementation. I can definitely see that having an impact on compile times.
Do I have that right?
Addendum: Now I'm trying to think of a case where you'd want a custom implementation of ne... I'm not sure I can come up with one
> I'm trying to think of a case where you'd want a custom implementation of ne... I'm not sure I can come up with one
One old example from school was comparing unordered sets of numbers, each backed by a flat array. Summing such an array, contiguous in memory, was very fast: faster than many individual numeric comparisons. So "not equals" checked for equal sums before dropping back to iteration. Of course, that only made sense in situations where more things weren't equal (and didn't share sums) than not, but it helped someone win some performance/vanity extra credit. And I didn't know about vectorized code at the time, so that might make it a wash.
A similar example might be with probablistic checksums of large data. If a checksum answers "maybe the same or definitely not the same" a la a HyperLogLog, comparing checksums is a quick way out for "not equals". Of course, that'd require some uniquely small/untrustworthy checksums, or some uniquely paranoid comparison programmers! That applies similarly to "equals", though.
About the only even vaguely realistic example I can think of is for non-complementary notions of equality and inequality, i.e. an application context in which case it makes sense to have rules like "two MyLists are equal if they contain the same elements, but are not equal if they contain different elements or have different orders". And I call that "realistic" because I've seen code do things like that .... not because it's anything but a terrible idea.
Maybe a data structure where you have an array of data and its hashed value, an eq implementation needs to go over the array to compare, but the ne implementation can short circuit by just comparing the hash. hash(a) != hash(b) => a != b, the reverse doesn't hold.
I thought about that sort of thing too, but eq returns equal-or-not-equal, so it could apply the same short-circuit
Simpler example: if two lists don't have the same length you know they're unequal without looking at the items. But you could early-terminate eq the same way and actually benefit both eq and ne
Thanks though lqd is the one to thank the most for the performance work. I really appreciate the build time performance folks (nick, lqd) are looking at things holistically rather than staying in one specific domain.
Before going into the details of the new Rust release, we'd like to draw attention to... [political cause]
The cause in this case is undeniably worthy, its an awful situation in an often crappy world, but what does it have to do with this release? Where do you start and stop with the issue-raising in technical release news?
Thanks, I feel like people are always trying to make sure everything is done in some super formal way. The authors decided to put this in so they did, they don't need some formalized criteria for "Good Movement" or whatever.
Its common place these days for tech organizations to promote social and political issues. The issue for me here is - what if hypothetically the political viewpoint is misguided?
What if this was 2003 and the statement said "Due to the newly found weapons of mass destruction in Iraq, we stand in solidarity with the American government for its war against terror"?
I don't think a tech organization should be making such statements in their release notes, which is essentially telling people what should be thought of as right, or wrong, or how to think about a particular issue.
To me its reflective of a potentially dangerous trend that everyone _must_ be an activist and have some kind of alignment.
All I care about is the new and improved logic flow syntax of Rust.
I feel like this trend is starting to come full circle. We went through a time where companies and organizations felt like they needed to be political activists in all their docs and announcements. And for a while it felt like questioning the activism was questioning the validity of the cause. But it feels like more people are recognizing that politics doesn't need to pervade every part of our lives. It is okay for technical release notes to only be technical release notes, regardless of what current events are.
Unlike Rust code, activism is an area where statements have a chance to be incorrect or misguided. And just like Rust code, you're welcome to review anything you read, and see if you like it or not.
The whole point of activism is to bring issues to an audience that wasn't prepared to hear such statements at a given time: this is why some people get annoyed when they read Notepad++ release notes for the first time!
Being "right" doesn't have anything to do with activism: there's lots of activism within, say, flat earthers, but that doesn't make Earth any less round. Still, in this particular point in time, stating support for women in Iran is probably the mildest form of activism anyone could push for.
> The issue for me here is - what if hypothetically the political viewpoint is misguided?
Then you stay away from engaging with the underlying community that issues such statements (which might just be a smaller sub-community of the project's wider community).
> All I care about is the new and improved logic flow syntax of Rust.
And you are free to care only about that, use it as a purely technical product and just ignore any political statements (which shouldn't be too hard).
---------
While I don't think every organization intends to have some kind of alignment, they ultimately will all have one, since people do, and organizations are made up of people.
Sometime in the last week, there was an open source federated social network project posted on HN. They have a very political stance when it comes to their developer community, which causes many people to stay away from contributing to the project, to a level where I think it might be the project's long-term demise. While it's never a nice sight to see "wasted effort" like that, given the high level of transparency and contributors willingly joining and staying in the community, that seems like a decent mode of operating.
Where I live, there's a Kony2012 guy still in town. I respect his resolve. I could let it get to me but he seems passionate so meh, let people do what makes them happy. I can skip the rhetoric if it bothers me.
That paragraph also got me wondering why they're not drawing attention to, for example, the Human Rights situation in China. Maybe because that might draw the ire of the powerful Chinese state? Or to the situation in Saudi Arabia, where women have even fewer rights than in Iran. Maybe because Saudi Arabia, unlike Iran, is a US ally?
These types of messages carry more weight when they're not too frequent; in the history of Rust we've posted three such messages. If we posted them too frequently they would lose impact. So we draw attention to things that have had recent developments/events, and where fresh attention seems like it may prove helpful. (See also https://news.ycombinator.com/item?id=33453262)
If we started posting about every terrible wrong in the world, we'd have multiple announcements per day, and they'd have zero impact.
Rust is an international project with participation from all over the world. Whether any particular country is allied with another has zero impact on the discussions that lead to these announcements.
Drawing attention has zero impact no matter how often or how rarely you do it. Unless the Rust team has privileged knowledge that they're releasing, or are directly acting in the interests of known individual contributors, donating any amount of money to a cause is worth far more than tens of thousands of people becoming informed that the world is slightly worse than it was yesterday.
Even if drawing attention was worth anything, I think you are assuming the wrong frequency - the Rust technical release notes may contain few calls to political action, but everyone reading them spends enough time online to be constantly bombarded with them.
No, it is not. Marketing is about making you want to buy something, and appeals to your materialism. Raising awareness is about making you Aware that something is happening, and appeals to your altruism. There is a heck of a lot more of the former, and the latter doesn't actually make you want to perform any specific action (if it results in action at all, frequently, the action is just sharing it again).
In other words, we bang our drum when we feel like it and really have no meaningful metrics or A/B measurements to gauge whether or not our announcement has made any actionable positive impact vs just irritating people who are solely interested in the technical release topic.
Some colleagues in Toronto were telling me about how there was a demonstration there last Saturday morning pertaining to this situation.
The demonstrators lined up along the sidewalk of one of the main streets, and were loudly chanting and screaming for a few hours. Others drove by and honked their vehicles' horns.
This was apparently done along stretches of the street with large residential complexes nearby, too.
Based on the bystanders, residents, and other people that my colleagues talked to, they seemed to think that this disruption likely alienated far more people than it attracted to support this particular cause.
> Based on the bystanders, residents, and other people that my colleagues talked to, they seemed to think that this disruption likely alienated far more people than it attracted to support this particular cause.
Same rhetoric used during the civil rights movement.
This whataboutism is pointless. It is not their duty to refer to each and every issue in the world. It is their right however to express the view for whatever they choose.
Why read further into it? They never said they don’t care about those other things. It is possible for humans to mention a specific cause without also negating all others.
Seriously, what is wrong with the logical reasoning of some people?
I could be wrong, but I think people get irked by shallow virtue signaling, especially when it's combined with superficial thoughts-and-prayers type of aid/advice, more than the the choice of political issues.
Although, I suppose recent political issues that everyone's already talking about, and a project tries to "raise awareness" reeks of a misguided virtue signaling PR stunt than when one talks about long-standing issues. Not saying this is the case here, though, as Rust is hardly something that needs PR.
I'm sure part of the reaction is that Twitter is full of this type of virtue signaling, and people have become allergic to it. I remember the whole "Yeah, this little master->main change will be a tectonic shift. Back pats all around! We did it people; we solved racism!" attitude that Twitter had during the main/master debate lol. Yes, make changes in what is probably the most progressive industry (since we nerds are generally more tolerant/progressive), like that's gonna make a difference in the morally decrepit police force, which the protests were about to begin with.
Anyway... I'm not sure what the word is, but I feel it's a next door neighbour to hypocrisy? And hypocrites annoying everyone.
Personally though, I think it's always good to talk about human rights or mental health issues! I'm not sure a paragraph everyone will skip is an adequate place for that, but it's a nice token effort, and it's somewhat commendable someone cared enough to put it in.
Anyway, this is all a bit incoherent, but I don't care enough to wordsmith the comment, only to share some of my opinions.
Ok, I belive they do on some superficial level. I mean, people virtue signal about things they care, otherwise they wouldn't be doing it. If they actually cared, why not try and do something meaningful about it[1]? When I cared about issues, I put effort into trying to change things a even on a meager/local scale. As a teen I volunteered at a library to teach children how to behave online. Later I helped refurbish a homelessness shelter in my home town. I've taught programming at an LGBT community centre.
Maybe I've done these for selfish reasons because they are things that personally affected my own past/development, and doing them made me feel good and significant. These are all small things, but at least I hope I've made a difference to a small number of people. So, in my books a tweet or a driveby paragraph in release notes doesn't really make a difference. Tell me, how did GitHub help make black people feel more comfortable on the streets of America? How did these release notes help people's rights in Iran?
[1]: Also, to be fair, I don't know who put that paragraph in. Maybe they did do meaningfully contribute (i.e. by setting up VPN networks or something), and maybe I'm being unnecessarily harsh. But in my limited experience, the people who preach the loudest do the least, but also herald of their preaches and coat themselves with efforts of others. Sadly
No, people do not "virtue signal" about things they care about. Perhaps they used to in the past, but language has moved on. The phrase is now understood to carry with it an accusation of insincerity. Therefore virtue signaling and actually caring are contradictory.
This is how language works. Usage is meaning. A change in usage is a change in meaning. Language doesn't care about your opinions on the matter, it simply is. The phrase "virtue signaling" now carries with it an accusation of insincerity. If you don't mean to level such an accusation, you're going to need to find a way to communicate what you do mean that isn't encumbered by connotations that have recently become standard.
Expressions of solidarity with the powerless can help them weather the storm: they buoy hope, they increase perceptions of connection and of agency. I have witnessed this repeatedly over decades, including at first hand in this very specific instance. If everyone kept quiet about everything they could not immediately, materially, "fix", the world would be a far more desolate place for many. I guess there's no particular obligation for you to care, but would it actually be such a privation for you to stoically weather your indignation about others doing so?
> Expressions of solidarity with the powerless can help them weather the storm: they buoy hope, they increase perceptions of connection and of agency
I agree that solidarity can help. But none of that's going on here... This pathetic attempt at shallow expression isn't going to reach the people who need it (or probably anyone in Iran for that matter, due to the Internet situation there).
> I guess there's no particular obligation for you to care, but would it actually be such a privation for you to stoically weather your indignation about others doing so?
This is degenerating into gaslighting and you trying to put words into my mouth, so I will let the thread rest. I guess I'm happy to agree to disagree on the effectiveness of online virtue signaling[1].
I'm not even judging these people that hard, I think. I'm just describing the response their shallow behaviour elicits in other people. I don't even get such a strong response myself, I just think it's worthless
[1] To avoid confusion I mean "pathetically shallow attempts at trying to make a difference to improve their colleagues perception of their (shallow) morals"; with malicious intent or without, the action is the same. But that concludes me playing online word/semantic lawyer
> This pathetic attempt at shallow expression isn't going to reach the people who need it
You have no idea. As I said, I have personal experience of this particular instance of what you stereotype, sans evidence, as 'virtual signalling', having a genuinely heartening effect on a friend whose nephew was killed recently in Iran. This is the trouble with you internet snarlers. You have so little knowledge of physical reality.
You call me an Internet snarler, but isn't what we're discussing Internet snarling? Anyway, I'm glad you have a friend who was touched by this and I'm sorry for your friend's loss.
Maybe because selectively caring about specific issues while ignoring others is a form of political bias. I know people love to shout whataboutism whenever someone points out legitimate hypocrisy rather than confront the hypocrisy.
Where’s the hypocrisy? You’re projecting that they don’t care about the other causes.
That’s your own fault not theirs.
Maybe they have some women on their team who are particularly moved by this event? Maybe they have some Iranian expats? Maybe they’re unaware of the extent of other issues? Maybe it doesn’t matter because again , saying one supports a specific cause doesn’t mean they don’t support others.
There is zero hypocrisy here. There are only logical fallacies from people reading too far into things.
> Maybe because selectively caring about specific issues while ignoring others is a form of political bias.
There's generally three options when it comes to politics; do nothing, do something, do everything.
The first does not help anyone, and the last; being impossible - is a path back to the first (via burn-out, apathy or simply inefficiency ("scope creep").
So the only real option is to do "something" - and champion a few causes.
Preventing some abuses can be worse than nothing. Imagine the following.
Your friend Adam hits Bob. You do nothing. Bob tries to hit back but you grab his arms so he can't. Adam hits Bob. You do nothing. Bob still can't hit back because you are preventing him.
Another possibility:
A Corp in which you are a stockholder is polluting the environment. You do nothing. B Inc pollutes the environment but not as much. You step in to stop them which causes B to lose out on a lot of profit. A Corp outcompetes B Inc. You become rich.
Do I think we are being overly harsh on Iran? No. Should we consider the possibility and try to avoid it? Yes. Should we be suspicious of other people that are biased in what they enforce? Yes.
I think it's clear these are really contrived examples built explicitly to prove an exception to the rule.
In the real world, doing something is typically better than doing nothing.
You are walking in the park and see a woman being dragged into a bush to be assaulted. Do you intervene? By doing so are you stopping all assaults against women? No, but invariably people would still say you've done more good by doing something than by doing nothing.
The protestors in Iran haven't hit Bob their government, you're not restraining an equally aggrieved party by backing them against their regime. They're if anything the long term victims of Bob's habitual violence and they're finally seeking to break free, not to hurt Bob, but to be free from being hurt themselves.
A child is starving to death in Sudan. Do you feed them or do nothing? Does feeding them feed all the children? Does feeding none of the children make the world a better place than feeding one? If you were that child, or their parents watching them die in their arms, would you hope people would step away from their completely detached hypotheticals and actually do something to save a life when they could?
When you listen to people who are pointing out that you are a hypocrite, you are platforming hateful abusers and possible Putin propagandists. Listening to negativity is platforming hate.
So now people that believe Saudi Arabia and other countries should be held accountable for human rights violations are Putin apologists? What does this have to do with Iran specifically?
It would be nice to not have politics permeate every aspect of our lives. Just to give people room to breathe. Everyone knows about whats happening in Iran already. There was no real benefit to making a declaration here via a rust release. Best keep these things for social media.
> There was no real benefit to making a declaration here via a rust release
Some people do think human solidarity, outside of stereotypically 'political' contexts, is a benefit in itself. I know many Iranians (accident of history - my mother adopted 2 Iranian refugees when I was in my teens). I showed this to one friend, who heard last week a 20 year old nephew of hers had been gunned down by the IRGC. She burst into tears and hugged me and told me how much this kind of expression kept hope alive.
Politics is physical reality, which tends to mug those who prefer to look away. If it mugs you merely via a sentence you prefer not to read, rather than a bullet or hammer, I suspect you can probably cope.
As a Rust team member, I have no earthly clue. Maybe it's the Core team? Or the blog author? Or the release team? Also no clue whatsoever as to the process for determining which cause to promote or even which causes are not allowed to be promoted (if any?). So now I'm curious... Let's look.
I believe the only publicly available output of this team has been whatever has been published to the Inside Rust blog. If you read the blog post I linked in my previous comment (their most recent one), it outlines their plans.
For full disclosure, this leadership chat was created in the fallout of the mod team resigning (of which I was a member). And I think it's a good thing, because it's getting a bunch of people talking that weren't talking before. And, as the blog post outlined, they're working towards producing an RFC to revamp part of Rust governance. Which... I think is needed.
It's just that... they are also making other decisions now. Whether that's beyond their mandate or not, I don't know. But it's certainly continuing the tradition of the Core Team, which started doing this a couple years ago. And whether they were within their mandate to do such things is also not clear to me.
To me it means that at least one person involved with developing Rust cares about this. I think skipping past it I am not personal interested is a small sacrifice for me to make, considering that I get a new Rust version for free.
I never saw Rust as political. It's maybe socially progressive in the sense that it's community shuns abusive behaviour towards minorities, but every community should strive for that, IMO.
Also, while I agree there are some horrible people who were associated with the CoC movement early on, I think it's unfair to judge the whole idea/project by those people. Also, I'm aware there are some poor CoCs that maintainers abuse, but that's true of any system!
Also, there's nothing wrong with being either leftist or rightist, as long as both sides can have a civil conversation!
And there's nothing wrong with empowerment! As an example, you're clearly confident enough to be able to voice your opinions, but some people still aren't, and some who are now but weren't before were empowered to be more confident. So there's nothing wrong with empowering people.
While GATs are undeniably cool, I think I'm actually most excited by the enabling of MIR inlining. Rust level optimizations have a real potential to increase performance and decrease compilation times, and inlining is one of the most important primitives for that.
Rust level optimizations sound promising. I could not find a good high level explanation what inlining means in this context and how it facilitates Rust level optimizations.
I think inlining is function inlining, which is an optimisation that lots of compilers do. The change here is to move (some of) that earlier in the compilation process (in the "middle end" of the Rust compiler rather than in the LLVM backend), which can make things more efficient by reducing the total amount of work that needs to be done.
The reason it's so important is that inlining synergises with other optimizations, its often run before or after other passes like constant propagation. Consider something like:
fn add(x : usize, y : usize) -> usize { x + y }
fn main() {
add(5, 1)
}
Without inlining we can't easily optimize the code of `main`. However, if we inline `add` into main, constant propagation will then directly see `5 + 1` and optimize that into `6`.
Is there anything we can do to bring an order of magnitude of improvement to compilation time? I know incremental compilation is by crate, how about by file like C and C++ do?
Incremental compilation is already even more fine-grained than by file- it is based on rustc's internal query system.
There is room to improve parallelization, though. Cargo will parallelize invocations of rustc (by crate) and rustc will parallelize backend code generation (functions in a crate are load balanced automatically) but the frontend is still not parallel.
IMO Arrays implementing IntoIterator was significant because it means there isn't a weird special case to teach newcomers about, and because it requires a hack to make it work (in older Editions the fact Arrays are IntoIterator is hidden during method resolution to prevent old code from breaking).
For context: I started out a passionate and evangelical Python "duck typing" proponent. Eventually migrated to Node, as it let me in the browser via JS (i'm fond of web tech). Eventually Go caught my eye due to types (before Typescript really existed) and so i stayed there for a while. Each of these lasted ~5 years.
These days i'm a heavy and solely Rust user.. going on ~3 years now iirc. Both in my work life, and home life.
The more experience i got in my career the more i loved types, so Rust's type system wasn't a shock to me. Yes, it was the most in depth typing i had used, but for me it was a natural transition. I was wanting types to solve problems for me. Rust felt very natural in that sense.
I advocate that Rust can be easy to learn if you focus on your bite sizes. Learn Rust with a keen eye for what looks like big and small bytes, and never exceed your mouth size. In the beginning lifetimes are scary, so avoid them - clone or `Arc` like mad. Be wary of heavy generic usage. Rust has lots of rope to hand yourself with, should you go looking for a noose.
I can’t really speak to the market right now, but I transitioned to Rust from Python and Typescript in April of 2021. I started learning Rust in I think 2018. I had a couple of decently sized Rust open source projects under my belt, one of which I had managed to get some time to work on at $previous_job, since we integrated it into our react client via WASM. The company I joined is working on HTTP network proxy stuff in relation to fraud prevention.
I didn’t have any professional experience in low level languages. I had some hobby/school experience with C and C++, but nothing recent.
Learning rust was not too bad. Took me a couple of tries to get going, but once I got the basics down, expanding from there was pretty straightforward.
At the time I was looking for a job, a solid majority of Rust jobs were in cryptocurrency or adjacent companies. I wasn’t interested in that, but I still found plenty of places to apply to. I got responses from almost all of them, and was able to pick between my top choices. My understanding is that now there are many more non-crypto jobs than there were, although I don’t know to what extent that has been affected by recent economic conditions.
I'm not fully celebrating GATs yet due to all the limitations mentioned in the linked stabilization blog post. [1] I'll be ecstatic if and when I can write a std::iter::Iterator impl that borrows from itself. Fingers crossed that can happen. And I'll be watching to see what libraries implement based on this MVP.
I'm celebrating other things in this release. let else will be great for ergonomics. Stable backtraces in std, split debuginfo on Linux, and const offset_from all address pain points for me. (Backtraces will be more useful though when the provider API lands. Then I think we'll be able to have really great error chains. Right now, there's no obvious way to go from a &dyn std::error::Error to a backtrace without guessing the concrete error type and downcasting, and the same problem applies to other forms of context I'd love to have.)
Here's a collection of comments from the same PR from users arguing for stabilization:
"I work on chumsky, a parser combinator crate. I've recently been experimenting with GATs internally as a way to control exactly what code Rust generates. Instead of praying to the LLVM gods that the compiler might optimise things, I use a GAT to project a particular parsing 'strategy' into the implementation of parsers. I've found that I can significantly improve the performance of the library by an order of magnitude, even beating out hand-written parsers, nom, and serde_json (with several caveats) without harming the library's expressivity (and, in fact, improving it). This all happens without the GATs themselves being exposed to library users at all."
"The first time I realized the Iterator trait was insufficient for what I wanted was before Rust 1.0 in 2014 when I wrote one of the first versions of the csv crate. All I wanted to do was write an iterator that lent out a borrow of an internal buffer in order to avoid allocating a new record on each iteration."
"I've been using GATs on nightly for a little less than a year for various experimental proc-macro crates. I can only say that GATs simplify a lot of things for me! I'm not doing things like LendingIterator, my interest is more in "DSL"s. Things like e.g. generate a struct that temporarily stores all the parameters to some function (where some of those parameters will be non-static references). The main concern will often be how much code can I avoid autogenerating i.e. is it possible to write abstractions as libraries over these things. GATs allow me to do that with ease. [...] The one I'm currently working on is unimock. The GAT stuff is only in the gat-mock branch, not released on crates.io yet. That GATified trait is MockFn."
"There is no way to use async traits in an embedded context (no_std) without GAT's or pulling in the alloc crate (to use async-trait). Pulling in alloc for most embedded platforms is not feasible, therefore we are currently locked to nightly for the embedded-hal-async crate."
"Issue #95 on the RustAudio crate for example says, "The first [solution] would be to make PortType generic over a 'a lifetime...however, this has a cascading effect, which would force all downstream users of port types to specify their lifetimes". Pythonesque made a simpler point here, "Without GATs, I ended up having to make an Hkt trait that had to be implemented for every type, define its projections, and then make everything heavily parametric and generic over the various conversions.""
Doesn't rust feel a bit too heavy weight?
It feels like the language packs too much firepower, can there be downsides to that?
C long life seems to be, in part, because of its simplicity.
Most of the new development is not about adding new features but about removing limitations and making existing features more orthogonal. GATs technically aren't introducing a new thing. They just allow to use the already existing generic syntax on more things. Similar thing with allowing impl Trait in more places and async traits.
> As the final step of the RLS deprecation, this release has replaced RLS with a small LSP server showing a deprecation warning, advising users to migrate to rust-analyzer.
RLS is no longer deprecated, but removed. “Deprecation warning” means “FYI, you shouldn’t be using this, but it’ll still work for now”. This is an obsolescence notification, not a deprecation warning.
I fear we’re losing the fight for the meaning of the word “deprecate”. Yet we have no other word or even phrase to convey what it has historically meant.
They’re often similar, but there are very important differences. (And I led with the word “removed” rather than “obsoleted” for a reason; perchance it was unwise to use the term obsolescence at all.)
Obsolescence is ambiguous. In common usage it means a thing is not maintained and will generally become harder and harder to use due to the lack of maintenance and support, so that at some point it will probably stop working and be unfixable. But especially in the software field it has long also been used to indicate things that actively don’t work any more because they’ve been replaced by something else. In short, “obsolete” already serves as what people are ruining “deprecated” to mean: maybe it works, maybe it doesn’t, but sooner or later it won’t work.
Deprecation, however, must not signify removal. It is purely a form of discouragement of something that still works, at least for now. See https://en.wikipedia.org/wiki/Deprecation.
Error checking; golang's error handling arguably reverses the happy/sad paths of code syntactically, and some users don't like reading things error-first.
Rust is getting as bloated as C++, only bored developers that entertain themselves by more and more syntactic sugar or looking smart, instead of actually writing software, will be glad of this versionitis of programming languages.
This release stabilises Generic Associated Types (GATs), a limited form of Higher Kinded Types. This is only an MVP release, but it already includes enough to be useful, and has been a huge multi-year effort (the RFC for the feature dates to April 2016).
Novice users of Rust probably won't use this feature directly, but it gives a lot more power to library authors to write more flexible APIs while still keeping all of Rust's strict correctness guardrails (i.e. exposing a safe API). It will also form the basis of the upcoming "async functions in traits" feature.
This is probably the most significant Rust release in the last couple of years.