Skip to content
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

Implement object-safety for arbitrary_self_types #50173

Closed

Conversation

mikeyhew
Copy link
Contributor

@mikeyhew mikeyhew commented Apr 23, 2018

r? @nikomatsakis
cc @withoutboats @arielb1 @eddyb

This is a work-in-progress PR that I am opening so that I can ask people questions as I implement it. Currently, I've added a single run-pass test that shows the ultimate goal of this PR in its most general form.

Custom method receivers, that is, anything except for self, &self, &mut self and self: Box<Self>, are currently considered non-object-safe. This PR will relax that restriction, and will allow any receiver that can be coerced from its fat version (containing the vtable) to its thin version (without a vtable). To check this, we require the following trait obligation to be satisfied:

forall<U> {
    if (Self: Unsize<U>) {
        Receiver: CoerceUnsized<Receiver<Self=U>>
    }
}

where Receiver is the type of the method's self argument, and the Receiver<Self=U> syntax means Receiver but with all instances of Self replaced with U.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 23, 2018
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-3.9 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.
[00:06:52]    Compiling rustc_errors v0.0.0 (file:///checkout/src/librustc_errors)
[00:08:51]    Compiling rustc_const_math v0.0.0 (file:///checkout/src/librustc_const_math)
[00:08:51]    Compiling proc_macro v0.0.0 (file:///checkout/src/libproc_macro)
[00:09:23]    Compiling syntax_ext v0.0.0 (file:///checkout/src/libsyntax_ext)
[00:09:28] error[E0433]: failed to resolve. Use of undeclared type or module `std`
[00:09:28]    --> librustc/traits/object_safety.rs:323:24
[00:09:28]     |
[00:09:28] 323 |                 .chain(std::iter::once(&predicate))
[00:09:28]     |                        ^^^ Use of undeclared type or module `std`
[00:09:28] 
[00:09:29] error[E0412]: cannot find type `Predicate` in this scope
[00:09:29]    --> librustc/traits/object_safety.rs:322:36
[00:09:29]     |
[00:09:29] 322 |             let caller_bounds: Vec<Predicate<'tcx>> = param_env.caller_bounds.iter()
[00:09:29]     |                                    ^^^^^^^^^ not found in this scope
[00:09:29] help: possible candidate is found in another module, you can import it into scope
[00:09:29] 20  | use ty::Predicate;
[00:09:29]     |
[00:09:29] 
[00:10:03] error: unreachable statement
[00:10:03] error: unreachable statement
[00:10:03]    --> librustc/traits/object_safety.rs:314:9
[00:10:03]     |
[00:10:03] 314 | /         let param_env = {
[00:10:03] 315 | |             let mut param_env = self.param_env(method.def_id);
[00:10:03] 316 | |
[00:10:03] 317 | |             let predicate = ty::TraitRef {
[00:10:03] ...   |
[00:10:03] 328 | |             param_env
[00:10:03] 329 | |         };
[00:10:03]     |
[00:10:03]     |
[00:10:03]     = note: `-D unreachable-code` implied by `-D warnings`
[00:10:03] 
[00:10:03] error[E0599]: no method named `to_predicate` found for type `ty::sty::TraitRef<'_>` in the current scope
[00:10:03]    --> librustc/traits/object_safety.rs:320:15
[00:10:03]     |
[00:10:03] 320 |             }.to_predicate();
[00:10:03]     | 
[00:10:03]     | 
[00:10:03]    ::: librustc/ty/sty.rs:543:1
[00:10:03]     |
[00:10:03] 543 | pub struct TraitRef<'tcx> {
[00:10:03]     | ------------------------- method `to_predicate` not found for this
[00:10:03]     |
[00:10:03]     = help: items from traits can only be used if the trait is in scope
[00:10:03]     = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
[00:10:03]             candidate #1: `use ty::ToPredicate;`
[00:10:03] 
[00:10:03] error[E0599]: no method named `subst` found for type `&'tcx ty::TyS<'tcx>` in the current scope
[00:10:03]    --> librustc/traits/object_safety.rs:346:46
[00:10:03]     |
[00:10:03] 346 |         let target_receiver_ty = receiver_ty.subst(
[00:10:03]     |
[00:10:03]     |
[00:10:03]     = help: items from traits can only be used if the trait is in scope
[00:10:03]     = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
[00:10:03]             candidate #1: `use ty::subst::Subst;`

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)

@mikeyhew
Copy link
Contributor Author

It looks like, in order to do the CoerceUnsized check described above, the object-safety checks are going to need a SelectionContext. Currently, the object-safety checks are implemented as methods on TyCtxt, and are callable inside and outside of inference. That will have to be refactored so that the object-safety methods operate on an InferCtxt or SelectionContext. This PR is blocked on that refactoring.

@mikeyhew mikeyhew force-pushed the arbitrary-self-types-object-safety branch from 7905214 to a234899 Compare April 23, 2018 06:34
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-3.9 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:start:test_run-pass
Check compiletest suite=run-pass mode=run-pass (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[00:52:33] 
[00:52:33] running 2966 tests
[00:52:50] ................F...................................................................................
[00:53:27] ....................................................................................................
[00:53:43] ....................................................................................................
[00:53:59] ....................................................................................................
[00:54:23] ....................................................................................................
---
[01:03:54] ....................................................................................................
[01:04:13] ..................................................................
[01:04:13] failures:
[01:04:13] 
[01:04:13] ---- [run-pass] run-pass/arbitrary_self_types_pointers_and_wrappers.rs stdout ----
[01:04:13] error: compilation failed!
[01:04:13] status: exit code: 101
[01:04:13] status: exit code: 101
[01:04:13] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-pass" "--target=x86_64-unknown-linux-gnu" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-pass/arbitrary_self_types_pointers_and_wrappers.stage2-x86_64-unknown-linux-gnu" "-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/run-pass/arbitrary_self_types_po3990968 .
2727276 ./obj/build
1967992 ./obj/build/x86_64-unknown-linux-gnu
722092 ./src
569160 ./obj/build/bootstrap
---
149124 ./src/llvm-emscripten/test
148948 ./.git/modules
148944 ./.git/modules/src
122708 ./obj/build/bootstrap/debug/incremental/bootstrap-1sil8jgb030ka
122704 ./obj/build/bootstrap/debug/incremental/bootstrap-1sil8jgb030ka/s-f0dlsc2ho6-9mypsc-2f3cmz1knheyt
110008 ./obj/build/x86_64-unknown-linux-gnu/stage0-tools/x86_64-unknown-linux-gnu
110004 ./obj/build/x86_64-unknown-linux-gnu/stage0-tools/x86_64-unknown-linux-gnu/release
106104 ./obj/build/x86_64-unknown-linux-gnu/stage0-tools/x86_64-unknown-linux-gnu/release/deps
102808 ./obj/build/x86_64-unknown-linux-gnu/stage0/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends
102808 ./obj/build/x86_64-unknown-linux-gnu/stage0/lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends
101924 ./obj/build/bootstrap/debug/incremental/bootstrap-2s8ik7x786gic
101920 ./obj/build/bootstrap/debug/incremental/bootstrap-2s8ik7x786gic/s-f0dn2jz4ts-ewpepo-8chh8umqc096
89224 ./obj/build/x86_64-unknown-linux-gnu/stage1
89200 ./obj/build/x86_64-unknown-linux-gnu/stage1/lib
88080 ./obj/build/x86_64-unknown-linux-gnu/stage1-std/x86_64-unknown-linux-gnu/release/incremental/core-31lccp6wy7orz
88080 ./obj/build/x86_64-unknown-linux-gnu/stage1-std/x86_64-unknown-linux-gnu/release/incremental/core-31lccp6wy7orz
88076 ./obj/build/x86_64-unknown-linux-gnu/stage1-std/x86_64-unknown-linux-gnu/release/incremental/core-31lccp6wy7orz/s-f0dmznt0f1-1fxfs2a-3by8jin3pp2v3
84852 ./obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/deps
81100 ./obj/build/x86_64-unknown-linux-gnu/doc/std
78760 ./obj/build/x86_64-unknown-linux-gnu/stage0-tools/release
78700 ./obj/build/x86_64-unknown-linux-gnu/stage0-sysroot

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)

@eddyb
Copy link
Member

eddyb commented Apr 24, 2018

@mikeyhew My suggestion lately has been to do the check that a CoerceUnsized impl is valid from object safety checks, but not use CoerceUnsized itself, because it's too flexible.
However, I'm not sure anymore that even makes any sense, since you would need a different opt-in trait, so maybe it should be a combination of Deref, CoerceUnsized, and custom checks.

The problems I've been thinking of arise when the CoerceUnsized impl is "irreversible", e.g. it goes from &mut T to *mut U or from &mut T to &U. I think the only way to be sure is to check that a recursive traversal on the fields that CoerceUnsized would have to convert, at every level, eventually reaches a leaf raw pointer or a reference (i.e. not some associated type trickery), given unknown trait parameters, including Self (IOW, all parameters being under a forall).

(BTW I think typeof(self)[U/Self] is more "standard" notation for the substituted type, although I prefer something like typeof(self)[Self -> U] because it's easier to read at a glance.)

@nikomatsakis
Copy link
Contributor

Hmm, I remember that I really wanted to revisit the way that the "coerce unsized" check works in general. I need to go refresh my memory I guess.

PS thanks a ton @mikeyhew for starting in on this! Sorry I've not had time for feedback yet.

@shepmaster
Copy link
Member

Ping from triage, @nikomatsakis — will you have time to check on this soon?

@shepmaster shepmaster added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 6, 2018
@mikeyhew mikeyhew force-pushed the arbitrary-self-types-object-safety branch from a234899 to ede12aa Compare May 10, 2018 19:51
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-3.9 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:start:test_run-pass
Check compiletest suite=run-pass mode=run-pass (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[00:51:47] 
[00:51:47] running 2980 tests
[00:52:04] ................F...................................................................................
[00:52:41] ....................................................................................................
[00:52:57] ....................................................................................................
[00:53:13] ....................................................................................................
[00:53:37] ....................................................................................................
---
[00:58:30] .........test [run-pass] run-pass/mir_heavy_promoted.rs has been running for over 60 seconds
[00:59:00] ...........................................................................................
[00:59:20] ..................................................................................ii................
[01:00:18] ..............................................i....................................................i
[01:00:22] .ii.......test [run-pass] run-pass/saturating-float-casts.rs has been running for over 60 seconds
[01:01:21] .......iiiiiii......................................................................................
[01:01:43] ....................................................................................................
[01:02:03] ....................................................................................................
[01:02:23] ................................................................................
[01:02:23] ................................................................................
[01:02:23] failures:
[01:02:23] 
[01:02:23] ---- [run-pass] run-pass/arbitrary_self_types_pointers_and_wrappers.rs stdout ----
[01:02:23] error: compilation failed!
[01:02:23] status: exit code: 101
[01:02:23] status: exit code: 101
[01:02:23] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-pass" "--target=x86_64-unknown-linux-gnu" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-pass/arbitrary_self_types_pointers_and_wrappers.stage2-x86_64-unknown-linux-gnu" "-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/run-pass/arbitrary_self_types_pointers_and_wrappers.stage2-x86_64-unknown-linux-gnu.aux"
[01:02:23] ------------------------------------------
[01:02:23] 
[01:02:23] ------------------------------------------
[01:02:23] stderr:
[01:02:23] stderr:
[01:02:23] ------------------------------------------
[01:02:23] error[E0599]: no method named `ptr_wrapper` found for type `Ptr<Wrapper<std::fmt::Debug>>` in the current scope
[01:02:23]   --> /checkout/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs:64:19
[01:02:23]    |
[01:02:23] 18 | struct Ptr<T: ?Sized>(Box<T>);
[01:02:23]    | ------------------------------ method `ptr_wrapper` not found for this
[01:02:23] ...
[01:02:23] 64 |     assert_eq!(pw.ptr_wrapper(), 5);
[01:02:23]    |
[01:02:23]    = help: items from traits can only be used if the trait is implemented and in scope
[01:02:23]    = help: items from traits can only be used if the trait is implemented and in scope
[01:02:23]    = note: the following trait defines an item `ptr_wrapper`, perhaps you need to implement it:
[01:02:23]            candidate #1: `Trait`
[01:02:23] 
[01:02:23] error[E0599]: no method named `wrapper_ptr_wrapper` found for type `Wrapper<Ptr<Wrapper<std::fmt::Debug>>>` in the current scope
[01:02:23]   --> /checkout/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs:67:20
[01:02:23]    |
[01:02:23] 30 | struct Wrapper<T: ?Sized>(T);
[01:02:23]    | ----------------------------- method `wrapper_ptr_wrapper` not found for this
[01:02:23] ...
[01:02:23] 67 |     assert_eq!(wpw.wrapper_ptr_wrapper(), 6);
[01:02:23]    |
[01:02:23]    = help: items from traits can only be used if the trait is implemented and in scope
[01:02:23]    = help: items from traits can only be used if the trait is implemented and in scope
[01:02:23]    = note: the following trait defines an item `wrapper_ptr_wrapper`, perhaps you need to implement it:
[01:02:23]            candidate #1: `Trait`
[01:02:23] error: aborting due to 2 previous errors
[01:02:23] 
[01:02:23] For more information about this error, try `rustc --explain E0599`.
[01:02:23] 
[01:02:23] 
[01:02:23] ------------------------------------------
[01:02:23] 
[01:02:23] thread '[run-pass] run-pass/arbitrary_self_types_pointers_and_wrappers.rs' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:3033:9
[01:02:23] 
[01:02:23] 
[01:02:23] failures:
[01:02:23]     [run-pass] run-pass/arbitrary_self_types_pointers_and_wrappers.rs
[01:02:23]     [run-pass] run-pass/arbitrary_self_types_pointers_and_wrappers.rs
[01:02:23] 
[01:02:23] test result: FAILED. 2960 passed; 1 failed; 19 ignored; 0 measured; 0 filtered out
[01:02:23] 
[01:02:23] thread 'main' panicked at 'Some tests failed', tools/compiletest/src/main.rs:492:22
[01:02:23] 
[01:02:23] 
[01:02:23] 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-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/run-pass" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-pass" "--stage-id" "stage2-x86_64-unknown-linux-gnu" "--mode" "run-pass" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-3.9/bin/FileCheck" "--host-rustcflags" "-Crpath -O -Zunstable-options " "--target-rustcflags" "-Crpath -O -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--docck-python" "/usr/bin/python2.7" "--lldb-python" "/usr/bin/python2.7" "--gdb" "/usr/bin/gdb" "--quiet" "--llvm-version" "3.9.1\n" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--llvm-components" "" "--llvm-cxxflags" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"
[01:02:23] 
[01:02:23] 
[01:02:23] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[01:02:23] Build completed unsuccessfully in 0:14:42
[01:02:23] Build completed unsuccessfully in 0:14:42
[01:02:23] make: *** [check] Error 1
[01:02:23] Makefile:58: recipe for target 'check' failed
112620 ./obj/build/x86_64-unknown-linux-gnu/stage0-tools/x86_64-unknown-linux-gnu
112616 ./obj/build/x86_64-unknown-linux-gnu/stage0-tools/x86_64-unknown-linux-gnu/release
108624 ./obj/build/x86_64-unknown-linux-gnu/stage0-tools/x86_64-unknown-linux-gnu/release/deps
103728 ./obj/build/bootstrap/debug/incremental/bootstrap-1x7l2oj4p22hp
103728 ./obj/build/bootstrap/debug/incremental/bootstrap-1x7l2oj4p22hp
103724 ./obj/build/bootstrap/debug/incremental/bootstrap-1x7l2oj4p22hp/s-f0wzxahbd3-1pt9yg9-1nozvcbv9keul
98508 ./obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/incremental
93500 ./obj/build/x86_64-unknown-linux-gnu/stage1
93476 ./obj/build/x86_64-unknown-linux-gnu/stage1/lib
90844 ./obj/build/x86_64-unknown-linux-gnu/stage1-std/x86_64-unknown-linux-gnu/release/incremental/core-31lccp6wy7orz
90844 ./obj/build/x86_64-unknown-linux-gnu/stage1-std/x86_64-unknown-linux-gnu/release/incremental/core-31lccp6wy7orz
90840 ./obj/build/x86_64-unknown-linux-gnu/stage1-std/x86_64-unknown-linux-gnu/release/incremental/core-31lccp6wy7orz/s-f0wzurp8ig-1ylfq8i-2w93x474pe4e6
87816 ./obj/build/x86_64-unknown-linux-gnu/doc/core
81436 ./obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/deps
80984 ./obj/build/x86_64-unknown-linux-gnu/doc/std
79036 ./obj/build/x86_64-unknown-linux-gnu/stage0-sysroot
---
60840 ./src/llvm-emscripten/lib
56092 ./obj/build/x86_64-unknown-linux-gnu/stage0/lib/rustlib/x86_64-unknown-linux-gnu/bin
55448 ./obj/build/x86_64-unknown-linux-gnu/stage0-rustc/release
53676 ./obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/incremental/syntax-33ta18b3panbi
53672 ./obj/build/x86_64-unknown-linux-gnu/stage1-rustc/x86_64-unknown-linux-gnu/release/incremental/syntax-33ta18b3panbi/s-f0wzwhtunt-etfjlr-2tybn1l6ckot6
48604 ./obj/build/x86_64-unknown-linux-gnu/stage0/bin
47984 ./obj/build/x86_64-unknown-linux-gnu/stage0-std
47104 ./src/test
46812 ./obj/build/x86_64-unknown-linux-gnu/stage1-std/release

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)

@TimNN
Copy link
Contributor

TimNN commented May 15, 2018

@nikomatsakis / @rust-lang/compiler: It looks like this PR needs your input to continue.

@mikeyhew
Copy link
Contributor Author

@TimNN, @nikomatsakis and I have been talking about this in Discord. It looks like this will be easier to implement the CoerceUnsized check once some trait system refactoring has landed — specifically, once evaluate_obligation and related methods are available on TyCtxt directly — so we're holding off on it for now.

I'm also working on refactoring the coerce_unsized method in rustc_typeck (#50753), and hopefully, once we figure that out, the object-safety checks in this PR can be implemented in a similar way.

@TimNN TimNN added S-blocked Status: Blocked on something else such as an RFC or other implementation work. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 22, 2018
@TimNN
Copy link
Contributor

TimNN commented May 22, 2018

Thanks for the update @mikeyhew. I've marked this PR is blocked, is there an issue or PR we can follow to see when this PR gets unblocked?

@mikeyhew
Copy link
Contributor Author

@TimNN there isn't one. #50753 is sort of a blocker in that it would be nice to do that before this, but it's not strictly necessary. I'll talk to @nikomatsakis on Discord soon, so we can figure out what specifically this PR is blocked on, and maybe open an issue or PR for that.

@pietroalbini pietroalbini added S-blocked Status: Blocked on something else such as an RFC or other implementation work. and removed S-blocked Status: Blocked on something else such as an RFC or other implementation work. labels Jun 4, 2018
@TimNN TimNN added A-allocators Area: Custom and system allocators and removed A-allocators Area: Custom and system allocators labels Jun 12, 2018
@TimNN TimNN added A-allocators Area: Custom and system allocators and removed A-allocators Area: Custom and system allocators labels Jun 26, 2018
@mikeyhew mikeyhew force-pushed the arbitrary-self-types-object-safety branch from ede12aa to 24b563a Compare July 13, 2018 16:03
@rust-highfive
Copy link
Collaborator

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.
[00:17:21]    Compiling rustc_msan v0.0.0 (file:///checkout/src/librustc_msan)
[00:17:22]    Compiling rustc_asan v0.0.0 (file:///checkout/src/librustc_asan)
[00:17:23]    Compiling rustc_lsan v0.0.0 (file:///checkout/src/librustc_lsan)
[00:17:23]    Compiling rustc_tsan v0.0.0 (file:///checkout/src/librustc_tsan)
[00:17:26] thread 'main' panicked at 'assertion failed: !value.has_escaping_regions()', librustc/ty/sty.rs:754:9
[00:17:26] 
[00:17:26] error: internal compiler error: unexpected panic
[00:17:26] 
[00:17:26] 
[00:17:26] note: the compiler unexpectedly panicked. this is a bug.
[00:17:26] 
[00:17:26] note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
[00:17:26] note: rustc 1.29.0-dev running on x86_64-unknown-linux-gnu
[00:17:26] 
[00:17:26] 
[00:17:26] note: compiler flags: -Z force-unstable-if-unmarked -C opt-level=2 -C prefer-dynamic -C debug-assertions=y -C link-args=-Wl,-rpath,$ORIGIN/../lib --crate-type lib
[00:17:26] 
[00:17:26] note: some of the compiler flags provided by cargo are hidden
[00:17:26] error: Could not compile `core`.
[00:17:26] 
[00:17:26] Caused by:
[00:17:26]   process didn't exit successfully: `/checkout/obj/build/bootstrap/debug/rustc --crate-name core libcore/lib.rs --color always --error-format json --crate-type lib --emit=dep-info,link -C opt-level=2 -C metadata=1cbcabaa1ea822b5 -C extra-filename=-1cbcabaa1ea822b5 --out-dir /checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/x86_64-unknown-linux-gnu/release/deps --target x86_64-unknown-linux-gnu -L dependency=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/x86_64-unknown-linux-gnu/release/deps -L dependency=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/release/deps` (exit code: 101)
[00:17:26]   process didn't exit successfully: `/checkout/obj/build/bootstrap/debug/rustc --crate-name core libcore/lib.rs --color always --error-format json --crate-type lib --emit=dep-info,link -C opt-level=2 -C metadata=1cbcabaa1ea822b5 -C extra-filename=-1cbcabaa1ea822b5 --out-dir /checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/x86_64-unknown-linux-gnu/release/deps --target x86_64-unknown-linux-gnu -L dependency=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/x86_64-unknown-linux-gnu/release/deps -L dependency=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/release/deps` (exit code: 101)
[00:17:26] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "build" "--target" "x86_64-unknown-linux-gnu" "-j" "4" "--release" "--locked" "--color" "always" "--features" "panic-unwind jemalloc backtrace" "--manifest-path" "/checkout/src/libstd/Cargo.toml" "--message-format" "json"
[00:17:26] expected success, got: exit code: 101
[00:17:26] thread 'main' panicked at 'cargo must succeed', bootstrap/compile.rs:1117:9
[00:17:26] travis_fold:end:stage1-std

[00:17:26] travis_time:end:stage1-std:start=1531498967729240718,finish=1531498981526380563,duration=13797139845


[00:17:26] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap build
[00:17:26] Build completed unsuccessfully in 0:13:59
[00:17:26] Makefile:28: recipe for target 'all' failed
[00:17:26] make: *** [all] Error 1

The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:0eddafa0
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
---
travis_time:end:09a2ba7b:start=1531498982105784632,finish=1531498982112169948,duration=6385316
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:01c1ee4e
$ head -30 ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers || true
head: cannot open ‘./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers’ for reading: No such file or directory
travis_fold:end:after_failure.4
travis_fold:start:after_failure.5
travis_time:start:0172d4ac
$ 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
Copy link
Collaborator

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:start:test_ui
Check compiletest suite=ui mode=ui (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[00:47:09] 
[00:47:09] running 1567 tests
[00:47:12] ............F.....................................................................................i.
[00:47:19] ....................................................................................................
[00:47:21] ....................................................................................................
[00:47:24] ....................................................................................................
[00:47:26] ....................................................................................................
[00:47:26] ....................................................................................................
[00:47:29] ....................................................................................................
[00:47:32] ....................................................................................................
[00:47:36] ....................................................................................................
[00:47:39] ....................................................................................................
[00:47:43] ........................................i...........................................................
[00:47:46] ..............................i.....................................................................
[00:47:50] ....................................................................................................
[00:47:53] ...................................F................................................................
[00:48:00] thread 'main' panicked at 'Some tests failed', tools/compiletest/src/main.rs:498:22
[00:48:00] ...................................................................
[00:48:00] failures:
[00:48:00] 
[00:48:00] 
[00:48:00] ---- [ui] ui/arbitrary-self-types-not-object-safe.rs stdout ----
[00:48:00] 
[00:48:00] error: ui test compiled successfully!
[00:48:00] status: exit code: 0
[00:48:00] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/arbitrary-self-types-not-object-safe.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/arbitrary-self-types-not-object-safe/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/arbitrary-seht_end":1}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error: internal compiler error: librustc/ty/subst.rs:425: Region parameter out of range when substituting in region 'a (root type=Some(&'a Self)) (index=1)\n\n"}
[00:48:00] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[00:48:00] note: Run with `RUST_BACKTRACE=1` for a backtrace.
[00:48:00] {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error\n\n"}
[00:48:00] 
[00:48:00] note: the compiler unexpectedly panicked. this is a bug.
[00:48:00] 
[00:48:00] note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
[00:48:00] note: rustc 1.29.0-dev running on x86_64-unknown-linux-gnu
[00:48:00] 
[00:48:00] 
[00:48:00] note: compiler flags: -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath
[00:48:00] 
[00:48:00] ------------------------------------------
[00:48:00] 
[00:48:00] thread '[ui] ui/span/dropck-object-cycle.rs' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:3162:9
---
travis_time:end:12926cd0:start=1531696441269220248,finish=1531696441276135294,duration=6915046
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:0c5a4ec6
$ 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 printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE"; gdb -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:00375784
travis_time:start:00375784
$ 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:093fa174
$ 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)

test includes `Rc`, `Arc,` `PinMut`, and `PinBox` as receiver types. To
be converted to a run-pass test once dynamic dispatch is implemented.
@rust-highfive
Copy link
Collaborator

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.
########################################################                  79.0%
######################################################################## 100.0%
[00:02:09] extracting /checkout/obj/build/cache/2018-08-01/cargo-beta-x86_64-unknown-linux-gnu.tar.gz
[00:02:09]     Updating registry `https://github.com/rust-lang/crates.io-index`
[00:02:32] error: the lock file needs to be updated but --locked was passed to prevent this
[00:02:32] failed to run: /checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo build --manifest-path /checkout/src/bootstrap/Cargo.toml --locked
[00:02:32] Makefile:81: recipe for target 'prepare' failed
[00:02:32] make: *** [prepare] Error 1
[00:02:33] Command failed. Attempt 2/5:
[00:02:33] Command failed. Attempt 2/5:
[00:02:34] error: the lock file needs to be updated but --locked was passed to prevent this
[00:02:34] failed to run: /checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo build --manifest-path /checkout/src/bootstrap/Cargo.toml --locked
[00:02:34] Makefile:81: recipe for target 'prepare' failed
[00:02:34] make: *** [prepare] Error 1
[00:02:36] Command failed. Attempt 3/5:
[00:02:36] Command failed. Attempt 3/5:
[00:02:36] error: the lock file needs to be updated but --locked was passed to prevent this
[00:02:36] failed to run: /checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo build --manifest-path /checkout/src/bootstrap/Cargo.toml --locked
[00:02:36] make: *** [prepare] Error 1
[00:02:36] Makefile:81: recipe for target 'prepare' failed
[00:02:39] Command failed. Attempt 4/5:
[00:02:39] Command failed. Attempt 4/5:
[00:02:39] error: the lock file needs to be updated but --locked was passed to prevent this
[00:02:39] failed to run: /checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo build --manifest-path /checkout/src/bootstrap/Cargo.toml --locked
[00:02:39] Makefile:81: recipe for target 'prepare' failed
[00:02:39] make: *** [prepare] Error 1
[00:02:43] Command failed. Attempt 5/5:
[00:02:43] Command failed. Attempt 5/5:
[00:02:44] error: the lock file needs to be updated but --locked was passed to prevent this
[00:02:44] failed to run: /checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo build --manifest-path /checkout/src/bootstrap/Cargo.toml --locked
[00:02:44] Makefile:81: recipe for target 'prepare' failed
[00:02:44] make: *** [prepare] Error 1
[00:02:44] The command has failed after 5 attempts.
travis_time:end:03b63a72:start=1536108445529160519,finish=1536108614347625929,duration=168818465410
---
travis_time:end:046da3fc:start=1536108614868535594,finish=1536108614876877306,duration=8341712
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:0a42fed6
$ 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 printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE"; gdb -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:01049de8
travis_time:start:01049de8
$ 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:046b2020
$ 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)

@mikeyhew
Copy link
Contributor Author

mikeyhew commented Sep 5, 2018

Does anyone know what's causing this Travis error?

@@ -135,6 +135,7 @@ pub trait Unsize<T: ?Sized> {
// Empty.
}


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this extra newline?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a holdover from when CoerceSized was there and should be removed

@bjorn3
Copy link
Member

bjorn3 commented Sep 5, 2018

Does anyone know what's causing this Travis error?

Compiler-builtins and clippy submodules are changed in this pr, so you have to update Cargo.lock.

@mikeyhew
Copy link
Contributor Author

mikeyhew commented Sep 5, 2018

Oh that's weird, I definitely didn't mean to update any submodules. I'll change them back. Thanks @bjorn3!

@bjorn3
Copy link
Member

bjorn3 commented Sep 5, 2018

@mikeyhew did you have submodules inited during rebase? They will keep their old checked out commit when checking out to a commit which updates a submodule to a different commit. I always run git submodule deinit -f --all before rebase, because of this.

@mikeyhew
Copy link
Contributor Author

mikeyhew commented Sep 5, 2018

@bjorn3 do you think that when I did git add . during rebase, I inadvertently updated the submodules?

@bjorn3
Copy link
Member

bjorn3 commented Sep 6, 2018

@mikeyhew yes. This has happened to me several times :)

let target_self_ty: Ty<'tcx> = self.mk_ty_param(
::std::u32::MAX,
Name::intern("RustaceansAreAwesome").as_interned_str(),
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, yes, I forgot about this =)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So — this is obviously a horrible hack — but is it one that users will ever notice? The code below just invokes predicate_must_hold, which won't itself generate an error, so perhaps not? The only way I could imagine would be through overflow maybe.

@nikomatsakis
Copy link
Contributor

(Note that we had planned — as part of the work on chalk — to make it possible to express the query in question cleanly; I'd be ok leaving this as a FIXME.)

@mikeyhew
Copy link
Contributor Author

mikeyhew commented Sep 6, 2018

Good point, then I will add a FIXME comment above that code

@aturon
Copy link
Member

aturon commented Sep 14, 2018

@mikeyhew @nikomatsakis ping on this -- I'm wondering if we have an ETA to get this over the finish line?

@mikeyhew
Copy link
Contributor Author

mikeyhew commented Sep 14, 2018

It's very close. @eddyb helped me with the codegen parts, so that's actually implemented now in a separate branch. We simplified it a bit — for now, we're only going to allow receivers whose ABI is the same as a pointer, which basically means it's limited to (newtypes of)* pointers, with the only extra fields being zero-sized like PhantomData. That covers all the cases we care about right now, including Rc<T> and compositional Pin (i.e. Pin<Box<T>, Pin<&mut T>).

What's left is adding checks in src/librustc_typeck/coherence/builtin.rs to enforce that. Once that's done, I'll open a new PR with everything, and it will just need to be reviewed.

EDIT: @aturon asked for an ETA. I'm thinking by Monday I'll have the new PR open... but we'll see 😄

@withoutboats
Copy link
Contributor

withoutboats commented Sep 14, 2018

@mikeyhew thanks for the update!

Our hope is that we can stabilize using (but not defining) arbitrary self type pointers in one of the next few release cycles. That will mean that any pointer that's can be used as a self pointer that's defined in std will work: that is, Rc, Arc, Pin, and compositions of other valid self pointers will all become valid self pointers. However, defining new ones will remain unstable while we work out the exact requirements around CoerceUnsized / CoerceSized / etc.

@mikeyhew
Copy link
Contributor Author

@withoutboats that plan sounds good. We'll have to figure out a way to disallow creation of receiver types on stable then, because right now they just have to implement Deref, and using a custom receiver type on a method is what requires a feature flag.

@nikomatsakis
Copy link
Contributor

@mikeyhew what do you mean by this?

and using a custom receiver type on a method is what requires a feature flag.

using how?

@mikeyhew
Copy link
Contributor Author

@nikomatsakis

This currently requires #![feature(arbitrary_self_types)], but according to what @withoutboats was saying, we should allow you to do it in stable Rust:

use std::rc::Rc;

trait Trait {
    fn foo(self: Rc<Self>);
}

However, we should still require #![feature(arbitrary_self_types)] to define your own type and use it as a receiver:

struct MyBox<T: ?Sized>(Box<T>);

impl<T: ?Sized> Deref for MyCustomPtr<T> {
    fn deref(&self) -> &T {
        &*self.0
    }
}

trait Trait {
    fn foo(self: MyBox<Self>);
}

In order to have the above distinction, we will need some way mark types like Rc and Pin<&mut T> as OK to use as method receivers without a feature flag.

@mikeyhew
Copy link
Contributor Author

We could use CoerceSized for this, but I'm not sure how it would work for structs. For trait methods, we would just have to check if the receiver is object safe, but for structs, Self is some arbitrary type, and not a type parameter, and the forall(U) { if (Self: Unsize<U>) { Receiver[Self -> U]: CoerceSized<Receiver> }} predicate doesn't make any sense.

Another option would be an attribute on the struct definition for Rc<T> and Pin<P>, but you have to be careful with that because, just because Pin<P> has the attribute, P might not.

I think the most robust way to do it would be to use a new, unstable trait with Deref as a supertrait:

trait Receiver: Deref {}

impl<T: ?Sized> Receiver for Rc<T> {}
impl<P: Receiver> Receiver for Pin<P> {}

Then for a type to be used as a receiver, it just needs to implement Receiver and transitively deref to Self.

I know it seems like a lot of traits, with Deref, CoerceSized and Receiver all being involved, but that way we can stop requiring Receiver at some point in the future... or change the requirements to something else entirely, which is fine because Receiver and CoerceUnsized are unstable.

@bors
Copy link
Contributor

bors commented Sep 19, 2018

☔ The latest upstream changes (presumably #53877) made this pull request unmergeable. Please resolve the merge conflicts.

@mikeyhew
Copy link
Contributor Author

Closing in favour of #54383

@mikeyhew mikeyhew closed this Sep 20, 2018
mikeyhew added a commit to mikeyhew/rust that referenced this pull request Nov 1, 2018
…candidates

I don't really understand what it's for, but see the comment here:
rust-lang#50173 (comment)

where arielb1 said

> Does this check do anything these days? I think `$0: Trait` is always considered ambiguous

and nikomatsakis agreed we may be able to get rid of it
bors added a commit that referenced this pull request Nov 3, 2018
…omatsakis

Take 2: Implement object-safety and dynamic dispatch for arbitrary_self_types

This replaces #50173. Over the months that that PR was open, we made a lot of changes to the way this was going to be implemented, and the long, meandering comment thread and commit history would have been confusing to people reading it in the future. So I decided to package everything up with new, straighforward commits and open a new PR.

Here are the main points. Please read the commit messages for details.

- To simplify codegen, we only support receivers that have the ABI of a pointer. That means they are builtin pointer types, or newtypes thereof.
- We introduce a new trait: `DispatchFromDyn<T>`, similar to `CoerceUnsized<T>`. `DispatchFromDyn` has extra requirements that `CoerceUnsized` does not: when you implement `DispatchFromDyn` for a struct, there cannot be any extra fields besides the field being coerced and `PhantomData` fields. This ensures that the struct's ABI is the same as a pointer.
- For a method's receiver (e.g. `self: Rc<Self>`) to be object-safe, it needs to have the following property:
    - let `DynReceiver` be the receiver when `Self = dyn Trait`
    - let `ConcreteReceiver` be the receiver when `Self = T`, where `T` is some unknown `Sized` type that implements `Trait`, and is the erased type of the trait object.
    - `ConcreteReceiver` must implement `DispatchFromDyn<DynReceiver>`

In the case of `Rc<Self>`, this requires `Rc<T>: DispatchFromDyn<Rc<dyn Trait>>`

These rules are explained more thoroughly in the doc comment on `receiver_is_dispatchable` in object_safety.rs.

r? @nikomatsakis and @eddyb

cc @arielb1 @cramertj @withoutboats

Special thanks to @nikomatsakis for getting me un-stuck when implementing the object-safety checks, and @eddyb for helping with the codegen parts.

EDIT 2018-11-01: updated because CoerceSized has been replaced with DispatchFromDyn
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.