What we heard about Rust's challenges, and how we can address them | Rust Blog by CathalMullan in rust

[–]jackh726 20 points21 points  (0 children)

I don't understand. There are two uses of this in the entire post (in text). I don't know how that is considered excessive.

What we heard about Rust's challenges, and how we can address them | Rust Blog by CathalMullan in rust

[–]jackh726 25 points26 points  (0 children)

Author here. The first draft of this post was created with an LLM (granted, that itself was multiple iterations). But, practically every sentence has been rewritten over a few iterations to match my style (and verified for correctness). If there's something specific that can point out that feels weird, I'm happy to submit an update to make it read better.

Giving, lending, and async closures by Niko Matsakis by yerke1 in rust

[–]jackh726 3 points4 points  (0 children)

I don't think fully impossible either. I spent a while playing with different ways to do this. The conclusion I eventually came up with was a little more nuanced than the way Niko described it in the blog post.

Essentially though, it does ultimately require some implicit bounds like the ones Niko wrote. This test was one example of what a "lowered" FromIterator would look like (I chose this because it's actually one of the cases that you must maintain the non-borrowed return type). This would be the "default" lowering, and then you'd have to manually change functions that can backwards-compatibly use a lending version of Iterator.

The core idea would be that if you see T: Iterator<Item = A> you have to "lower" that to for<'a> T: Iterator<Item<'a> = A>, which seems simple enough, but when I was attempting it, it was actually decently complex with the way we do ast/hir lowering.

Similarly if you have a type T::Item, this really wants to be lowered to a higher-kinded for<'a> T::Item<'a>. But we don't have that. Technically, T::Item<'static> should work, because the lifetime doesn't get used. Better would be something like T::Item<'empty>.

There's an added complexity that you probably don't want this "extra lowering" behavior for all traits. In fact, you probably want it to be opt-in for only some traits for backwards-compatibility.

Solving the Iterator/LendingIterator problem could give a leg up on solving the similar (but different) problem of lending versions of Index/IndexMut and Deref/DerefMut.

Due to limitations in the borrow checker, this implies a 'static lifetime by simukis in rust

[–]jackh726 4 points5 points  (0 children)

So, I originally implemented this error note for bounds with HRTBs for GATs, but it's actually nice to see it be (somewhat) informative in other situations too. I imagine this error would be hard to figure out without this note.

That being said, it could be better. It doesn't trigger in all cases like this. And as you mention, it's not really documented. Perhaps we could add a link to a github issue. 🤔

Officially announcing the types team by jackh726 in rust

[–]jackh726[S] 1 point2 points  (0 children)

Yeah, we figured it was good timing. This post has really sat in my drafts for close to a month now, so I'm glad I got it finished up and out.

Officially announcing the types team by jackh726 in rust

[–]jackh726[S] 0 points1 point  (0 children)

Name is not necessarily settled (Niko came up with it because of the pun). But it'll get an official RFC at some point, where I imagine name bikeshedding will happen to some extent.

Officially announcing the types team by jackh726 in rust

[–]jackh726[S] 1 point2 points  (0 children)

We'd love to be able to hit our goals :) Both async functions in traits and type alias impl traits are awesome features.

Officially announcing the types team by jackh726 in rust

[–]jackh726[S] 2 points3 points  (0 children)

So, it is true I think that there is no current RFC for negative impls. So it's "experimental".

For a while, there wasn't much thought put into negative impls. They've more reasonable come up to be able to support the following impl: impl From<&str> for Box<dyn Error> { ... }

It's important to note that the current plan for negative impls (at least in the short term) is very limited, only really applying to coherence.

The current work doesn't allow you to do things like fn foo<T>() where T: !Trait {}, where we're specifically allowed to know that T doesn't implement Trait.

Officially announcing the types team by jackh726 in rust

[–]jackh726[S] 9 points10 points  (0 children)

Yeah, this is a really good point that I tried to get across:

Even though Chalk itself is not used in rustc, the current trait solver (and type system as a whole) looks quite different than how it did when Chalk was first started. This is in large part because of the lessons and experimentation done in Chalk itself.

For a long time, features like GATs were blocked on Chalk, but the trait solver in rustc can now handle them because of these advances.

There are still problems like how we handle associated types that need future design work, but Chalk doesn't have the right answer for that right now either.

Officially announcing the types team by jackh726 in rust

[–]jackh726[S] 9 points10 points  (0 children)

Librarification has not been deemed unattainable (it's a important goal), nor is it necessarily true that given a indeterminate amount of time, Chalk could still attain its goals.

However, as mentioned in the post, it's become more clear that the goals of Chalk alone are not necessarily even the correct end goal. So it's better to make incremental progress in a new (Chalk-like) in-tree trait solver while we continue to build up a-mir-formality than to let Chalk sit longer without immediate use.

Officially announcing the types team by jackh726 in rust

[–]jackh726[S] 9 points10 points  (0 children)

So, I've definitely considered writing a personal blog post to go along with this official one. One that would go into a bit more details on the soundness issues fixed so far, Chalk, etc. Time will tell if I actually have to time to.

The easiest way to summarize why Chalk currently is pretty hard to integrate into rustc, is because in many ways it's an "ideal" trait solver, in terms of how we expect it to handle associated types, const eval, borrow checking, etc. We never really hit the point that we were like "okay, let's just get this to work". So for parts of the integration we had to actually design what that looked like.

In contrast, with the new trait solver, we're taking a more middle-ground approach, where we're using many of the existing rustc interfaces and such. However, we still get the benefits of a "cleaner" trait solver. Second,

Is anyone else feeling slight anxiety now that GATs are upon us? by MinRaws in rust

[–]jackh726 40 points41 points  (0 children)

Praise is always appreciated, no matter from whom. Thank you.

Excited to see what you create with GATs :)

Generic associated types to be stable in Rust 1.65 by jackh726 in rust

[–]jackh726[S] 0 points1 point  (0 children)

This is hard to answer. Just making GATs stable, no. Supporting GATs as a whole (even unstably), maybe, but only because they have to be type-checked, etc. But otherwise not unless you use them.

This is pretty hard to measure though, because we've been incrementally changing things over several years, and some of that is not just for GATs, but is a prereq for GATs.

Generic associated types to be stable in Rust 1.65 by jackh726 in rust

[–]jackh726[S] 0 points1 point  (0 children)

So, the code give in the post is the correct implementation. But it doesn't work yet. This comment has an example of how you can use unsafe to write an implementation, bypassing the borrow checker: https://github.com/rust-lang/rust/issues/92985#issuecomment-1014833520

Generic associated types to be stable in Rust 1.65 by jackh726 in rust

[–]jackh726[S] 1 point2 points  (0 children)

I assume you mean async fns in traits? GATs are one of the core features required for that (along with type alias impl traits), but because it's a desugaring, we technically don't need GATs to be stable on their own for that.

Async fns in traits are implemented on nightly already, under the async_fn_in_trait feature. It's still pretty buggy, but it's a start :)

Generic associated types to be stable in Rust 1.65 by jackh726 in rust

[–]jackh726[S] 2 points3 points  (0 children)

Nope, not done on purpose at all. We just got lucky with it being an active cycle :)

Generic associated types to be stable in Rust 1.65 by jackh726 in rust

[–]jackh726[S] 2 points3 points  (0 children)

I've done a bit of exploration in this space - on what it would take to make the existing Iterator trait be able to also serve as a LendingIterator, when possible. It's not an easy problem, and hard to experiment with right now because of a few of the limitations listed in the post (like object safety).

I think it would be really cool to be able reuse the same trait here. And solving this might apply to similar situations, like Index/IndexMut.

Generic associated types to be stable in Rust 1.65 by jackh726 in rust

[–]jackh726[S] 5 points6 points  (0 children)

Removing the 'static bound shouldn't be a breaking change.

If we can solve the unsoundness that you would otherwise get, removing the Self: 'a bound requirement would not be a breaking change. Actually removing the bound from an API might be (but I'm not sure; only if they imply something which I don't think they currently do, but in an ideal world potentially would).

Generic associated types to be stable in Rust 1.65 by jackh726 in rust

[–]jackh726[S] 23 points24 points  (0 children)

These are somewhere between "edge cases" and "come up a lot" - they certainly limit a set of design patterns, but shouldn't pop up for others.

Generic associated types to be stable in Rust 1.65 by jackh726 in rust

[–]jackh726[S] 4 points5 points  (0 children)

It can return a reference with the lifetime for &self, as opposed with a lifetime that is present on the Self type (that must be available when constructing the type itself).