New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Unsized rvalues: implement boxed closure impls. #55431

Open
wants to merge 6 commits into
base: master
from

Conversation

@qnighy
Contributor

qnighy commented Oct 28, 2018

This pull request contains boxed_closure_impls that provides long-hoped three impls:

impl<A, F: FnOnce<A> + ?Sized> FnOnce<A> for Box<F> { .. }
impl<A, F: FnMut<A> + ?Sized> FnMut<A> for Box<F> { .. }
impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> { .. }

This has been blocked by several reasons; see FnBox #28796 for details.

Now that #48055 is (partly) implemented, we're ready to introduce the above impls, replacing existing FnBox workarounds.

There are two major concerns, however.

Major concern 1: instability

I think these impls should be introduced as an unstable feature first, mainly because it relies on unsized rvalues. However, impl itself can't stand as unstable; all existing unstable features are tied with functions, methods, or types. I tried putting #[unstable] on the impls but that didn't work. I'll mark this PR as [WIP] until it is resolved.

Major concern 2: compatibility with FnBox

I'm not really sure, but FnBox may be widely used in the nightly world. Although unstable features may regress, it's good if there's a path for gradual migration. It can be done in the following way:

  • Make FnBox a subtrait of FnOnce. This ensures that dyn FnBox implements FnOnce.
  • Make use of specialization to avoid overlap between FnOnce impls for Box<impl FnOnce> and Box<dyn FnBox>.

I believe that this minimizes breakage of crates that use FnBox.

Minor concern: feature name and tracking issue

I currently assign boxed_closure_impls as the name and #48055 as the tracking issue. I'll prepare a separate tracking issue when the Major Concern 1 is resolved.

@rust-highfive

This comment has been minimized.

Collaborator

rust-highfive commented Oct 28, 2018

r? @frewsxcv

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive

This comment was marked as resolved.

Collaborator

rust-highfive commented Oct 28, 2018

The job x86_64-gnu-llvm-5.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_time:end:01148c20:start=1540709908911124858,finish=1540709963285862772,duration=54374737914
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#Pull-Requests-and-Security-Restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
Setting environment variables from .travis.yml
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
---
[00:48:58] .................................................................................................... 100/4972
[00:49:01] .................................................................................................... 200/4972
[00:49:04] .................................................................................................... 300/4972
[00:49:07] .................................................................................................... 400/4972
[00:49:11] ..................................FF................................................................ 500/4972
[00:49:19] .................................................................................................... 700/4972
[00:49:26] ...........................................................i...........i............................ 800/4972
[00:49:29] .............................................................................iiiii.................. 900/4972
[00:49:33] .................................................................................................... 1000/4972
---
[00:51:12] .................................................................................................... 4000/4972
[00:51:15] .................................................................................................... 4100/4972
[00:51:19] ......................................................................i............................. 4200/4972
[00:51:25] .................................................................................................... 4300/4972
[00:51:28] ........................................................F........................................... 4400/4972
[00:51:36] ..........................................i......................................................... 4600/4972
[00:51:40] .................................................................................................... 4700/4972
[00:51:46] .................................................................................................... 4900/4972
[00:51:46] .................................................................................................... 4900/4972
/two-phase-nonrecv-autoref.rs","byte_start":4970,"byte_end":4983,"line_start":139,"line_end":139,"column_start":5,"column_end":18,"is_primary":false,"text":[{"text":"    double_access(&mut a, &a);","highlight_start":5,"highlight_end":18}],"label":"mutable borrow later used by call","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable\n  --> /checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs:139:27\n   |\nLL |     double_access(&mut a, &a);\n   |     ------------- ------  ^^ immutable borrow occurs here\n   |     |             |\n   |     |             mutable borrow occurs here\n   |     mutable borrow later used by call\n\n"}
[00:51:48] {"message":"cannot borrow `i` as immutable because it is also borrowed as mutable","code":{"code":"E0502","explanation":"\nThis error indicates that you are trying to borrow a variable as mutable when it\nhas already been borrowed as immutable.\n\nExample of erroneous code:\n\n```compile_fail,E0502\nfn bar(x: &mut i32) {}\nfn foo(a: &mut i32) {\n    let ref y = a; // a is borrowed as immutable.\n    bar(a); // error: cannot borrow `*a` as mutable because `a` is also borrowed\n            //        as immutable\n}\n```\n\nTo fix this error, ensure that you don't have any other references to the\nvariable before trying to access it mutably:\n\n```\nfn bar(x: &mut i32) {}\nfn foo(a: &mut i32) {\n    bar(a);\n    let ref y = a; // ok!\n}\n```\n\nFor more information on the rust ownership system, take a look at\nhttps://doc.rust-lang.org/stable/book/refstart":5787,"byte_end":5788,"line_start":167,"line_end":167,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":"    i[i[3]] = 4;","highlight_start":7,"highlight_end":8}],"label":"immutable borrow occurs here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs","byte_start":5785,"byte_end":5786,"line_start":167,"line_end":167,"column_start":5,"column_end":6,"is_primary":false,"text":[{"text":"    i[i[3]] = 4;","highlight_start":5,"highlight_end":6}],"label":"mutable borrow occurs here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs","byte_start":5791,"byte_end":5792,"line_start":167,"line_end":167,"column_start":11,"column_end":12,"is_primary":false,"text":[{"text":"    i[i[3]] = 4;","highlight_start":11,"highlight_end":12}],"label":"mutable borrow ends here","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable\n  --> /checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs:167:7\n   |\nLL |     i[i[3]] = 4;\n   |     - ^   - mutable borrow ends here\n   |     | |\n   |     | immutable borrow occurs here\n   |     mutable borrow occurs here\n\n"}
[00:51:48] {"message":"cannot borrow `i` as immutable because it is also borrowed as mutable","code":{"code":"E0502","explanation":"\nThis error indicates that you are trying to borrow a variable as mutable when it\nhas already

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@rust-highfive

This comment was marked as resolved.

Collaborator

rust-highfive commented Oct 28, 2018

The job x86_64-gnu-llvm-5.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_time:end:00658f30:start=1540726071786761911,finish=1540726164927521186,duration=93140759275
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#Pull-Requests-and-Security-Restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
Setting environment variables from .travis.yml
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
---
[00:47:19] .................................................................................................... 100/4972
[00:47:22] .................................................................................................... 200/4972
[00:47:25] .................................................................................................... 300/4972
[00:47:28] .................................................................................................... 400/4972
[00:47:31] .................................F.F................................................................ 500/4972
[00:47:39] .................................................................................................... 700/4972
[00:47:44] ...........................................................i...........i............................ 800/4972
[00:47:47] .............................................................................iiiii.................. 900/4972
[00:47:51] .................................................................................................... 1000/4972
---
[00:49:23] .................................................................................................... 4000/4972
[00:49:26] .................................................................................................... 4100/4972
[00:49:29] ......................................................................i............................. 4200/4972
[00:49:34] .................................................................................................... 4300/4972
[00:49:37] ........................................................F........................................... 4400/4972
[00:49:44] ..........................................i......................................................... 4600/4972
[00:49:48] .................................................................................................... 4700/4972
[00:49:50] .................................................................................................... 4800/4972
[00:49:53] .................................................................................................... 4900/4972
[00:49:53] .................................................................................................... 4900/4972
[00:49:55] ...........i............................................................
[00:49:55] failures:
[00:49:55] 
[00:49:55] ---- [ui] ui/borrowck/two-phase-nonrecv-autoref.rs#ast stdout ----
[00:49:55] 
[00:49:55] error in revision `ast`: /checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs:79: unexpected error: '79:11: 79:12: use of moved value: `f` [E0382]'
[00:49:55] 
[00:49:55] error in revision `ast`: /checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs:95: unexpected error: '95:11: 95:12: use of moved value: `f` [E0382]'
[00:49:55] 
[00:49:55] error in revision `ast`: /checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs:79: expected error not found: use of moved value: `*f`
[00:49:55] 
[00:49:55] error in revision `ast`: /checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs:95: expected error not found: use of moved value: `*f`
[00:49:55] 
[00:49:55] error in revision `ast`: 2 unexpected errors found, 2 expected errors not found
[00:49:55] status: exit code: 1
[00:49:55] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs" "--target=x86_64-unknown-linux-gnu" "--cfg" "ast" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/borrowck/two-phase-nonrecv-autoref.ast/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/borrowck/two-phase-nonrecv-autoref.ast/auxiliary" "-A" "unused"
[00:49:55]     Error {
[00:49:55]         line_num: 79,
[00:49:55]         kind: Some(
[00:49:55]             Error
[00:49:55]             Error
[00:49:55]         ),
[00:49:55]         msg: "79:11: 79:12: use of moved value: `f` [E0382]"
[00:49:55]     Error {
[00:49:55]         line_num: 95,
[00:49:55]         kind: Some(
[00:49:55]             Error
[00:49:55]             Error
[00:49:55]         ),
[00:49:55]         msg: "95:11: 95:12: use of moved value: `f` [E0382]"
[00:49:55] ]
[00:49:55] 
[00:49:55] not found errors (from test file): [
[00:49:55]     Error {
[00:49:55]     Error {
[00:49:55]         line_num: 79,
[00:49:55]         kind: Some(
[00:49:55]             Error
[00:49:55]         ),
[00:49:55]         msg: "use of moved value: `*f`"
[00:49:55]     Error {
[00:49:55]         line_num: 95,
[00:49:55]         kind: Some(
[00:49:55]             Error
[00:49:55]             Error
[00:49:55]         ),
[00:49:55]         msg: "use of moved value: `*f`"
[00:49:55] ]
[00:49:55] 
[00:49:55] thread '[ui] ui/borrowck/two-phase-nonrecv-autoref.rs#ast' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:1358:13
[00:49:55] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[00:49:55] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[00:49:55] 
[00:49:55] ---- [ui] ui/borrowck/two-phase-nonrecv-autoref.rs#nll stdout ----
[00:49:55] 
[00:49:55] error in revision `nll`: /checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs:79: unexpected error: '79:11: 79:12: use of moved value: `f` [E0382]'
[00:49:55] 
[00:49:55] error in revision `nll`: /checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs:95: unexpected error: '95:11: 95:12: use of moved value: `f` [E0382]'
[00:49:55] 
[00:49:55] error in revision `nll`: /checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs:79: expected error not found: use of moved value: `*f`
[00:49:55] 
[00:49:55] error in revision `nll`: /checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs:95: expected error not found: cannot move a value of type
[00:49:55] 
[00:49:55] error in revision `nll`: /checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs:95: expected error not found: cannot move a value of type
[00:49:55] 
[00:49:55] error in revision `nll`: /checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs:95: expected error not found: use of moved value: `*f`
[00:49:55] 
[00:49:55] error in revision `nll`: 2 unexpected errors found, 4 expected errors not found
[00:49:55] status: exit code: 1
[00:49:55] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/borrowck/two-phase-nonrecv-autoref.rs" "--target=x86_64-unknown-linux-gnu" "--cfg" "nll" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/borrowck/two-phase-nonrecv-autoref.nll/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-Z" "borrowck=mir" "-Z" "two-phase-borrows" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/borrowck/two-phase-nonrecv-autoref.nll/auxiliary" "-A" "unused"
[00:49:55]     Error {
[00:49:55]         line_num: 79,
[00:49:55]         kind: Some(
[00:49:55]             Error
[00:49:55]             Error
[00:49:55]         ),
[00:49:55]         msg: "79:11: 79:12: use of moved value: `f` [E0382]"
[00:49:55]     Error {
[00:49:55]         line_num: 95,
[00:49:55]         kind: Some(
[00:49:55]             Error
[00:49:55]             Error
[00:49:55]         ),
[00:49:55]         msg: "95:11: 95:12: use of moved value: `f` [E0382]"
[00:49:55] ]
[00:49:55] 
[00:49:55] not found errors (from test file): [
[00:49:55]     Error {
[00:49:55]     Error {
[00:49:55]         line_num: 79,
[00:49:55]         kind: Some(
[00:49:55]             Error
[00:49:55]         ),
[00:49:55]         msg: "use of moved value: `*f`"
[00:49:55]     Error {
[00:49:55]         line_num: 95,
[00:49:55]         kind: Some(
[00:49:55]             Error
---
[00:49:55]         line_num: 95,
[00:49:55]         kind: Some(
[00:49:55]             Error
[00:49:55]         ),
[00:49:55]         msg: "use of moved value: `*f`"
[00:49:55] ]
[00:49:55] 
[00:49:55] thread '[ui] ui/borrowck/two-phase-nonrecv-autoref.rs#nll' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:1358:13
[00:49:55] 
[00:49:55] 
[00:49:55] ---- [ui] ui/span/borrowck-call-is-borrow-issue-12224.rs stdout ----
[00:49:55] 
[00:49:55] error: /checkout/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs:44: unexpected error: '44:5: 44:8: cannot borrow field `f.f` of immutable binding as mutable [E0596]'
[00:49:55] 
[00:49:55] error: /checkout/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs:44: expected error not found: cannot borrow `Box` content `*f.f` of immutable binding as mutable
[00:49:55] error: 1 unexpected errors found, 1 expected errors not found
[00:49:55] status: exit code: 1
[00:49:55] status: exit code: 1
[00:49:55] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/span/borrowck-call-is-borrow-issue-12224/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/span/borrowck-call-is-borrow-issue-12224/auxiliary" "-A" "unused"
[00:49:55]     Error {
[00:49:55]         line_num: 44,
[00:49:55]         kind: Some(
[00:49:55]             Error
[00:49:55]             Error
[00:49:55]         ),
[00:49:55]         msg: "44:5: 44:8: cannot borrow field `f.f` of immutable binding as mutable [E0596]"
[00:49:55] ]
[00:49:55] 
[00:49:55] not found errors (from test file): [
[00:49:55]     Error {
[00:49:55]     Error {
[00:49:55]         line_num: 44,
[00:49:55]         kind: Some(
[00:49:55]             Error
[00:49:55]         ),
[00:49:55]         msg: "cannot borrow `Box` content `*f.f` of immutable binding as mutable"
[00:49:55] ]
[00:49:55] 
[00:49:55] thread '[ui] ui/span/borrowck-call-is-borrow-issue-12224.rs' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:1358:13
[00:49:55] 
---
[00:49:55] 
[00:49:55] thread 'main' panicked at 'Some tests failed', tools/compiletest/src/main.rs:503:22
[00:49:55] 
[00:49:55] 
[00:49:55] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnuout!\(.*\)|\1|;y|!|/|'); if [ -f "$EXE" ]; then printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE"; gdb --batch -q -c "$CORE" "$EXE" -iex 'set auto-load off' -iex 'dir src/' -iex 'set sysroot .' -ex bt -ex q; echo travis_fold":"end:crashlog; fi; done || true
travis_fold:end:after_failure.4
travis_fold:start:after_failure.5
travis_time:start:06917076
travis_time:start:06917076
$ cat ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers || true
cat: ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers: No such file or directory
travis_fold:end:after_failure.5
travis_fold:start:after_failure.6
travis_time:start:0696c702
$ dmesg | grep -i kill

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@rust-highfive

This comment has been minimized.

Collaborator

rust-highfive commented Oct 28, 2018

The job x86_64-gnu-llvm-5.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_time:end:0f20aec0:start=1540737014979086364,finish=1540737068428273499,duration=53449187135
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#Pull-Requests-and-Security-Restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
Setting environment variables from .travis.yml
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
---
[00:51:15] .................................................................................................... 2200/4972
[00:51:19] .................................................................................................... 2300/4972
[00:51:23] .................................................................................................... 2400/4972
[00:51:27] .................................................................................................... 2500/4972
[00:51:30] ............................................................iiiiiiiii............................... 2600/4972
[00:51:37] ..........ii........................................................................................ 2800/4972
[00:51:39] .................................................................................................... 2900/4972
[00:51:43] .................................................................................................... 3000/4972
[00:51:46] .....i.............................................................................................. 3100/4972
---
travis_time:start:test_codegen
Check compiletest suite=codegen mode=codegen (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[01:04:41] 
[01:04:41] running 112 tests
[01:04:44] i..ii...iii.......i...i.........i..iii...........i.....i.....ii...i..i.ii..............i...ii..ii.i. 100/112
[01:04:44] test result: ok. 82 passed; 0 failed; 30 ignored; 0 measured; 0 filtered out
[01:04:44] 
[01:04:44]  finished in 3.451
[01:04:44] travis_fold:end:test_codegen
---
[01:39:47] 
[01:39:47] 
[01:39:47] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[01:39:47] Build completed unsuccessfully in 0:53:20
[01:39:47] make: *** [check] Error 1
[01:39:47] Makefile:58: recipe for target 'check' failed

The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:03b33118
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
---
travis_time:end:133bb880:start=1540743076301033206,finish=1540743076305694415,duration=4661209
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:0beb0618
$ ln -s . checkout && for CORE in obj/cores/core.*; do EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|'); if [ -f "$EXE" ]; then pr

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@bjorn3

This comment has been minimized.

Contributor

bjorn3 commented Oct 28, 2018

@TimNN ^ not very helpful

@alexreg

This comment has been minimized.

Contributor

alexreg commented Nov 5, 2018

FnBox was only ever a stop-gap solution, and highly unstable. I really wouldn't worry about migration, and would just obsolete it immediately in favour of this, if it works just as well/better in all circumstances.

@Mark-Simulacrum

This comment has been minimized.

Member

Mark-Simulacrum commented Nov 15, 2018

I've re-assigned this to @nikomatsakis since I think it'll probably want lang/compiler team discussion or review.

@Aaronepower

This comment has been minimized.

Contributor

Aaronepower commented Nov 25, 2018

Triage; @nikomatsakis Hello, have you been able to get back to this PR?

@Dylan-DPC

This comment has been minimized.

Member

Dylan-DPC commented Dec 3, 2018

CI fails with:

[01:39:47] failures:
[01:39:47] 
[01:39:47] ---- /checkout/src/doc/unstable-book/src/library-features/boxed-closure-impls.md - boxed_closure_impls::Usage (line 27) stdout ----
[01:39:47] error[E0057]: this function takes 1 parameter but 0 parameters were supplied
[01:39:47]   --> /checkout/src/doc/unstable-book/src/library-features/boxed-closure-impls.md:40:5
[01:39:47]    |
[01:39:47] 14 |     f();
[01:39:47]    |     ^^^ expected 1 parameter
[01:39:47] 
[01:39:47] thread '/checkout/src/doc/unstable-book/src/library-features/boxed-closure-impls.md - boxed_closure_impls::Usage (line 27)' panicked at 'couldn't compile the test', librustdoc/test.rs:332:13
[01:39:47] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[01:39:47] 
[01:39:47] 
[01:39:47] failures:
[01:39:47]     /checkout/src/doc/unstable-book/src/library-features/boxed-closure-impls.md - boxed_closure_impls::Usage (line 27)
[01:39:47] 
[01:39:47] test result: FAILED. 0 passed; 1 failed; 4 ignored; 0 measured; 0 filtered out
[01:39:47] 
[01:39:47] 
[01:39:47] stderr ----
[01:39:47] 
[01:39:47] 
[01:39:47] 
[01:39:47] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[01:39:47] Build completed unsuccessfully in 0:53:20
[01:39:47] make: *** [check] Error 1
[01:39:47] Makefile:58: recipe for target 'check' failed
@Dylan-DPC

This comment has been minimized.

Member

Dylan-DPC commented Dec 3, 2018

Pinging from triage @rust-lang/compiler can anyone review this?

@eddyb

This comment has been minimized.

Member

eddyb commented Dec 3, 2018

This is not really a compiler change. Maybe @rust-lang/lang + @rust-lang/libs?

@cramertj

This comment has been minimized.

Member

cramertj commented Dec 3, 2018

@eddyb I think it is compiler-relevant since one of the core questions in the PR description is how to make use of the new impls unstable:

However, impl itself can't stand as unstable; all existing unstable features are tied with functions, methods, or types. I tried putting #[unstable] on the impls but that didn't work. I'll mark this PR as [WIP] until it is resolved.

This isn't possible today, and it's hard for me to understand how it could become possible: we'd have to somehow gate all coercions, where clauses, transitive uses (e.g. trait MyTrait {} impl<T> MyTrait for T where T: FnOnce() { ... }) etc. I'm personally fine exposing this from the lang side as it seems obvious that these impls should exist somehow. The only hold-up I would have is if we accidentally make it backwards-incompatible to change the impl of FnOnce for Box<T> to avoid alloca by passing self by-pointer and dropping the allocated memory after the call. I can't think of many reasonable ways that a user could be relying on the alloca + move-to-stack occurring, though, so I think this is fine and I don't see a reason not to land these impls now that we finally can.

@eddyb

This comment has been minimized.

Member

eddyb commented Dec 3, 2018

@cramertj I think that's a lang team discussion topic - that is, whether we should just stabilize now, given that feature-gating is hard (or even impossible).
Maybe we should start an FCP merge on this PR?

@cramertj

This comment has been minimized.

Member

cramertj commented Dec 3, 2018

@rfcbot fcp merge

This change introduces the following (insta-stable) trait impls:

impl<A, F: FnOnce<A> + ?Sized> FnOnce<A> for Box<F> { .. }
impl<A, F: FnMut<A> + ?Sized> FnMut<A> for Box<F> { .. }
impl<A, F: Fn<A> + ?Sized> Fn<A> for Box<F> { .. }

Defining these impls requires the use of the unsized_locals feature and we'd ideally like to gate these impls since they rely on unstable features in order to make it possible to implement them (i.e. it's not just this particular impl that is unstable as with e.g. most of std, but implementing them at all is impossible without the unstable feature or some extra-clever and probably UB hacks).

However, we don't have the machinery (and possibly won't ever have the machinery) to make trait impls unstable. As such, merging this PR makes Box<FnOnce()> instantly call-able on stable.

These implementations have been desired for a long time but have been impossible to add until now. I'm not sure of any other reasonable ways to implement them, or any ways that we might want to change the implementations going forward in a user-observable way.

@rfcbot

This comment has been minimized.

rfcbot commented Dec 3, 2018

Team member @cramertj has proposed to merge this. The next step is review by the rest of the tagged teams:

Concerns:

Once a majority of reviewers approve (and none object), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@Centril

This comment has been minimized.

Contributor

Centril commented Dec 3, 2018

Is there a particular reason to stabilize these impls now rather than to wait until unsized_locals is stable?

@alexreg

This comment has been minimized.

Contributor

alexreg commented Dec 3, 2018

@Centril The surface area is much smaller for these three impls, I guess, and they cover a large portion of the urgent demand for unsized locals at the same time.

@alexcrichton

This comment has been minimized.

Member

alexcrichton commented Dec 4, 2018

@rfcbot concern unimplementable-if-unsized-does-not-pan-out

Historically we've avoiding expanding the stable API surface area of the standard library with unstable features. One of the best examples here is specialization where we've exclusively used it so far for performance improvements and we haven't started to use it for actually expanding trait impls yet. The rationale for this is that we can probably recover performance via other means if absolutely necessary if the unstable feature (specialization) doesn't pan out.

Do we have a similar recourse for this? What if the unstable feature doesn't pan out? Are we confident enough that we can provide this implementation for all of time?

@cramertj

This comment has been minimized.

Member

cramertj commented Dec 4, 2018

@alexcrichton So I'd argue this is implementable even if the current unsized-rvalues-using-alloca proposal doesn't shake out-- we can still pass self by-pointer into the method and clean up the memory for the Box after the fact, or add a vtable shim to FnOnce specifically that takes Box<Self>. I think we definitely want self-by-value to be object-safe for all the benefits it gives, so I'd argue we want something that can provide this functionality regardless of whether the current feature as-implemented shakes out.

Compared with specialization, where exactly which implementations are allowed and when overlaps may occur is still open to soundness-related debate, the likelihood of the API surface needing to change here is far smaller. Basically the only thing that's being promised here is "there is some way to call FnOnce::call_once on a Box<dyn FnOnce()>". I think there are enough alternatives (pass-by-pointer, a special vtable shim which takes Box<Self>, etc.) that we can feel safe providing this API.

@cramertj

This comment has been minimized.

Member

cramertj commented Dec 4, 2018

@Centril

Is there a particular reason to stabilize these impls now rather than to wait until unsized_locals is stable?

Box<dyn FnOnce(..) -> ...> working would be a massive improvement to the ergonomics of lots of code which currently relies on hacky custom traits for every function signature needed. As I said above in my response to @alexcrichton, I feel like the API surface being provided here is high value, small, and low-risk enough that it needn't be blocked by the much larger and more complex unsized_locals feature.

@alexcrichton

This comment has been minimized.

Member

alexcrichton commented Dec 4, 2018

@rfcbot resolve unimplementable-if-unsized-does-not-pan-out

Sounds solid to me, thanks for the explanation!

However, since `unsized_locals` is a very young feature, we're careful about
this `FnOnce` impl now.
There's another reason for instability: for compatibility with `fnbox`,

This comment has been minimized.

@cramertj

cramertj Dec 4, 2018

Member

There isn't a way for users to observe this on stable, and IMO we should deprecate and remove FnBox as soon as possible so we can remove the default here.

@dtolnay

This comment has been minimized.

Member

dtolnay commented Dec 5, 2018

Just to confirm -- this is also going to work for Box<FnOnce() + Send>, Box<FnOnce() + Sync>, Box<FnOnce() + Send + Sync> right?

@Centril

This comment has been minimized.

Contributor

Centril commented Dec 5, 2018

@rfcbot concern i-need-to-think-about-this

@xfix xfix referenced this pull request Dec 9, 2018

Open

Remove uses of FnBox #851

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment