- Servo hi-pri/blockers (larsberg) servo/servo#2853
- cross-borrowing/borrow operator RFCs (nrc)
- RFC: Collections reform (aturon) rust-lang/rfcs#235
- RFC: Error conventions take 3 (aturon) rust-lang/rfcs#236
- RFC: Namespacing enums (aturon) rust-lang/rfcs#390
- RFC: Numerics reform (aturon) rust-lang/rfcs#369
- failing in dtors (nrc) - rust-lang/rust#14875
- RFC: &'static [u8, ..N] for byte literals (acrichto) rust-lang/rfcs#339
- RFC: Cargo build cmd + -l for rustc (acrichto) rust-lang/rfcs#403
- RFC: linkage tweaks (acrichto) rust-lang/rfcs#404
- RFC: un-feature-gate struct_variant (acrichto) rust-lang/rfcs#418
- RFC: macro invocations, ()/[] implies expr (pnkfelix): rust-lang/rfcs#378
- RFC:
pub
marker on (public) trait items (pnkfelix): rust-lang/rfcs#227- see also private trait items RFC: rust-lang/rfcs#52 for motivation
- RFC: type conversions (nrc): rust-lang/rfcs#401
acrichto, brson, nrc, steveklabnik, larsberg, pnkfelix, aturon, azita, pcwalton, nmatsakis
- brson: feature staging rfc, hr stuff, release automation, feature staging patch, combined install, reviews
- acrichto: crates.io styling, bugs, cargo integration, cargo bugs, RFCs to land!
- nrc: trait impls (turned out to be annoying), random bugs
- aturon: blog and RFC writing, API work, rtio removal
- pnkfelix: box prototype RFC, dtor semantics (8861); PTO
- acrichto merge rust-lang/rfcs#235
- nrc close rust-lang/rfcs#226
- nrc close rust-lang/rfcs#248
- larsberg: acrichto fixed cargo issues. don't have anything to upgrade rust for currently!
- pcwalton: bitflags aren't inlined in our build
- larsberg: I can take it
- aturon: Part of a series of RFCs where an area of the libraries needed more significant work ( not just renam/deprecate). This is a comprehensive look at libcollections for conventions, etc. Highlights include: removing all of the current collection traits (5-6 of them) for length, mutable sequence, etc. Nobody's happy with the design of these, and the feeling is that the traits we'd ultimately like can't be expressed without HKT. In general, we feel like for 1.0 it's not so important to support generic programming, though concrete ones are. So, we'll drop the traits, but standardize the APIs across the collections so that we can introduce the traits later. Other major components include soving the 'equiv' problem in HashMap. Issue is that it's common to use one with string keys, but it means that when you do a lookup, it's looking for an &String (instead of string slices). No good story for how to write containers that work over slices. This RFC proposes a multidispatch-based approach, that basically lets you borrow a string as an &String or an &str string slice-type, which makes it more natural. Lots of good stuff, like getting rid of MaybeOwned. Other other major thing is that people have been looking for an Iterable trait, and this RFC makes us forward compatible with it. We don't have HKT, so we can't do the full thing, but we can do IntoIterator, though. One of the contentious issues is that IntoIterator tells you how to consume a data structure into an interator, and it makes sense to apply to a refernce (so it would work on vec or &vec). But, it's a bit subtle, because the kind of iterator you get depends on if you owned the vec or borrowed it. In particular:
for x in v.iter() //instead of...
for x in &v // can write
for x in v.into_iter() // instead of...
for x in v // this
- aturon: This syntax for
for
loops is not a breaking change. The last part is contentious because it's a bit subtle. The other is that it reverses the defaults. Right now, with the iterator methods, the shortest-named one gives you borrowed data, but the new thing does a move instead. Since that might encourage cloneing, that's dangerous. Final part on the for loop business is that it's something we could add later, backwards-compatibly. However, I think this is connected to Deref coersions... But, we could split this RFC and talk about for loops later. - brson: This is an epic RFC and really well-done!
- steveklabnik: I've seen other people outside the Rust community impressed by the quality of our RFCs, like this one.
- nrc: What was the motivation for the controversial bits?
- aturon: Two pieces. One is introducing IntoIterator at all. In general, we want to reduce the number of specialized convenience methods to instead work with iterators. There are methods today that are specialized instead of through iterators. So, having IntoIterator, we can build composable APIs. And it's a building block for Iterable later on. This part is not too controversial. The next step, though, is that it makes sense to make for loops general in the same way. Partially for ergonomic reasons, but also for consistency reasons. That particular piece also hooks into the Deref coercions later.
- nrc: My initial reaction to this is that it's so subtle that it will be confusing. It's sort of like when you use
.
and have all these auto coercions. - aturon: If you get it wrong, you'll get a borrowchk error (e.g., if you consume instead of borrowing). The question is: how do you react? Will you just add .clone()?
- brson: Maybe a lint could give a good hint?
- nmatsakis: This is also a more general thing.
- larsberg: We have lots of cases where we have stupid clones in Servo, especially because of the default suggestion in the error message.
- pcwalton: Could just have an error if you are calling clone() on something that's the last use of it...
- aturon: Since for is central, we could also reasonably special-case it. The best argument from my side is that it consolidates the ownership/borrowing concepts in Rust.
- brson: I'm wondering if you would expect this change to provoke people to use moving iterators or still expect borrowed iterators to be the common case?
- aturon: Borrowed, by far. It's intereating because it's one of the few places in Rust where we do borrowing by default - elsewhere we do moves. People are surprised because most of the time you work with references, but moving is usually the right default.
- nrc: Would there be a difference in behavior between a for loop over &vec and vec.as_slice()?
- aturon: That would be the same.
- nrc: Good
- aturon: you could also write
&mut vec
and you'd be iterating over mutable references. - pnkfelix: I don't have a disagreement, but you might want to land the for loop changes separately or later?
- brson: I agree. Maybe split this out just to get it more visibility?
- aturon: Yes, it's such a big RFC that it's easy to miss this point...
- nmatsakis: It was not missed. It was discussed a fair amount. Staging landing it in the compiler is one thing, but if the issue is that we haven't gotten enough feedback on the for loop part?
- brson: There's so much here, you just might as well chunk it into more units of work.
- nmatsakis: yes, definitely chunk up the actual work. But chunking up the RFC creates extra work. If we decide not to implement this right away, it's not like the decision is set in stone.
- aturon: Another downside I forgot to mention is that there are some situations where you might want to work with the iterator you're looping over (so when you're inside the for loop, bump it along), this wouldn't work. It doesn't work today anyway because the borrowchk doesn't support it anyway...
- nmatsakis: Could use
ref
, maybe? Hrm. Seems minor, regardless. - aturon: Can always work around with an explicit loop. Anyway, I have no objection to considering the
for
part later... - nrc: I'm convinced that the whole thing should be +1
- brson: I agree.
- nmatsakis: Yes. This is a coherent vision and it appeals to me.
- brson: acrichto, merge it?
-
nrc: Cross-borrowing is what we had in an ad-hoc way to go from Box or Gc to &T. Removed it because it was ad-hoc and a bit weird that it was just for the builtins. The downside is that now we have a bunch of places where you have &* or &**, which is bad because it's line noise. People just play "type tetris" until it compiles. My initial proposal was #226, which would let anywhere that you have a custom Deref impl, it would work as well. Therefore, it would work for all smart pointer implementations. Similar to what we had before, but for all smart pointers. Downside is that they're implicit coercions and doesn't support substitutability. You can't subst the start (&*blah with blah) because it doesn't respect the borrowchk because it adds a borrow. So, it doesn't respect the statics. Aturon proposed #241, so the cross-borrow coercions are prevented by ensuring it only works for borrowed values. So if you start with &Box you can get &T. And if you have a Box then rather than writing &*blah, you can just write &blah and get a reference to the thing inside the Box instead of just a ref to the Box itself. This approach is better because it respects substitutability. Downside is that it's a bit less predictable than the original proposal because it drills through types to find a conversion that gives you something that's compatible instead of just doing it once.
-
nrc: So, #248 was born! It repurposes & to be a borrow operator rather than address-of. Has the same results as aturon's proposal (so &blah for a Box gives you an &T). I gathered a bunch of statistics, and that's usually what you want.
-
brson: Can you point out the data in that gist that supports that point?
-
pnkfelix: I blame larsberg for writing bad meeting minutes that don't support that data...
-
nrc: Third table down! So, if you apply the address-of operators in the third one and compare it to the total number of those operators, it shows the total number of times you actually wanted to get &Box instead of &T.
-
brson: So you almost always want to deref all the way?
-
nrc: These cases are when you take an address-of at all, so it also compares when you do an &*. Total of about 3000 in the Rust compiler as opposed to 800 where you go after the Box. Probably not going to make a decision today...
-
larsberg: have you talked to josh at all? we do some things with pointers to js objects
-
larsberg: I know they were going to do some things with borrow ref to smart pointer to avoid repinning
-
nrc: I'll double-check with zwarich
-
aturon: Can we talk about whether this is something that fits into the 1.0 timeframe before we discuss it more?
-
nrc: If we change the way & works, it has to be pre-1.0. Definitely breaking! If we just want to add the coercions, it could be post-1.0. We have said that post-1.0 we might have a stripping-back phase where we work on ergonomics before we release. The first proposal is easy to implement. The second was not hard and is a win.
-
aturon: right, so 248 is not back-compat, so we do need to make a decision about the direction, at the least. nrc is emphasizing the substitutability principle, which is good. There is another way of comparing the proposal, which is the way that they maintain ownership. In 226, you can write something (like a Box as a parameter), which looks like it's being moved, but where it will actually be borrowed. That already happens with macros and of course with method receivers, but we've tried to keep it isolated. Usually, you can look at the callsite and know what's going on with ownership. For me, personally, that makes 226 a non-starter, since you lose that property. Then the main difference is the extra ampersand between 226 and 241. With nrc's second proposal, I think the idea is that when you write & you immediately deref all the way, and there's a second operator you can use if you want to not do that.
-
nrc: Not an operator; a trait with a different function.
foo.address_of()
instead of a separate operator. -
brson: So for those 700 cases in the compiler change to the method?
-
nrc: yes.
-
aturon: If you have a value and implement deref, you know what you will have in any context. With the coercion rules, what happens depends on what you wrote and the signature of the thing you're calling. That may be less predictable. It's a fair tradeoff, but in terms of what this means practically, with the proposals you can usually use & and the right thing will happen (it covers both address-of and deref). Since it's also using the receiver-side information. If the main motivation is ergonomics and the predictability downside doesn't worry me too much... you generally know when you're working with a smart pointer, and you generally know what the argument is expecting. I guess to me ownership is the main thing, and if the compiler is figuring out how many layers to strip off, that's fine.
-
aturon: One part of the collections rfc was to make vectors deref into slices. Because if you have that and combine it with these coercion proposals, you have a good story for passing in a slice as an argument. If you have a vector v and want to pass it in as a slice, you can just do &v. Or if you have a reference, you can just pass it and it will be converted. So, I'd argue that if we're going to do one, we should do MINE! :-)
-
nrc: Maybe too much weight on the flexibility side there? With the borrow operator proposal, in almost all situations you have the same thing. If you want a borrowed thing, you just write &. If you already have an &T and write & to that, you still just have an &T at the end of it.
-
pnkfelix: What about the vector example?
-
nrc: The places where there are a difference are related to the vector. If we assume we have vecs derefing to slice, then we have the same behavior in the two proposals in that if you have a vector v and write &v, you will have a slice in my proposal and aturon's. If you desire a slice, that is.
-
aturon: Under which of your proposals?
-
nrc: 248. The two places it makes a difference in 241 and 248 is if you want is not maximally derefed. If you have a method that take an &Rc, then 241 has a flexibility advantage, whereas 248 gives you the slice by default or a reference to what's in the Rc. My belief is that these situations are rare. The other place where aturon's thing is more flexible is if you have a ref to the smart pointer or vec already, you don't need to do any operations at all if you want a ref to the thing inside. In mine, you need to borrow it out. I suspect these situations are rare. I think the ergonomic burden of an extra & seems reasonable when the borrowed-ness does not match already.
-
pcwalton: I think having a borrowed reference to an owning thing is common.
-
aturon: Comes up when you have a vector of vectors. Get a slice to the outer, and you'll have an owned vector... happens when you have enclosed types.
-
nmatsakis: From a timeline point of view, we cannot do 248. Changing the semantics of & is just not in the cards. It's a major change. I also have a lot of concerns, though I see the appeal. I like the lend notion, but I think it introduces inconsistencies, like that ref bindings work differently. Or you can't call a method in a pattern binding, so ref bindings to have it. These things rely on autoref having this behavior. Also, from the data, it's not clear there's supporting data for this change (800/3000 is not that small). Other is that with the interaction with vec, it may be that you rarely want an &vec, but it's not the case that you rarely want an &mut vec - that's much more common! So, &mut vec would do the wrong thing. Anyway, I think this is appealing, but it's not a slam-dunk and there isn't a lot of time.
-
steveklabnik: I haven't figured out why yet, but I feel weird about this change to the borrow operator. I suspect that there will be negative reactions.
-
nrc: The feedback on the RFC was definitely extreme in the two separate camps.
-
nmatsakis: I think aturon said most of what I wanted to say to the other two. When we had the older, more limited cross-borrowing rules, I found it confusing occasionally (in particular that T and Box did not work the same). Lots of semantic surprises. It was not an uncommon complaint at the time.
-
aturon: Be nice to have some resolution here. If we're ruled out 248, the others are backwards compatible. nrc makes a good point that ergonomics are important for 1.0! rustc uses smart pointers more than most rust code - cross-borrowing is much less common outside of the compiler. More pressing has been having to write .as_slice. We have a solution to that with slice notation, though it's not as nice as these proposals. But if we ended up with two ways to get a slice at the end, it's not the end of the world. Maybe this is a nice to have, but the main ergonomic problem has been dealt with. I'd be OK with postponing these RFCs. Or we could approve it and make it not a milestone goal.
-
brson: I'm wary of rushing this in at the last minute...
-
steveklabnik: I was assuming everything is landing behind a feature gate.
-
nmatsakis: Yes. I think we would gate this until we are sure or remove it.
-
brson: I feel uncomfortable pushing this through today. I'd like to let it bake another week.
-
nrc: I can close 226 - it's inferior to 241. Perhaps it's worth having another stab at 241 to see if we can make it more predictable? And if we don't have time, we can close 248, since we can't do it post-1.0. Does that seem reasonable?
-
aturon: Sounds good to me
-
nrc: Will close 226 and 248. I will sit on 241 for a while.
-
brson: We have a huge backlog. Do we need make-up meetings? Or next week?
-
acrichto: Some have been on for a few weeks. We should make up.
-
aturon: Maybe Thursday triage old ones instead of new ones?
-
nrc: I think adding issues on the RFC repo has been great, as it's reduced the number of new RFCs to triage.
-
brson: Great!