forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 1
Meeting weekly 2012 02 21
dherman edited this page Feb 21, 2012
·
1 revision
Jesse, Brian, Niko, Dave, Tim, Patrick, Graydon, Marijn
- Graydon: posted yesterday RFC process document and some notes on retagging in issue tracker, until I realized you can't do AND queries
- Graydon: GitHub says this is known and being worked on
- Graydon: I added some clustering tags for the time being
- Graydon: worst case we could go back to bugzilla
- Jesse: GitHub issues app on Heroku has querying support. (searching for "a-attributes i-papercut" on http://githubissues.heroku.com/#mozilla/rust does the intersection correctly)
- Marijn: even if not, there's an API; we could write a search engine ourselves
- Graydon: only thing missing is negation, but this will help
- Dave: seems inevitable they'll eventually fix GitHub issues
- Graydon: yeah, they fixed a ton of things last time, and they have tons of enterprise customers, so this is all on their list
- Niko: question: didn't quite understand what the wiki said -- if we settle on nominating for closing an issue, what tag do we use?
- Graydon: oops, forgot that; I'll make it a B tag
- Graydon: oh, I did create one: B-IsThisDone
- Niko: sounds like "Did we do this already"
- Graydon: yeah, I'll do B-ShouldClose too
- Niko: Tim, what's the status on classes?
- Tim: some implementation, front-end stuff, no methods yet; still very early on
- Niko: definitely wanting traits
- Dave: don't you need classes before traits?
- Niko: independent: can be used on impls
- Patrick: traits want CCI to be really useful
- Niko: that's true, gated on me
- Niko: my status: serialization mostly done, hoping to start deserialization today
- Niko: don't know if everyone knows: I've been blogging about region options, and I was going to make a table about different options
- Graydon: that would be super useful, and your blog posts have been extremely tantalizing
- Niko: I've been writing the posts because I couldn't make the table till I understand the different options
- Niko: I feel like there's a continuum and the current system is at one end
- Graydon: yeah, I think we can nudge it a bit further w/o overwhelming the user
- Graydon: one thing I want to point out: you talk about available-everywhere regions, I wanted to point out the constant region would be a super-useful one
- Niko: good point
- Graydon: other status updates? I'm working one export globbing, library and OS work
- Marijn: optimization work mostly complete; haven't finished vtable part; made much more complicated by having non-monomorphized; think I'll leave that till that's gone; may do bug-hunting in the meanwhile
- Graydon: always a good idea
- Niko: hopefully we can bring those things together next week
- Brian: rewrote task API over weekend; not dramatically different from before; updates to make room for wanted things
- Brian: working on getting rustdoc finished; also working on parallelizing it (not strictly necessary, but fun)
- Graydon: noticed an AST server growing in rustdoc; nice place to prototype it; if it works can put it in the compiler
- Jesse: actually faster with parallelization?
- Brian: not yet; need to use borrowable pointers for the par_map; currently copying structures
- Jesse: can we do borrowing without null?
- Niko: it's hard
- Graydon: could change to unique, hand it out as unsafe pointers, when they give it back return ownership
- Niko: I think that's something we'll want to talk about; hard part is you have to do it in some lib that knows the tasks are done
- Jesse: should par_map be part of std lib?
- Brian: we'll see; obviously we'll eventually want lots of concurrency primitives
- Marijn: one thing I want to discuss: can people agree to just removing preconditions from std lib functions? I suspect Tim is the only one who'll have a problem with this
- Marijn: not adding anything, making lib hard to use; until typestate matures we should remove them
- Graydon: I tend to agree
- Patrick: me too; it would be good to tackle in a more holistic way at some point; I do like the idea of dynamically checked contracts (with names); something worth thinking about
- Dave: trade-off I see: dynamic approach leads to lack of clarity about what can fail and what can cost at runtime; lint mode simply puts this decision on the programmer
- Tim: I'm ok with removing preconditions until typestate gets fixed, but I'm concerned that we won't fix typestate
- Dave: my only concern is that we may not find a solution
- Tim: sure, as long as it's an explicit decision, rather than just getting ignored
- Graydon: yeah. e.g., if it's gonna be a DbC system, we should make it that (e.g., remove purity). I'm not quite ready to abandon the static approach. I do really want that
- Dave: maybe restrict to subcases that we can reason about more robustly: non-empty vectors, subcases of enums
- Niko: I like static reasoning, definitely in favor of seeing what we can express
- Patrick: this sounds more like types than refinements
- Tim: yeah, this is closer to the datasort refinements I proposed earlier
- Patrick: to me, important question is not whether refinements are useful but ... well, another question anyway is whether the control flow will be useful
- Dave: I think it could still play a role if there's still useful information that can be conveyed to the type system via
if
- Graydon: kind of depends how expression-y you want the language to be
- Dave: I think it still comes up even in an expression-y language
- Graydon: informal poll of preferences: do you want to bother with static reasoning e.g. datasort refinements?
- (most raise hands, not Marijn)
- Graydon: another informal poll: do you think we'll need to abandon the user-specified predicates being used for static refinements?
- (Patrick, Niko, Dave raise hands)
- Patrick: we definitely want some particular patterns of static refinement of info, but I don't see the user-specified refinement types working well
- Graydon: I talked with the Hermes people a while back; they used it for message-passing, so I'd hoped it would be useful for us too; but if it's not working out for us I'm ok with focusing on the stuff where we need it
- Graydon: I still think the control-flow part could play a role
- Patrick: it's still useful for init checking
- Dave: even if it's just used for that, I still think it pays for itself
- Graydon: so we'll go ahead and remove the refinements from the stdlib
- Jesse: change to assertions at top?
- Graydon: yeah; we can talk down the road about enhancing typestate further or turning it into DbC
- Graydon: we're not at the point of a full-on assault of that subsystem yet
- Jesse: I have some concerns about unsafe blocks
- Brian: Jesse & I were discussing: lots of things we do in unsafe blocks that inhibit things the compiler is supposed to be doing but isn't
- Brian: specifically, won't be able to yield nor cycle-collect; hadn't considered this till recently, but seems pretty clear that's the case
- Jesse: also unwinding if you get a failure
- Brian: right, can't unwind
- Niko: unsafe::leak which leaves refcount unadjusted
- Niko: not entirely clear to me why that should prevent cycle collection etc
- Brian: b/c yielding can fail; if we unwind, we would drop the ref twice
- Niko: yielding can fail b/c it might check an error state
- Brian: linked failure; child fails
- Niko: so leak has to be done atomically, which we could do if we're more careful with move mode
- Graydon: mm-hmm
- Niko: my question is, is it only refcounting, or are there other problems?
- Brian: don't know. specifically familiar with this case
- Patrick: C# has this thing called pinning: in order to interact w/ pointers in unsafe way, have to pin the pointer; tells the GC not to touch it; could stuff like that be helpful?
- Niko: maybe
- Brian: possibly. wouldn't solve problem of not being able to fail
- Niko: kinda feel like if it's only refcounting, that's addressible in another way; if there are other problems, it'd be good to know
- Jesse: is it reasonable to say: if you fail in unsafe block and compiler doesn't know how to unwind, you'll lose the whole process?
- Brian: so much important code written in unsafe blocks... and you could get a kill signal at any time
- Graydon: you're saying any time there's an unsafe block on the stack atack at all?
- Brian: yeah
- Niko: you've only given one example...
- Patrick: can we use resources? rewrite unsafe blocks to be failure-safe somehow?
- Niko: resources and failure have a checkered relationship; if there's a failure in a resource, etc etc
- Graydon: I had a document written up a long time ago about this
- Niko: all I'm saying is, I've tried using resources this way and had leaks
- Graydon: yeah, there's a bunch of interlocking things here, and it's extremely tricky and super hard to debug
- Graydon: one example: comm system has to have clear lifecycles for everything
- Graydon: needs to be a version of failure that works in all contexts on all platforms
- Graydon: we should have better answers than "the process shuts down" -- that's us saying we didn't do our homework
- Niko: similar case is when you have a failure and there's C code on the stack; in that case maybe we really can throw up our hands
- Dave: is it not fair to say that unsafe code is just a more convenient way to write C code?
- Niko: I'm not yet convinced this is an issue; leaking refcounts is tricky business, and if you're mucking with pointers, it's tricky
- Patrick: there are multiple things here: reason we abort in C calls is that we don't know that that C code has any sort of failure-recovery mechanism at all; if there were a way to show that C code were all exception-safe, or returned an error code, we could do something different; but a lot of times that's not true of C code; but that's not true of Rust unsafe code: we actually have hope of giving it sane failure semantics; maybe some way to tag unsafe code as not failure-safe; don't think it's the case that unsafe code must abort, because it does have a sane failure semantics
- Niko: that's exactly what I think
- Graydon: let me rephrase succinctly: in Rust side, we can assume programmers are aware of failure; on C side, we can't; conclusion: unsafe Rust is opt-out, and C code is opt-in
- Jesse: in the C code or in the Rust binding for the C code?
- Graydon: could go either way
- Niko: there's a wide range of cases to handle
- Graydon: I think it's reasonable, for example, to have C have a dynamic way to interface with failure system
- Niko: JSAPI, for example, uses return codes
- Graydon: two sides to that: how does C code inform Rust callers that it's failed; how does Rust code that's been called back from C inform C that it's failed
- Niko: right
- Graydon: two possibilities: mark function saying this C code is aware of failures and has this mechanism; declare this C code is failure-irrelevant, no big deal to just toss it out
- Niko: what I wanted to ask: could imagine marking C code as failure-safe, could be Rust code's responsibility to take return code, or could be built into the runtime
- Niko: just want to see if we can orthogonalize two concerns
- Graydon: ability to set "this task is failing" and check "is this task failing" from C side should be sufficient, so long as when you unwind through a C frame you clean up; gets into implementation of the unwind system
- Graydon: keep in mind, portable unwind system has a dynamic component
- Graydon: if we stop using DWARF failure system, we could have a uniform failure model; downside is that exceptions are no longer zero-cost
- Graydon: what are people's gut feelings on this? do you like SEH?
- Graydon: three options
- a. only use SEH on Windows, otherwise use some C API
- b. switch to using that API on all platforms for uniformity
- c. give up on allowing C code to clean up after itself
- Patrick: I want to add: Brian & I have talked about this, SEH cost is not as high as you might think; cost is only applicable for resources; for refcounts, unilaterally blow away on failure, and for unique pointer you can also unilaterally blow away; so only have to run destructors
- Niko: would have to track which unique ptrs owned by process
- Patrick: yeah, some bookkeeping, but not that much; so it seems SEH is tolerable when it's only for resource destructors
- Graydon: so SEH everywhere, uniform interface everywhere
- Patrick: yeah
- Niko: I agree
- Niko: Graydon: are you saying the C code would have to call these things, so you'd have to write C code wrappers for libraries that don't know about Rust?
- Graydon: yes, you'd have to write a C wrapper that adapts; usually just one function; not that hard to tell users how to do it
- Niko: seems like it'd be enough to set an annotation on C callback, something like canfail, on exit from function check the RustCurrentTaskIsFailing and continue to propagate failure; is that true?
- Graydon: would be assuming all C code can fail; always checking that flag on return
- Niko: might want to try to optimize that
- Graydon: flag check doesn't sound that bad to me
- Niko: no, true. main thing is we want to be able to catch the error, let the C code propagate it for a little while, and then keep going
- Graydon: yeah
- Niko: as long as that's what we're talking about, I'm fine. I'd rather you don't have to write C code every time
- Graydon: anyone not wanna do SEH everywhere approach?
- (crickets)
- Patrick: binary size was also an issue
- Graydon: yeah, it mattered on cell phones. but then everything matters on cell phones
- Graydon: so sounds like concensus to try it out and see
- Niko: yeah
- Jesse: so this is how Rust itself handles failures, in addition to C code
- Graydon: yeah; basically giving up on DWARF zero-cost exceptions
- Jesse: alternative on windows?
- Graydon: windows has something special, metadata blobs that look something like DWARF; has something that all Windows debuggers use
- Jesse: it's zero-cost in the not-throwing case?
- Graydon: yeah, never truly zero-cost, but it's about not throwing
- Patrick: and to reiterate, if we're clever, this should only cost for resource destructors, which are rare
- Niko: yeah, in C++ it's mostly for memory management
- Jesse: well, in Firefox we use auto classes (RAII) for security invariants as well
- Graydon: Patrick: when you say clever, how clever?
- Patrick: well, failure is non-recoverable, and all RC data is task-local, so you can indiscriminantly blow away all task-local data once destructors have run
- Graydon: you do have to find destructors in heap
- Niko: well, we can walk the heap
- Graydon: you also have to drop unique ptrs
- Patrick: right, need bookkeeping to see which uniques belong to the task
- Niko: walk the stack to find roots
- Graydon: one way or another, yeah
- Graydon: what's happening in our landing pads now?
- Brian: basically they run cleanup code that our other code runs anyway
- Graydon: so this is a pretty substantial change to codegen; all landing pads will be eliminated
- Dave: won't this change the order of destructors?
- Niko: doesn't bother me
- Patrick: you can compute which RC's were from the stack just based on their counts
- Niko: how important is it to preserve that?
- Graydon: that I don't think is terribly important; concept is the only ordering they provide is the order inside them; but stack destructors should happen inside-out
- Dave: other question: keeping stuff alive longer b/c they get dropped after destructors run?
- Graydon: yeah, it's a corner case; originally had two failure modes, soft failure and hard failure; if a destuctor enters hard failure, no more destructors run during that destructor, go back into soft failure after completing that destructor
- Jesse: ISTM we shouldn't allow resources inside destructors
- Niko: we can't do that; could call a function
- Graydon: analogous to Java; exception in finally overrides
- Graydon: same concept, yeah; not currently implemented
- Jesse: not-running-some-destructors sounds like serious leaks, or getting security checks wrong
- Graydon: we'll need a design document, but I believe there's a solution
- Graydon: Brian, are you okay with experiment with SEH everywhere?
- Brian: yep, I'm fine with that
- Graydon: I don't think users are stressing the failure system yet; more of a long-term thing we need a plan for for developers
- Brian: the Windows situation is a little embarrassing right now
- Graydon: SEH also makes it way easier to debug; breakpoints in SEH is doable, with DWARF it's impossible in my experience
- Brian: I've done it
- Niko: Brian's made of stronger stuff than the rest of us
- Jesse: is compiled Rust code fast enough that we could do meaningful comparisons of DWARF vs SEH?
- Patrick: yes, but you have to be careful what kind of program you're using
- Graydon: don't think we'll be able to do an exhaustive comparison, but a gut feeling comparison would be important, like is rustc perf still acceptible; ideally it should get smaller
- Niko: I would even expect it to get slightly faster
- Brian: we took a big hit for DWARF unwinding; I'd expect we could do better by rolling our own
- Patrick: well, be wary of comparisons; may make compiler faster but not other programs
- Graydon: it's a tough decision to make strictly on perf; the perf space is enormous; should base it more on what we want to achieve; perf should just be aiming at "reasonable"
- Brian: Servo will care about perf a lot
- Niko: particularly messaging; latency of messages directly affects the architecture
- Jesse: do we have a perf test suite?
- Brian: yes, but we never check them; I'd like to set up something better before we make a huge push on performance
- Niko: data is good