- Servo hi-pri/blockers (larsberg) servo/servo#2853
- RFC: Numerics reform (aturon) rust-lang/rfcs#369
- kmc's thoughts on macros/1.0 (aturon) https://gist.github.com/kmcallister/96668f02200cdb81e33e
- 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: std::fmt stabilization (acrichto) rust-lang/rfcs#380
- HRTB (nmatsakis) -- rust-lang/rfcs#387
- multiple lifetime bounds (nmatsakis) rust-lang/rfcs#242
- Out-of-sync nightlies (wycats)
huon, pnkfelix, nmatsakis, acrichto, kmc, brson, aturon, nrc, wycats, dherman, pcwalton
- pnkfelix: strict lifetime rules for drop (#8861, #16154)
- brson: automation
- aturon: RFCs: cmp/ops, Show, API evolution; stabilization: iter, str, ascii. more I/O work.
- acrichto: crates.io/heroku, collections reform, stability & local crates, bots bots bots
- nrc: coercions implementation, thinking about macros, == where clauses
- pcwalton: Servo work week, opt-in built-in traits
- nmatsakis: HRBT, operator dispatch, various pulls
- acrichto: merge rust-lang/rfcs#242
- pnkfelix merge rust-lang/rfcs#378
- brson merge rust-lang/rfcs#387
- acrichto: work with and merge rust-lang/rfcs#418
- brson: merge rust-lang/rfcs#369
https://gist.github.com/kmcallister/96668f02200cdb81e33e
- brson: we've decided to stabilize macros for 1.0. We want to see how we can improve things before the release. kmc has a lot of ideas (see above). We also want to make sure there's an "owner" for this topic
- kmc: There's a little writeup, the link above. I've done a lot of Rust macro programming in the last months. There are two issues.
- kmc: One is naming issues. You define a macro within your crate, and when you try to use it in another crates the names may not map correctly. There are a lot of hacks to work around this.
- kmc: But a simple way to work around this is my $crate idea. It expands to the name of the crate the macro was imported from, or nothing if it was defined locally.
- kmc: I've been able to use this to redefine a lot of the macros in core/std on a branch. I don't see a big downside with this approach.
- kmc: The other pain point is import/export namespacing. Right now, there's no namespacing. There are some hacky ways to control when they appear in the namespace.
- kmc: I propose, since we want to avoid major overhauls, that macros should be crate scoped. On a per module basis, you decide which macros to actually bring into the scope.
- kmc: I think that won't be too hard to implement.
- kmc: Right now, two libraries can define macros with the same name and there's no ways to deal with it. Crate scope can deal with that.
- kmc: Also, it will allow us to get rid of the phase attribute for macros. Then we can drop #[phase(plugin)] which is feature-gated.
- kmc: Those changes are pretty targeted. The $crate thing already works (modulo rebase). I think those two together would go a long way toward making macros more usable for 1.0
- nmatsakis: I'm not sure what the 2nd point means, and in particular, how you can do it without syntax. Is this going to be a new RFC?
- kmc: I can write RFCs, just wanted to get the high-level idea discussed.
- kmc: I want to have a kind of "use" for macros, but not via the "real" use (because that would require a lot of work in resolve).
- nmatsakis: "Macros are crate scoped" means that whereever you define them, they have a simle name.
- kmc: Could be an item macro like use!, could be an attribute. You'd also be able to rename the macros on import, which should be straightforward.
- nmatsakis: When you link against a crate, it brings those names into scope?
- kmc: No; it means that you can use them via a "macro use" statement
- nmatsakis: It bring them into your crate's namespace/macro list?
- kmc: Yes. Which is now per-crate, rather than global.
- kmc: There's also an issue about macros referring to other macros. Details in the writeup.
- nrc: You say we don't need #[phase(plugin)]. Why do we need #[plugin]?
- kmc: Syntax extensions.
- nrc: But for macro rules you wouldn't need anything?
- kmc: Right. They come in with the extern crate, then you can
use
them when you want them. - nrc: For the $crate idea, you hinted that there might be a "proper" way to do this; do you know what that is?
- kmc: We need a unique way to refer to a crate, and to close over those crates -- basically hygiene for crates. When you set up a reference in a macro, you'll hard link to the right crate, regardless of how things look at the use site. Might not be too hard, but definitely harder than $crate.
- kmc: $crate just piggybacks on the fact that we re-transcribe. Definitely less flexible than true hygiene.
- acrichto: It means that there's no guarantee that an exported macro will work for clients (you might not use $crate)
- kmc: Right. The guideline would be to always use $crate.
- nmatsakis: Do I have to link directly to the crate that my macro uses?
- kmc: E.g. libcollections defines a vec macro, which uses $crate. Then libstd rexports vec; you just have to make sure that libstd defines an API-compatible vec name. Mostly it just works.
- pnkfelix: So you do have to have a parallel module hierarchy?
- kmc: Yes. Solving that would need crate hygiene and related linkage issues.
- kmc: But $crate handles libcore and libcollections have macros that are reexported from std. Works great with the facade.
- nrc: What's the use case for replacing $crate with the exporting crate rather than original crate?
- kmc: You know the exporting crate exists in the set of crates in the current module.
- nmatsakis: Seems like we agree that this kind of simple solution is a good direction. Just need an RFC. Let's defer detail questions to that.
- nrc: One high level question though. Why should we have any module-level stuff at all for macros? In my mind macros exist prior to modules.
- kmc: Not quite sure I followed. Macros expand to code that contains paths, and we need to make sure those names actually work out correctly.
- nrc: I'm assuming you'd have to use absolute paths in macros?
- kmc: The problem is they're not really absolute; hence $crate
- nrc: Right. Assuming we use $crate, you still need to import into a module. Is that necessary?
- kmc: You could also do the import when you bring in the crate. The per module thing is inspired by macro escape, which is scoped only to that module.
- nmatsakis: This RFC has been implemented for a while. It's just a minor tweak.
- nmatsakis: Originally, when you wrote a lifetime bound on a type, there could be only one, but this RFC allows multiple bounds; and it's been implemented for a while.
fn foo<'a, T:'a>() { .. }
fn foo<'a, 'b, T:'a+'b>() { .. } // ok
- pnkfelix: This RFC suggests that we make it semantically significant whether you use {}, versus () or [] following a macro invocation. We'd use that to determine whether to parse as an expression or statement/decl.
- pnkfelix: Feedback overall is positive.
- nmatsakis: I like is, as I wrote. There hasn't been a ton of feedback.
+1's all around
- pnkfelix: I will merge
- nmatsakis: Needed for unboxed closures. RFC has details. The proposal allows you to write trait bounds that don't name specific regions. Something like:
fn foo<F>()
where F : for<'a> Fn(&'a int) -> &'a int
{
}
- nmatsakis: You can do this with fns, but not with traits; it's been the big missing piece of expressiveness.
- nmatsakis: The only contentious thing in the RFC was to add the
for
keyword here, in part to future proof against intended grammar changes. (for
is short forfor all
) - acrichto: Does this affect closure types? By putting in a
for
keyword there? - nmatsakis: It should.
- acrichto: Do we have plans to put in elision here?
- nmatsakis: That's in the RFC. Comes with the parens notation, which generally work like fn today. For example, this would be equivalent to the above:
fn foo<F>()
where F : Fn(&int) -> &int
{}
- brson: "where for" means "why", not to bikeshed
- nmatsakis: "for" means "for all"
- huon: what about boxed closures?
- nmatsakis: in a type, you could write:
Box<Fn(&int) -> &int>
Box<for<'a> Fn(&'a int) -> &'a int>
- nmatsakis: a bit verbose, but not worse than today.
- nmatsakis: I think we do want to allow
for
in either location (before or after:
), because you might want this more general form:
where for<'a> &'a T : SomeThing<'a>
- brson: Is this pretty rare to have to write?
- nmatsakis: Yeah.
- brson: And what does this block?
- pcwalton: Unboxed closures
- nmatsakis: If you type the following a lot, you'd be typing
for
instead:
fn foo(x: <'a> |&'a int| -> &'a int)
- nmatsakis: But usually you don't have to give names to these lifetimes.
- brson: Any concerns?
- acrichto: Could imagine some syntax tweaks, we can do that later.
- brson: I will merge
- pnkfelix: Proposes as a forward-compat issue to add
pub
to all the trait items (which are currently implicitly public). - pnkfelix: Since you might want in the future to allow private trait items, this would future proof. (Or else we'd have to add
priv
back in the future). - pnkfelix: It also makes refactoring a bit easier.
- wycats: I'm strongly in favor of this. Another factor is: sometimes you have to type
pub
, sometimes you don't, and that's hard to learn - acrichto: You can easily miss default methods, though, so this is still not perfect.
- wycats: I think the key point is consistency.
- nmatsakis: It is a little confusing, and I've also wanted some kind of trait privacy (although not sure on the exact semantics).
- nmatsakis: There will be churn.
- brson: Right, that's my concern.
- wycats: Could do a two-phase deprecation.
- pcwalton: I agree
- nrc: My worry is that, although I agree about the consistency issue, in some ways saying they should be the same is a false equivalence. After all, traits are interfaces, so you'd expect public by default, whereas other things are implementations, so you'd expect private by default.
- nrc: I feel like this is adding a lot of boilerplate for the common case. That feels wrong to me.
- wycats: I agree with your instinct -- if I had to guess the defaults, I'd end up in the same place.
- wycats: But you still have to think about it. Whereas: if it's public, type
pub
is very easy and doesn't require thought. - pcwalton: I think consistency outweighs the other concerns.
- nmatsakis: I like the "one true keyword" of
pub
. - nmatsakis: Not a lot of feedback from commenters yet.
- nrc: I see other consistency issues as larger, like commas and colons and so on for structs. This has never seemed too painful.
- nmasakis: some of those might be worth addressing separately.
- wycats: any objections to a two-phase deprecation?
< missed convo >
- aturon: what about on impls?
- (somebody) seems inconsistent to not require pub on impls of traits
- wycats: i was surprised starting out that in any of these cases you don't have to type pub
- huon: is a private method scoped with a trait? can you implement it outside of the module it's defined in?
- pnkfelix: We're not adding private methods yet.
- aturon: seems like we agree with the rfc that it is required on the impls
- pcwalton: i strongly think it should not be allowed on the impl
- nrc: it would never make sense to have pub on the trait but not write it on the impl
- pcwalton: if you wrote it on the impl it would disagree with what pub means everywhere else ... 'this is public or private w/r/t this module'. i would expect pub/priv on an impl of trait would be to say where that impl can be referenced from (w/r/t current module).
- aturon: we've been honing what priv means in rust toward a simple model, where you write 'pub' for something that can be exposed outside this module. seems accurate
- nmatsakis: that impl method could be called from outside module where it's defined. seems consistent
- aturon: had similar arguments before: just because it is pub doesn't mean you can access it. but not marking pub means that external mods can't access them.
- pcwalton: maybe my problem is impl for trait doesn't create names anywhere, so it seems meaningless
- nmatsakis: this argument might be stronger for 'priv' - looks like it can only be called from current module, but actually it can only be called from module that defined the trait
- pcwalton: (missed)
- nrc: priv impl method for trait can't actually be called in the module its defined
- nmatsakis: is what it is
- pcwalton: impls are globally scoped, not part of name resolution. they don't exist in the module hierarchy.
- nmatsakis: (missed)
- wycats: today, if you look at a fn, you have to understand the whole context. would be better to just be able to look at the function to know if it's pub
- nmatsakis: also cut-and-paste issue
- pcwalton: but conversely, if you require pub/priv you have to think about whether it's a trait impl to understand the semantics
- acrichto: we don't know what priv items are going to look like
- pcwalton: in haskell you can have typeclass methods that are not exported and you can't export impls because it doesn't make sense
- aturon: let's table
- wycats: right now, the nightlies across platforms are not guaranteed to be in sync. In the past week, OS X and Linux diverged, which blocked us for ~1 day. There was a breaking change between the two nightlies.
- wycats: I think we should only promote nightlies if they all succeed, rather than per-platform
- acrichto: We agree.
- wycats: It's pretty painful.
- brson: We have a lot of automation issues that got prioritized above this. If this is bad enough, we can re-prioritize, but it'll push other priorities back.
- wycats: All I can say is that it cost me (as a production user) a day.
- pnkfelix: Can't you just do this via the upgrade script?
- wycats: I'm just running rustup, and the result is compilers that are incompatible.
- nmatsakis: Yes, might be easier to do via rustup
- brson: But there's no archive of the nightlies.
- acrichto: Could just cache your own nightlies like Servo does.
- wycats: I will investigate.
- acrichto: But we can probably target this soon.
- acrichto: RFC to un-gate struct variants. Unclear why they're gated.
- acrichto: sfackler brought up that privacy story isn't clear. Recommend change to: everything is pub if the enum is pub.
- acrichto: Otherwise, seems like a straightforward ungating.
- pcwalton: Fine by me. They were gated because they felt unnecessary and people wanted to remove them.
- nmatsakis: Also questions about the
pub
issue. But I guess we can live with whatever it is -- makes sense to make consistent with enums - nrc: I would've thought consistent with structs.
- acrichto: We'd have to require pub on tuple variants
- nmatsakis: The idea was that tuple structs and enum tuples -- all this stuff should be consistent. Multiple axes of consistency. But we don't want the tuples to behave one way and structs behave a different way.
- nrc: My concerns is the behavior should be the same whether you write it as a top-level item or a variant.
- acrichto: Sounds like you'd want to make everything private by default.
- nmatsakis: I think you could defend either proposal, so we should minimize churn.
- brson: Are there changes here?
- acrichto: Yes, just the privacy changes, which are minimal.
- brson: Please work with sfackler to make the RFC changes and merge.
< minor missed discussion >
- brson: I'll merge