Stream: wg-ffi-unwind

Topic: "C unwind" vs "C noexcept"


nikomatsakis (Oct 28 2019 at 20:40, on Zulip):

So it seems like the arguments in this hackmd document are fairly complete. Based on this, I personally find the argument in favor of the current setup ("C" does not permit unwinding, "C unwind" does) more compelling. To me, the killer argument is the point around safety and the interaction with -Zpanic=abort.

nikomatsakis (Oct 28 2019 at 20:40, on Zulip):

At least in our last meeting, the lang team seemed to agree.

nikomatsakis (Oct 28 2019 at 20:41, on Zulip):

Based on this, I'm wondering if we should declare this a finalized decision as well -- that would unlock us to move forward with a 0th RFC that includes the "C unwind" ABI.

nikomatsakis (Oct 28 2019 at 20:49, on Zulip):

Er, I forgot about @Josh Triplett's comment earlier

Josh Triplett: I just read through this whole thread, and the idea of allowing unwinding by default seems reasonable to me.

so perhaps I am speaking too soon. Seems to argue in favor of doing the minimal "just create the group" RFC, just to make progress.

Kyle Strand (Oct 28 2019 at 20:51, on Zulip):

I think "C unwind" would have the exact same concerns regarding -Zpanic=abort. In fact, I have been thinking of the question of extern "C"'s behavior in terms of whether or not extern "C" should be an alias for extern "C unwind". (I realize that's not the only possibility discussed in that document, but I think it highlights the need to design "C unwind" with all due safety considerations, etc, regardless of how we treat "C".)

Kyle Strand (Oct 28 2019 at 20:52, on Zulip):

I think the "just create the group" RFC is the right approach. Combining a governance issue with technical issues increasingly seems like a recipe for another very confusing GitHub thread.

nikomatsakis (Oct 28 2019 at 21:30, on Zulip):

I think "C unwind" would have the exact same concerns regarding -Zpanic=abort

I cover this in the doc: I think it's quite different. The key point is that extern "C" leaves it, in some sense, ambiguous whether unwinding occurs -- it claims that it might, but de facto it rarely does.

nikomatsakis (Oct 28 2019 at 21:30, on Zulip):

In contrast, "C unwind" would only be used where unwinding is expected

nikomatsakis (Oct 28 2019 at 21:31, on Zulip):

This in turn means that we can insert shims to catch unwinding and abort without undue code size increase

nikomatsakis (Oct 28 2019 at 21:31, on Zulip):

(That said, I think it would be interesting to see real data here)

Kyle Strand (Oct 28 2019 at 21:39, on Zulip):

(That said, I think it would be interesting to see real data here)

Agreed. I don't want to accidentally design ourselves into a corner in such a way that we can't add optimizations in the future, but optimizations without data don't seem like a good basis for selecting default behaviors.

nikomatsakis (Oct 28 2019 at 21:40, on Zulip):

(There are other arguments, all similar -- the core question is which aligns more closely with reality)

nikomatsakis (Oct 28 2019 at 21:40, on Zulip):

( I don't think it's right to frame it as just an optimization question )

nikomatsakis (Oct 28 2019 at 21:42, on Zulip):

(specifically, the question of auditing and reasoning)

nikomatsakis (Oct 28 2019 at 21:42, on Zulip):

One thing that struck me was when @Taylor Cramer mentioned that if we switched the default, he'd probably just do extern "C noexcept" for all functions in Fuschia.

nikomatsakis (Oct 28 2019 at 21:43, on Zulip):

which, in some sense, is fine...

nikomatsakis (Oct 28 2019 at 21:43, on Zulip):

anyway

Kyle Strand (Oct 28 2019 at 21:56, on Zulip):

I'd actually prefer that. If Rust had a benevolent dictator and I were that dictator, I'd just deprecate extern "C" and everyone would need to pick between "C unwind" and "C nounwind".

Kyle Strand (Oct 28 2019 at 21:57, on Zulip):

Also the keyword would be changed to abi for function definitions, while keeping extern for "import-like" declarations

gnzlbg (Oct 29 2019 at 07:51, on Zulip):

One thing that struck me was when @Taylor Cramer mentioned that if we switched the default, he'd probably just do extern "C noexcept" for all functions in Fuschia.

Not only fuchsia. I'd need to do the same on libc, which includes Fuchsia support, and that would mean that this is done for all platforms that Rust currently supports. That would be an API breaking change on all platforms, anyone taking function pointers to libc functions would need to update their code, libc would need a new major release, which means that the ecosystem would be broken until all crates update, but crates need to update in order, etc.

gnzlbg (Oct 29 2019 at 07:56, on Zulip):

So we probably would need to figure out a way of adding support for two incompatible versions of a C-linking dependency to cargo or similar features to avoid a lot of pain.

Amanieu (Oct 29 2019 at 11:42, on Zulip):

Would it be a breaking change to change functions which are cancellation points in libc to extern "C unwind"?

gnzlbg (Oct 29 2019 at 11:46, on Zulip):

Yes, that's also a breaking change.

gnzlbg (Oct 29 2019 at 11:47, on Zulip):

I'd like to be able to say it would be a much smaller breaking change, but I don't think that's the case. There are not that many cancellation points, but they are used by a lot of crates.

gnzlbg (Oct 29 2019 at 11:48, on Zulip):

With implicit coercions we could try to roll in those changes and see what happens, but there are a couple of things that implicit coercions don't cover.

gnzlbg (Oct 29 2019 at 11:49, on Zulip):

e.g. impl Trait for extern "C" fn(...) { } wouldn't implement Trait for the cancellation points if we make them extern "C unwind" anymore

gnzlbg (Oct 29 2019 at 11:51, on Zulip):

I've seen code like that in the wild (e.g. in the libm testing crates), but it did not apply to any cancellation points

nikomatsakis (Oct 29 2019 at 22:47, on Zulip):

I'd like to be able to say it would be a much smaller breaking change, but I don't think that's the case. There are not that many cancellation points, but they are used by a lot of crates.

This is an interesting consideration that is not covered in the existing doc

nikomatsakis (Oct 29 2019 at 22:48, on Zulip):

However, @gnzlbg, another option would be to export those functions via a (deprecated) wrapper that (e.g.) aborts on unwind, and expose the real functions some other way

nikomatsakis (Oct 29 2019 at 22:48, on Zulip):

(and perhaps also offer a major version bump that corrects the issue)

gnzlbg (Oct 30 2019 at 08:34, on Zulip):

@nikomatsakis yeah, maybe. We should explore how to land this on libc. A problem with wrappers is that the address of the original libc function gets lost, and that could be a breaking change (e.g. if people are getting the address of the function, and then using dlsym or similar to figure out if its actually linked or if the libc is too old).

gnzlbg (Oct 30 2019 at 08:36, on Zulip):

(and perhaps also offer a major version bump that corrects the issue)

We currently can't. libc links C libraries, and is linked as part of the rustc run-time, that is, it is part of a crates dependency graph if that crate links liballoc or libstd.

gnzlbg (Oct 30 2019 at 08:36, on Zulip):

IIRC, the only reason one can link libc from crates.io is because it has the same major version as the one that's linked by libstd.

gnzlbg (Oct 30 2019 at 08:37, on Zulip):

If we bump the major version of libc, then the versions in crates.io and libstd are incompatible.

gnzlbg (Oct 30 2019 at 08:37, on Zulip):

This means that you can't use the slightly older libc crate with libstd anymore.

gnzlbg (Oct 30 2019 at 08:37, on Zulip):

and that if you are in an older Rust toolchain, you can't use crates using the newer libc anymore.

gnzlbg (Oct 30 2019 at 08:38, on Zulip):

IIRC when libc was bumped from 0.1 to 0.2 this required an ecosystem wide upgrade.

gnzlbg (Oct 30 2019 at 08:39, on Zulip):

Everyone had to migrate their crates to use the latest Rust toolchain, and the latest libc version, and nothing older would work with those versions of those crates, and there are no "facade-crate" workarounds that one can use to avoid that.

gnzlbg (Oct 30 2019 at 08:40, on Zulip):

@Alex Crichton ^^^^^^ this is at least what I recollected from back then, I'm not sure if something has fundamentally changed in the toolchain since that might allow us to handle this.

nikomatsakis (Oct 30 2019 at 12:56, on Zulip):

@gnzlbg I think it woud be useful to have a list of all the functions that you know can unwind --

nikomatsakis (Oct 30 2019 at 12:56, on Zulip):

is it all pthread APIs?

nikomatsakis (Oct 30 2019 at 12:56, on Zulip):

I'm not sure how pthread cancellation works

nikomatsakis (Oct 30 2019 at 12:56, on Zulip):

any time I've needed that sort of mechanism I always built it myself

gnzlbg (Oct 30 2019 at 12:59, on Zulip):

there is a list, wait

gnzlbg (Oct 30 2019 at 12:59, on Zulip):

http://man7.org/linux/man-pages/man7/pthreads.7.html

gnzlbg (Oct 30 2019 at 12:59, on Zulip):

See "cancellation points" there

gnzlbg (Oct 30 2019 at 13:00, on Zulip):

I'm not sure how pthread cancellation works

It pretty much works like a garbage collector would, it can only kick in when the current thread yields control to the "runtime"

gnzlbg (Oct 30 2019 at 13:01, on Zulip):

in this case the runtime is the C library, so pretty much all functions in the C library are cancellation points, e.g., open, or poll, etc.

gnzlbg (Oct 30 2019 at 13:02, on Zulip):

I don't know what happens if the thread that gets cancelled doesn't call one of those cancellation points for a while

gnzlbg (Oct 30 2019 at 13:03, on Zulip):

@Amanieu might know

gnzlbg (Oct 30 2019 at 13:03, on Zulip):

IIRC an implementation can in some cases send a signal, and kill the thread if it isn't caught, but..

gnzlbg (Oct 30 2019 at 13:03, on Zulip):

I don't know if any implementation actually does that

gnzlbg (Oct 30 2019 at 13:05, on Zulip):

Full ist:

     The following functions are required to be cancellation points by
       POSIX.1-2001 and/or POSIX.1-2008:

           accept()
           aio_suspend()
           clock_nanosleep()
           close()
           connect()
           creat()
           fcntl() F_SETLKW
           fdatasync()
           fsync()
           getmsg()
           getpmsg()
           lockf() F_LOCK
           mq_receive()
           mq_send()
           mq_timedreceive()
           mq_timedsend()
           msgrcv()
           msgsnd()
           msync()
           nanosleep()
           open()
           openat() [Added in POSIX.1-2008]
           pause()
           poll()
           pread()
           pselect()
           pthread_cond_timedwait()
           pthread_cond_wait()
           pthread_join()
           pthread_testcancel()
           putmsg()
           putpmsg()
           pwrite()
           read()
           readv()
           recv()
           recvfrom()
           recvmsg()
           select()
           sem_timedwait()
           sem_wait()
           send()
           sendmsg()
           sendto()
           sigpause() [POSIX.1-2001 only (moves to "may" list in POSIX.1-2008)]
           sigsuspend()
           sigtimedwait()
           sigwait()
           sigwaitinfo()
           sleep()
           system()
           tcdrain()
           usleep() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
           wait()
           waitid()
           waitpid()
           write()
           writev()

       The following functions may be cancellation points according to
       POSIX.1-2001 and/or POSIX.1-2008:

           access()
           asctime()
           asctime_r()
           catclose()
           catgets()
           catopen()
           chmod() [Added in POSIX.1-2008]
           chown() [Added in POSIX.1-2008]
           closedir()
           closelog()
           ctermid()
           ctime()
           ctime_r()
           dbm_close()
           dbm_delete()
           dbm_fetch()
           dbm_nextkey()
           dbm_open()
           dbm_store()
           dlclose()
           dlopen()
           dprintf() [Added in POSIX.1-2008]
           endgrent()
           endhostent()
           endnetent()
           endprotoent()
           endpwent()
           endservent()
           endutxent()
           faccessat() [Added in POSIX.1-2008]
           fchmod() [Added in POSIX.1-2008]
           fchmodat() [Added in POSIX.1-2008]
           fchown() [Added in POSIX.1-2008]
           fchownat() [Added in POSIX.1-2008]
           fclose()
           fcntl() (for any value of cmd argument)
           fflush()
           fgetc()
           fgetpos()
           fgets()
           fgetwc()
           fgetws()
           fmtmsg()
           fopen()
           fpathconf()
           fprintf()
           fputc()
           fputs()
           fputwc()
           fputws()
           fread()
           freopen()
           fscanf()
           fseek()
           fseeko()
           fsetpos()
           fstat()
           fstatat() [Added in POSIX.1-2008]
           ftell()
           ftello()
           ftw()
           futimens() [Added in POSIX.1-2008]
           fwprintf()
           fwrite()
           fwscanf()
           getaddrinfo()
           getc()
           getc_unlocked()
           getchar()
           getchar_unlocked()
           getcwd()
           getdate()
           getdelim() [Added in POSIX.1-2008]
           getgrent()
           getgrgid()
           getgrgid_r()
           getgrnam()
           getgrnam_r()
           gethostbyaddr() [SUSv3 only (function removed in POSIX.1-2008)]
           gethostbyname() [SUSv3 only (function removed in POSIX.1-2008)]
           gethostent()
           gethostid()
           gethostname()
           getline() [Added in POSIX.1-2008]
           getlogin()
           getlogin_r()
           getnameinfo()
           getnetbyaddr()
           getnetbyname()
           getnetent()
           getopt() (if opterr is nonzero)
           getprotobyname()
           getprotobynumber()
           getprotoent()
           getpwent()
           getpwnam()
           getpwnam_r()
           getpwuid()
           getpwuid_r()
           gets()
           getservbyname()
           getservbyport()
           getservent()
           getutxent()
           getutxid()
           getutxline()
           getwc()
           getwchar()
           getwd() [SUSv3 only (function removed in POSIX.1-2008)]
           glob()
           iconv_close()
           iconv_open()
           ioctl()
           link()
           linkat() [Added in POSIX.1-2008]
           lio_listio() [Added in POSIX.1-2008]
           localtime()
           localtime_r()
           lockf() [Added in POSIX.1-2008]
           lseek()
           lstat()
           mkdir() [Added in POSIX.1-2008]
           mkdirat() [Added in POSIX.1-2008]
           mkdtemp() [Added in POSIX.1-2008]
           mkfifo() [Added in POSIX.1-2008]
           mkfifoat() [Added in POSIX.1-2008]
           mknod() [Added in POSIX.1-2008]
           mknodat() [Added in POSIX.1-2008]
           mkstemp()
           mktime()
           nftw()
           opendir()
           openlog()
           pathconf()
           pclose()
           perror()
           popen()
           posix_fadvise()
           posix_fallocate()
           posix_madvise()
           posix_openpt()
           posix_spawn()
           posix_spawnp()
           posix_trace_clear()
           posix_trace_close()
           posix_trace_create()
           posix_trace_create_withlog()
           posix_trace_eventtypelist_getnext_id()
           posix_trace_eventtypelist_rewind()
           posix_trace_flush()
           posix_trace_get_attr()
           posix_trace_get_filter()
           posix_trace_get_status()
           posix_trace_getnext_event()
           posix_trace_open()
           posix_trace_rewind()
           posix_trace_set_filter()
           posix_trace_shutdown()
           posix_trace_timedgetnext_event()
           posix_typed_mem_open()
           printf()
           psiginfo() [Added in POSIX.1-2008]
           psignal() [Added in POSIX.1-2008]
           pthread_rwlock_rdlock()
           pthread_rwlock_timedrdlock()
           pthread_rwlock_timedwrlock()
           pthread_rwlock_wrlock()
           putc()
           putc_unlocked()
           putchar()
           putchar_unlocked()
           puts()
           pututxline()
           putwc()
           putwchar()
           readdir()
           readdir_r()
           readlink() [Added in POSIX.1-2008]
           readlinkat() [Added in POSIX.1-2008]
           remove()
           rename()
           renameat() [Added in POSIX.1-2008]
           rewind()
           rewinddir()
           scandir() [Added in POSIX.1-2008]
           scanf()
           seekdir()
           semop()
           setgrent()
           sethostent()
           setnetent()
           setprotoent()
           setpwent()
           setservent()
           setutxent()
           sigpause() [Added in POSIX.1-2008]
           stat()
           strerror()
           strerror_r()
           strftime()
           symlink()
           symlinkat() [Added in POSIX.1-2008]
           sync()
           syslog()
           tmpfile()
           tmpnam()
           ttyname()
           ttyname_r()
           tzset()
           ungetc()
           ungetwc()
           unlink()
           unlinkat() [Added in POSIX.1-2008]
           utime() [Added in POSIX.1-2008]
           utimensat() [Added in POSIX.1-2008]
           utimes() [Added in POSIX.1-2008]
           vdprintf() [Added in POSIX.1-2008]
           vfprintf()
           vfwprintf()
           vprintf()
           vwprintf()
           wcsftime()
           wordexp()
           wprintf()
           wscanf()
gnzlbg (Oct 30 2019 at 13:07, on Zulip):

My rule of thumb is that, if some operation of the POSIX or C library APIs can result in a context switch to the kernel, the it is probably a cancellation point. That's a lot of operations.

Alex Crichton (Oct 30 2019 at 14:09, on Zulip):

@gnzlbg I don't think that characterization of a major-version upgrade is quite right, and I think the next version can go much more smoothly than the last. It sort of depends on the specifics, but it's not so bad that everyone has to upgrade their rustc

Amanieu (Oct 30 2019 at 14:11, on Zulip):

Basically cancellation works like this:
1) pthread_cancel sends a signal to the thread being canceled.
2) The signal handler sets a flag in thread-local storage and returns.
3) If the thread was in a system call, that system call is automatically interrupted by the signal.
4) At cancellation points, glibc checks this flag and triggers unwinding if it is set.

Amanieu (Oct 30 2019 at 14:13, on Zulip):

There is also PTHREAD_CANCEL_ASYNCHRONOUS, which unwinds directly from the signal handler (without needing a cancellation point). But this is horribly unsafe and the man page says that this is only safe to use if the thread does not call any libc functions.

gnzlbg (Oct 30 2019 at 14:15, on Zulip):

I don't think that characterization of a major-version upgrade is quite right, and I think the next version can go much more smoothly than the last.

@Alex Crichton do you remember exactly what caused so much pain last time ?

gnzlbg (Oct 30 2019 at 14:16, on Zulip):

Looking at the libc crate, the crate does not use the links = key in the Cargo.toml, so there should not be a conflict in dependency resolution due to it.

gnzlbg (Oct 30 2019 at 14:16, on Zulip):

The only places where things are linked are in the extern "C" { ... } blocks using link flags

gnzlbg (Oct 30 2019 at 14:17, on Zulip):

but that should not cause any troubles across major version releases

Alex Crichton (Oct 30 2019 at 14:17, on Zulip):

@gnzlbg the pain point is that libc01::c_void was a different type than libc02::c_void, so if you used *mut c_void in your public API then everyone had to upgrade at the same time to get everyone to agree on c_void (or any other libc type in the public API)

Alex Crichton (Oct 30 2019 at 14:18, on Zulip):

that point specifically is now fixed with core::ffi::c_void

Alex Crichton (Oct 30 2019 at 14:18, on Zulip):

functions themselves don't matter, it's the public types being shared across libc versions

Alex Crichton (Oct 30 2019 at 14:18, on Zulip):

and c_void was the #1 through like #1000 reason why it was so common

gnzlbg (Oct 30 2019 at 14:18, on Zulip):

yes libc now uses core::ffi::c_void

Alex Crichton (Oct 30 2019 at 14:18, on Zulip):

so a transition to 1.0 won't exactly be smooth but it won't be as bad as the last, or at least that's theorized

gnzlbg (Oct 30 2019 at 14:19, on Zulip):

the other types haven't changed either

gnzlbg (Oct 30 2019 at 14:19, on Zulip):

then there shouldn't be a problem at all in doing a new libc release

gnzlbg (Oct 30 2019 at 14:20, on Zulip):

ah, no wait

Alex Crichton (Oct 30 2019 at 14:20, on Zulip):

(FWIW if a new libc release is being done this is something I think we'll want to coordinate with folks, this shouldn't just happen off-hand)

Alex Crichton (Oct 30 2019 at 14:20, on Zulip):

but the issue is not that the types didn't change but that they're defined in two crates

gnzlbg (Oct 30 2019 at 14:20, on Zulip):

@Alex Crichton if I release libc 0.3, then libc::03::c_int is a different type that libc::02::c_int

Alex Crichton (Oct 30 2019 at 14:20, on Zulip):

That's not quite true b/c c_int is a type alias to i32

gnzlbg (Oct 30 2019 at 14:20, on Zulip):

so anyone using those for interoperation will run into issues

Alex Crichton (Oct 30 2019 at 14:20, on Zulip):

so it resolves to the same type

Alex Crichton (Oct 30 2019 at 14:20, on Zulip):

something like struct Dl_info, however, will be different even though it didn't change

gnzlbg (Oct 30 2019 at 14:20, on Zulip):

ok, so it only impacts the struct types

gnzlbg (Oct 30 2019 at 14:21, on Zulip):

or the enum File {}

Alex Crichton (Oct 30 2019 at 14:21, on Zulip):

(but again let's discuss specifics before it actually hapens)

Alex Crichton (Oct 30 2019 at 14:21, on Zulip):

right yeah

gnzlbg (Oct 30 2019 at 14:21, on Zulip):

I see

Alex Crichton (Oct 30 2019 at 14:21, on Zulip):

do you want to release libc 0.3 soon?

gnzlbg (Oct 30 2019 at 14:21, on Zulip):

no

Alex Crichton (Oct 30 2019 at 14:21, on Zulip):

ah ok

gnzlbg (Oct 30 2019 at 14:21, on Zulip):

I just though things were worse than they are

Alex Crichton (Oct 30 2019 at 14:21, on Zulip):

nah yeah we're in a way better position than before

Alex Crichton (Oct 30 2019 at 14:21, on Zulip):

especially with c_void solved

Alex Crichton (Oct 30 2019 at 14:21, on Zulip):

and all typedefs go to the same base integer types

gnzlbg (Oct 30 2019 at 14:22, on Zulip):

yes, type aliases help here for better or worse

gnzlbg (Oct 30 2019 at 14:23, on Zulip):

this looks pretty much as good as it is going to get

gnzlbg (Oct 30 2019 at 14:23, on Zulip):

every major release is going to cause the incompatibility with the types unless we use the semver trick

gnzlbg (Oct 30 2019 at 14:23, on Zulip):

(e.g. libc 0.3 depends on 0.2 and re-exports everything or parts of it)

Kyle Strand (Oct 30 2019 at 18:05, on Zulip):

@nikomatsakis I've added a quote from Nick Lewycky (whom I've mentioned a few times before and whom I've invited to join this group) to the document. I think it has some overlap with some other sections, but, unlike other arguments for letting extern "C" unwind-by-default, actually seems like a reasonable argument _not_ to introduce extern "C nounwind".

Kyle Strand (Oct 30 2019 at 18:09, on Zulip):

@Amanieu I would also like to hear your reaction to that quote

Amanieu (Oct 30 2019 at 18:13, on Zulip):

Well, you can't really capture exceptions in C, but you can definitely throw them (just call _Unwind_RaiseException).

Amanieu (Oct 30 2019 at 18:16, on Zulip):

IMO the main argument is that extern "C" -> extern "C nounwind" is an optimization, which extern "C" -> extern "C unwind" is actually needed for correctness.

Amanieu (Oct 30 2019 at 18:17, on Zulip):

Also we avoid any issues with bumping the libc version, since extern "C nounwind" fn will coerce to extern "C" fn.

Kyle Strand (Oct 30 2019 at 18:23, on Zulip):

Well, you can't really capture exceptions in C, but you can definitely throw them (just call _Unwind_RaiseException).

Isn't Nick's statement that you could catch them with a library function (the way Rust does) correct?

Kyle Strand (Oct 30 2019 at 18:24, on Zulip):

(I guess I'm still not sure how that actually works; it seems like it would need to set up a new frame with a landing pad...)

Amanieu (Oct 30 2019 at 18:53, on Zulip):

You would need to attach a custom personality function and generate the necessary landing pads. I'm pretty sure you can't do either even with GCC-specific extensions.

nikomatsakis (Nov 01 2019 at 15:29, on Zulip):

so -- obviously this remains the big topic dejour

nikomatsakis (Nov 01 2019 at 15:29, on Zulip):

I no longer like my framing (i.e., the topic of this zulip thread), in that I think that the set of interesting options is a bit more... entangled.

nikomatsakis (Nov 01 2019 at 15:30, on Zulip):

I was thinking about how to reorganize the information in the hackmd

nikomatsakis (Nov 01 2019 at 15:30, on Zulip):

I was thinking about trying to have a "Considerations" section that tries to outline major blocks of considerations, and then have a proposal section that goes through various possible designs and discusses their impact on the considerations

nikomatsakis (Nov 01 2019 at 15:30, on Zulip):

I think the proposals would be:

nikomatsakis (Nov 01 2019 at 15:30, on Zulip):
nikomatsakis (Nov 01 2019 at 15:31, on Zulip):
nikomatsakis (Nov 01 2019 at 15:32, on Zulip):
nikomatsakis (Nov 01 2019 at 15:32, on Zulip):
nikomatsakis (Nov 01 2019 at 15:32, on Zulip):

I guess there are basically two orthogonal facets

nikomatsakis (Nov 01 2019 at 15:33, on Zulip):
nikomatsakis (Nov 01 2019 at 15:33, on Zulip):

but I'm not sure they're orthogonal in terms of the overall design space

nikomatsakis (Nov 01 2019 at 15:34, on Zulip):

(in other words, it feels like we might want to decide them together, though I'm trying to elaborate why I thought that now)

Kyle Strand (Nov 01 2019 at 15:42, on Zulip):

Let me think about how to organize the dock and give you an outline later, without doing the actual verbiage reorg

Kyle Strand (Nov 01 2019 at 15:43, on Zulip):

I want to spend a bit of time on the release notes blog today if possible, and over the weekend update the discussion/status summaries

nikomatsakis (Nov 01 2019 at 16:23, on Zulip):

"release notes blog"?

Kyle Strand (Nov 01 2019 at 16:37, on Zulip):

Er, release blog post.

nikomatsakis (Nov 07 2019 at 18:17, on Zulip):

Let me think about how to organize the dock and give you an outline later, without doing the actual verbiage reorg

@Kyle Strand were you ever able to make progress on this?

Kyle Strand (Nov 07 2019 at 18:19, on Zulip):

Not really, unfortunately. I didn't even get a chance to help out with the blog post.

Last update: Nov 15 2019 at 09:45UTC