- unqualified associated types (nrc) #18764
- feature-gate
-EXPR
forEXPR: uN
? (pnkfelix) http://internals.rust-lang.org/t/forbid-unsigned-integer/752/20 - warnings on trivial casts and type ascription (nrc)
- variance and traits
- process::exit (acrichto) rust-lang/rfcs#1011
- coherence
- as and overflow (nmatsakis) rust-lang/rfcs#1019
- tonight's rollup (acrichto)
huonw, pnkfelix, steveklabnik, nmatsakis, nrc, acrichto, aturon, pcwalton
- acrichto: beta stabilization, landing final PRs, misc stability
- steveklabnik: knocking out as many A-docs issues as possible, working on the Book, especially wrt non-systems people, link checking
- aturon: blog, stabilization for beta, RFC on governance, RFC on API evolution
- pnkfelix: landing overflow work for beta
pnkfelix: feature-gate unary-negate operator on u{8,16,32,64,size}.
- nrc: had planned to do this
- nrc: some discussion yesterday tending towards not doing this
- nrc: "this" refers to: in a trait or impl at the moment, you do
Self::T
to talk about an assoc type T, and similarly for a method, you doSelf::foo
to get the method as a fn. The idea of unqualified is dropping theSelf
for either or both (two options). Seems consistent to do it for either nothing or for types/methods both. - nrc: pro: associated types are on a more even footing with generics ergonomically
- nrc: con: scoping is kind of odd. Perhaps writing
Self::
isn't so bad. Scoping is odd because, especially with methods, you have this relatively common-ish pattern where you have a methodread
at the module level, and a method on the impl that calls out to it, and you can't do that anymore, you have to explicitly name of them differently (or have a common helper), or use an absolute path. - nrc: approach to implementing this that I ended up with you also don't get access to assoc types and items in supertraits, which is perhaps surprising.
- nrc: perhaps better to just leave things as they are.
- pnkfelix: to be clear, what you mean is that if you try to write
foo
expecting the module-level fn, you actually wind up with a self-recursive loop, so long as the types match up, right? - nrc: yes but the types don't seem to match up regularly in practice. This also happens with types, e.g. we have an associated type
IntoIter
that namesvec::IntoIter
. - nrc: thoughts?
- acrichto: I'm fine with
Self::
and have never felt desire not to. - pnkfelix: method thing is a serious drawback to me. Wasn't so obvious that you have to do it for both types/methods.
- nrc: you could choose not to, but it seems more consistent that way.
- aturon: in the future, one point was that it would be possible to add
use
within a trait or impl, to help with simplifying particularly hairy, noisy traits. Would probably be rarely used but there may be cases where it's worth the trouble. - nrc: I should point out that this is a backwards incompatible change, unless you use an explicit opt-in as aturon points out.
- nmatsakis: my feeling is that we are in a consistent state now; the other state may be consistent; but given that beta is days away, best to stay where we are. Devil we know and all that.
- pnkfelix: I think it's surprising that
-foo
is valid wherefoo
has unsigned type. It has no sensible dynamic check; it always wraps except for0
if you interpret it numerically. Our current approach is to define: - Today:
-e
on unsigned value to(!e).wrapping_add(1)
- pnkfelix: I propose we just stop supporting it.
- pnkfelix: Getting rid of it entirely seems a bit aggressive this close to beta, but feature-gating it seems harmless.
- pnkfelix: Maybe crypto people want it? Other people suggest that you should say what you want (bitwise negate plus 1).
- pnkfelix: I don't see a strong clear signal besides effort to change/feature-gate it.
- nrc: I've in the past been a strong proponent for it.
- nrc: But now that whatever our future ergonomics for wrapping integers are, it could be included in that, and that standard unsigned integers should not allow it.
- nrc: So I think we should feature-gate it.
crickets
- acrichto: I'm a little uncomfortable with it. In the sense that it's kind of odd that we have an arbitrary subset of operations that are wrapping, but others that are bitwise... it would be nice to know the impact ahead of time. Don't have the time to gain that, but gating is always a good option.
- nmatsakis: I don't know what you're advocating precisely. Is that a +1 or -1 to negating unsigned?
- acrichto: Seems fine but I feel like I've often forgotten about legit use cases.
- nmatsakis: seems unlikely to be a huge crippling change given that you can add a method
x.negate()
or something locally - nmatsakis: feature-gate seems prudent, can always lift it.
- nrc: landed a patch last week which allowed all existing coercions to work as casts.
- nrc: also added lints so that if you have an unnecessary cast, you get the lint.
- nrc: landed with warn by default. two lints: numeric (allow by default), others (landed as warn, changed to allow)
- nrc: idea was we would wait for type ascription and change it to warn, at which point you can switch to use
:
and it's straightforward, unlike now - nrc: all well and good but we will hit beta. wanted to check in if not having these warnings on for beta was something we're comfortable with.
- nmatsakis: my feeling is it should stay at allow until type ascription is unfeature-gated, which is supposed to be after beta. Then it can become warn.
- pnkfelix: kballard mentioned idea of using type aliases as the key for the lint.
- pnkfelix: is there any plan to incorporate this?
- nrc: I did not and didn't plan to. Ideal world seems to be that we would have a lint that would warn only if it were not necessary on any platform, but that's not possible to do (without solving the halting problem! then it's easy! -ed.).
- pnkfelix: could approximate it in some crazy ways
- nrc: sure but I have no plans to do anything. Maybe if there is a lot of demand we could figure out something. Comes back into how we treat type aliases; we currently desugar them quite early. If we wanted to support something more like a newtype than an alias, that might require casting or coercion or something, there are options there. But that would be changing the language.
- nmatsakis: the lint can certainly look at AST to figure out if this was a type alias, but a platform-dependent one is clearly very hard.
- nmatsakis: does seem like allow-by-default will not get much use. but people also hate explicitly #[allow]. maybe if we can get a lot of the benefit by just ignoring type aliases, it'd be better to have something we can something that defaults to on. but we can do this later, we're allowed to tweak lints.
- nrc: doesn't feel particularly urgent or high priority.
- nmatsakis: I want to make all traits invariant with respect to their input. No MarkerTrait, no PhantomFn. You could have unused type params on traits, they would be invariant.
- nmatsakis: In practice, most traits are invariant (any trait with assoc types must be). So it doesn't carry its weight.
- nmatsakis: I have a PR, haven't heard many objections.
- aturon: Note that we can add back variance later on, this doesn't prevent that. (Though it would ahve to be in a slightly different form).
- acrichto: Is anything using this?
- nmatsakis: No. I took it out and it didn't break any code. There are probably traits where the type params are inferred to have variants, but it's not important for the code we've written. Only matters if you have references in the type params.
- nmatsakis: Generally, knowing the types is enough.
- acrichto: Small RFC to add std::process:exit for exiting the process with an error code. Safe binding for libc exit.
- acrichto: Caveats: won't run any destructors on current thread, also you don't know the state of other threads. This means we're saying that leaking/not running dtors is safe.
- acrichto: Location-wise, some people have suggested std::env::exit instead. I think it's analogous to std::thread::sleep.
- pcwalton: Happy for this to be safe.
- aturon: Part of the motivation here is that set_exit_code is not ready for stabilization (basically shared global state, not sure that we want this to be the story). So this gives us some way to return an exit code in stable code. You can just call it at the end of main, for example.
- nmatsakis: I'm fine with exposing exit, don't care where it lives. std::process seems fine.
- steveklabnik: I'm fine making this stable -- I can't see how the API could be different.
- acrichto: On windows, exit code is unsigned, unix it's signed. Don't think it matters, going with signed.
- nmatsakis: I got real worried about coherence a week or two ago. I realized taht the orphan rules have tilted the playing field so that downstream crates can add as many impls as possible -- but that constrains the kinds of impls that upstream crates can add in the future.
- nmatsakis: I went through a whole bunch of scenarios, especially regarding negative reasoning. You can add an impl for one trait that induces an impl conflict for a distinct trait.
- nmatsakis: That was the problem. We've talked about it before, so I won't go into great depth here.
- nmatsakis: I came up with a solution that has minimal impact and preserves a lot of freedom.
- nmatsakis: There are certain types and traits that are considered "fundamental": &, &mut, Box, Fn traits.
- nmatsakis: The idea is that adding a blanket impl for one of these types/traits is considered a breaking change. E.g.:
trait Foo { fn foo(&self) { } }
impl<T> Foo for &T { }
impl Foo for LocalType { }
impl Foo for &LocalType { }
impl Foo for Box<LocalType> { }
impl Foo for &Box<&mut &LocalType> { }
// not ok:
impl Foo for Vec<LocalType> { }
- nmatsakis: The benefit is that downstream crates can implement #[fundamental] traits for not just their own local types, but also e.g. &LocalType, Box etc (assuming that the upstream crate hasn't already provided a blanket impl that overlaps).
- nmatsakis: But other than blanket impls of #[fundamental] types, you can always add impls without risking breakage. So e.g. Vec can continue implementing existing traits. Or we coudl impl Copy for Range.
- nmatsakis: The other aspect is that there are fundamental traits. You have to implement these traits right away, or not at all, for a given type. For now, these are the Fn traits, but we may want to expand. The restrictions apply also to negative reasoning, which is where #[fundamental] traits come in:
trait MyTrait { }
impl<T:Foo> MyTrait for T { }
impl MyTrait for Vec<LocalType> { }
Vec<LocalType>: !Foo
- nmatsakis: Basically saying, you can't assert that something isn't implemented unless you control it (i.e., you could impl it). This avoids indirect conflicts where impling one trait can break impls of other traits. In practice, doing this for Fn traits is enough.
- nmatsakis: We can keep #[fundamental] gated for now, and I tried to tag the minimal number of types/traits, but we can grow it. Also, we can grow, change, or just stabilize this system in the future. Note, it's not a breaking change to add #[fundamental] to an existing type/trait.
- nmatsakis: My impl gets through all of rustc and most of std (modulo some existing coherence bugs). I also built several cargo crates, including the top crates, Iron.
- aturon: This is awesome work. I'm especially happy that it manages not to break code, while also keeping our options very much open in the future (by not having to stabilize the attribute right now).
- nmatsakis: It may be, by the way, that this strategy will allow us to relax other aspects of the coherence rules. We'll have to see.
- nmatsakis: There was a discussion, and I made an RFC along the lines of the meeting we had last time, basically saying that
as
will stay the way it is. Seems like most people are OK with that.
- acrichto: I've been working on a rollup; the whole queue is in there. If you've got stuff, just make sure it's approved, I'll take care of rebasing etc. That's true for tonight, and I'll likely do the same tomorrow.
- pnkfelix: I'm dealing with some cross-compilation issues; are you testing those?
- acrichto: That will pass the auto builders and fail on snapshot/beta builders, so that's a hazard
- pnkfelix: But there's android
- acrichto: Ah right, ok.
- nmatsakis: What's the hard deadline?
- acrichto: Roughly, Wednesday night. Thursday morning we'll kick off the build. Landing more things Thursday morning may be possible.