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

Add implementations for converting boxed slices into boxed arrays #61515

Merged
merged 1 commit into from
Aug 6, 2019

Conversation

shepmaster
Copy link
Member

@shepmaster shepmaster commented Jun 4, 2019

This mirrors the implementations of reference slices into arrays.

Discussion

Remaining

  • Implement Error
  • Create a tracking issue

@shepmaster shepmaster added C-enhancement Category: An issue proposing an enhancement or a PR with one. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Jun 4, 2019
@rust-highfive
Copy link
Collaborator

r? @cramertj

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

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 4, 2019
@shepmaster
Copy link
Member Author

/cc @varkor due to #61415

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-6.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:00a57890:start=1559650962019955280,finish=1559651049498696116,duration=87478740836
$ 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
$ export GCP_CACHE_BUCKET=rust-lang-ci-cache
$ export AWS_ACCESS_KEY_ID=AKIA46X5W6CZEJZ6XT55
---

[00:04:02] travis_fold:start:tidy
travis_time:start:tidy
tidy check
[00:04:02] tidy error: /checkout/src/liballoc/boxed.rs:604: TODO is deprecated; use FIXME
[00:04:07] some tidy checks failed
[00:04:07] 
[00:04:07] 
[00:04:07] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/tidy" "/checkout/src" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "--no-vendor" "--quiet"
[00:04:07] 
[00:04:07] 
[00:04:07] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test src/tools/tidy
[00:04:07] Build completed unsuccessfully in 0:01:11
---
travis_time:end:022cb2b8:start=1559651305935227206,finish=1559651305939954745,duration=4727539
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:160d5350
$ 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 --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:1f09eee0
travis_time:start:1f09eee0
$ 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:01410a50
$ 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)

src/liballoc/boxed.rs Outdated Show resolved Hide resolved
use core::convert::TryFrom;

#[derive(Debug, Copy, Clone)]
#[unstable(feature = "boxed_slice_try_from", issue = "0")]
Copy link
Member Author

Choose a reason for hiding this comment

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

Needs an issue (if deemed acceptable)

Copy link
Member

Choose a reason for hiding this comment

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

Here and below: trait implementations are insta-stable.

@varkor
Copy link
Member

varkor commented Jun 4, 2019

Are you not able to parameterise over all array lengths? This doesn't requite const generics as it currently stands.

@shepmaster
Copy link
Member Author

Are you not able to parameterise over all array lengths? This doesn't requite const generics as it currently stands.

I'm not following your meaning. This PR adds one more case of using macros to explicitly enumerate certain sizes. If this were to be merged before #61415, I assume that you'd want to update that PR to include this new code. If that PR is merged first, I should update this to follow suit.

It didn't make sense to jump right to const generics in this PR until the decisions were made in the other PRs.

I also wanted to prevent me adding anything complicated like the Default bounds issue for zero-length arrays.

Copy link
Contributor

@Centril Centril left a comment

Choose a reason for hiding this comment

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

Neat. I think you should be able to replicate this for Rc and Arc as well.

src/liballoc/boxed.rs Outdated Show resolved Hide resolved

fn try_from(boxed_slice: Box<[T]>) -> Result<Box<[T; $N]>, Self::Error> {
if boxed_slice.len() == $N {
unsafe { Ok(Box::from_raw(Box::into_raw(boxed_slice) as *mut [T; $N])) }
Copy link
Contributor

Choose a reason for hiding this comment

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

A comment re. safety would be nice.

Copy link
Member Author

Choose a reason for hiding this comment

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

I wanted to copy the rationale from slices, but it didn't have one; neither does the unsafe block immediately before this implementation in the file.

Is it valid to say

This is safe for the same reasons and under the same conditions that converting a slice to an array is safe

?

Copy link
Contributor

Choose a reason for hiding this comment

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

I would elaborate more from the POV of the unsafe operations you are using and how you have verified the proofs they need. Also, Ok(unsafe { seems preferable since the Ok bit doesn't partake in the unsafety.

@varkor
Copy link
Member

varkor commented Jun 4, 2019

It didn't make sense to jump right to const generics in this PR until the decisions were made in the other PRs.

If we were adding a new, unstable method, it might make sense to use const generics, because there aren't concerns with breaking stable code. But these are insta-stable (#55436), so that's probably not advisable.

#[unstable(feature = "boxed_slice_try_from", issue = "0")]
/// Can we use TryFromSliceError instead?
/// TODO: implement Error
pub struct PlaceholderError(());
Copy link
Member Author

Choose a reason for hiding this comment

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

We may want to create a custom error in order to recover the original allocation in case of failure.

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-6.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:0edf11ba:start=1559660039446708615,finish=1559660223151861699,duration=183705153084
$ 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
$ export GCP_CACHE_BUCKET=rust-lang-ci-cache
$ export AWS_ACCESS_KEY_ID=AKIA46X5W6CZEJZ6XT55
---
travis_time:start:test_codegen
Check compiletest suite=codegen mode=codegen (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[01:01:49] 
[01:01:49] running 144 tests
[01:01:51] i..iii.....iii..i.iii....i......................i..i.................i.....i..........ii.i..i..i.ii. 100/144
[01:01:53] test result: ok. 114 passed; 0 failed; 30 ignored; 0 measured; 0 filtered out
[01:01:53] 
[01:01:53]  finished in 4.322
[01:01:53] travis_fold:end:test_codegen
---
travis_time:start:test_assembly
Check compiletest suite=assembly mode=assembly (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[01:01:55] 
[01:01:55] running 9 tests
[01:01:55] iiiiiiiii
[01:01:55] 
[01:01:55]  finished in 0.145
[01:01:55] travis_fold:end:test_assembly

---
travis_time:start:test_debuginfo
Check compiletest suite=debuginfo mode=debuginfo-gdb+lldb (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[01:02:10] 
[01:02:10] running 122 tests
[01:02:33] .iiiii...i.....i..i...i..i.i.i..i.ii..i.i.....i..i....i..........iiii..........i...ii...i.......ii.i 100/122
[01:02:38] .i.i......iii.i.....ii
[01:02:38] 
[01:02:38]  finished in 28.008
[01:02:38] travis_fold:end:test_debuginfo

---
[01:14:14]    Compiling alloc v0.0.0 (/checkout/src/liballoc)
[01:14:16] error[E0412]: cannot find type `PlaceholderError` in module `crate::boxed`
[01:14:16]     --> src/liballoc/sync.rs:1793:44
[01:14:16]      |
[01:14:16] 1788 | / macro_rules! array_impls {
[01:14:16] 1789 | |     ($($N:expr)+) => {
[01:14:16] 1790 | |         $(
[01:14:16] 1791 | |             #[unstable(feature = "boxed_slice_try_from", issue = "0")]
[01:14:16] 1792 | |             impl<T> TryFrom<Arc<[T]>> for Arc<[T; $N]> {
[01:14:16] 1793 | |                 type Error = crate::boxed::PlaceholderError;
[01:14:16]      | |                                            ^^^^^^^^^^^^^^^^ not found in `crate::boxed`
[01:14:16] 1804 | |     }
[01:14:16] 1805 | | }
[01:14:16]      | |_- in this expansion of `array_impls!`
[01:14:16] 1806 | 
[01:14:16] 1806 | 
[01:14:16] 1807 | / array_impls! {
[01:14:16] 1809 | |     10 11 12 13 14 15 16 17 18 19
[01:14:16] 1810 | |     20 21 22 23 24 25 26 27 28 29
[01:14:16] 1811 | |     30 31 32
[01:14:16] 1812 | | }
---
[01:14:16] 
[01:14:16] error[E0425]: cannot find function `PlaceholderError` in module `crate::boxed`
[01:14:16]     --> src/liballoc/sync.rs:1799:43
[01:14:16]      |
[01:14:16] 1788 | / macro_rules! array_impls {
[01:14:16] 1789 | |     ($($N:expr)+) => {
[01:14:16] 1790 | |         $(
[01:14:16] 1791 | |             #[unstable(feature = "boxed_slice_try_from", issue = "0")]
[01:14:16] ...    |
[01:14:16] 1799 | |                         Err(crate::boxed::PlaceholderError(()))
[01:14:16]      | |                                           ^^^^^^^^^^^^^^^^ not found in `crate::boxed`
[01:14:16] 1804 | |     }
[01:14:16] 1805 | | }
[01:14:16]      | |_- in this expansion of `array_impls!`
[01:14:16] 1806 | 
[01:14:16] 1806 | 
[01:14:16] 1807 | / array_impls! {
[01:14:16] 1809 | |     10 11 12 13 14 15 16 17 18 19
[01:14:16] 1810 | |     20 21 22 23 24 25 26 27 28 29
[01:14:16] 1811 | |     30 31 32
[01:14:16] 1812 | | }
[01:14:16] 1812 | | }
[01:14:16]      | |_- in this macro invocation
[01:14:16] 
[01:14:16] error[E0412]: cannot find type `PlaceholderError` in module `crate::boxed`
[01:14:16]     --> src/liballoc/rc.rs:1221:44
[01:14:16]      |
[01:14:16] 1216 | / macro_rules! array_impls {
[01:14:16] 1217 | |     ($($N:expr)+) => {
[01:14:16] 1218 | |         $(
[01:14:16] 1219 | |             #[unstable(feature = "boxed_slice_try_from", issue = "0")]
[01:14:16] 1220 | |             impl<T> TryFrom<Rc<[T]>> for Rc<[T; $N]> {
[01:14:16] 1221 | |                 type Error = crate::boxed::PlaceholderError;
[01:14:16]      | |                                            ^^^^^^^^^^^^^^^^ not found in `crate::boxed`
[01:14:16] 1232 | |     }
[01:14:16] 1233 | | }
[01:14:16]      | |_- in this expansion of `array_impls!`
[01:14:16] 1234 | 
[01:14:16] 1234 | 
[01:14:16] 1235 | / array_impls! {
[01:14:16] 1237 | |     10 11 12 13 14 15 16 17 18 19
[01:14:16] 1238 | |     20 21 22 23 24 25 26 27 28 29
[01:14:16] 1239 | |     30 31 32
[01:14:16] 1240 | | }
---
[01:14:16] 
[01:14:16] error[E0425]: cannot find function `PlaceholderError` in module `crate::boxed`
[01:14:16]     --> src/liballoc/rc.rs:1227:43
[01:14:16]      |
[01:14:16] 1216 | / macro_rules! array_impls {
[01:14:16] 1217 | |     ($($N:expr)+) => {
[01:14:16] 1218 | |         $(
[01:14:16] 1219 | |             #[unstable(feature = "boxed_slice_try_from", issue = "0")]
[01:14:16] ...    |
[01:14:16] 1227 | |                         Err(crate::boxed::PlaceholderError(()))
[01:14:16]      | |                                           ^^^^^^^^^^^^^^^^ not found in `crate::boxed`
[01:14:16] 1232 | |     }
[01:14:16] 1233 | | }
[01:14:16]      | |_- in this expansion of `array_impls!`
[01:14:16] 1234 | 
[01:14:16] 1234 | 
[01:14:16] 1235 | / array_impls! {
[01:14:16] 1237 | |     10 11 12 13 14 15 16 17 18 19
[01:14:16] 1238 | |     20 21 22 23 24 25 26 27 28 29
[01:14:16] 1239 | |     30 31 32
[01:14:16] 1240 | | }
[01:14:16] 1240 | | }
[01:14:16]      | |_- in this macro invocation
[01:14:16] 
[01:14:18] error[E0308]: mismatched types
[01:14:18]    --> src/liballoc/boxed_test.rs:145:25
[01:14:18]     |
[01:14:18] 145 |     let r: Box<[u32]> = Box::from(v);
[01:14:18]     |                         ^^^^^^^^^^^^ expected slice, found struct `vec::Vec`
[01:14:18]     = note: expected type `std::boxed::Box<[u32]>`
[01:14:18]     = note: expected type `std::boxed::Box<[u32]>`
[01:14:18]                found type `std::boxed::Box<vec::Vec<{integer}>>`
[01:14:18] 
[01:14:18] error[E0599]: no method named `try_into` found for type `std::boxed::Box<[u32]>` in the current scope
[01:14:18]     |
[01:14:18]     |
[01:14:18] 147 |     let a: Result<Box<[u32; 3]>, _> = r.clone().try_into();
[01:14:18]     |
[01:14:18]     = help: items from traits can only be used if the trait is in scope
[01:14:18]     = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
[01:14:18]             `use core::convert::TryInto;`
[01:14:18]             `use core::convert::TryInto;`
[01:14:18] 
[01:14:18] error[E0599]: no method named `try_into` found for type `std::boxed::Box<[u32]>` in the current scope
[01:14:18]     |
[01:14:18]     |
[01:14:18] 150 |     let a: Result<Box<[u32; 2]>, _> = r.clone().try_into();
[01:14:18]     |
[01:14:18]     = help: items from traits can only be used if the trait is in scope
[01:14:18]     = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
[01:14:18]             `use core::convert::TryInto;`
[01:14:18]             `use core::convert::TryInto;`
[01:14:18] 
[01:14:19] error[E0599]: no method named `try_into` found for type `sync::Arc<[u32]>` in the current scope
[01:14:19]      |
[01:14:19]      |
[01:14:19] 193  | pub struct Arc<T: ?Sized> {
[01:14:19]      | ------------------------- method `try_into` not found for this
[01:14:19] ...
[01:14:19] 2301 |         let a: Result<Arc<[u32; 3]>, _> = r.clone().try_into();
[01:14:19]      |
[01:14:19]      = help: items from traits can only be used if the trait is in scope
[01:14:19]      = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
[01:14:19]              `use core::convert::TryInto;`
[01:14:19]              `use core::convert::TryInto;`
[01:14:19] 
[01:14:19] error[E0599]: no method named `try_into` found for type `sync::Arc<[u32]>` in the current scope
[01:14:19]      |
[01:14:19]      |
[01:14:19] 193  | pub struct Arc<T: ?Sized> {
[01:14:19]      | ------------------------- method `try_into` not found for this
[01:14:19] ...
[01:14:19] 2304 |         let a: Result<Arc<[u32; 2]>, _> = r.clone().try_into();
[01:14:19]      |
[01:14:19]      = help: items from traits can only be used if the trait is in scope
[01:14:19]      = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
[01:14:19]              `use core::convert::TryInto;`
[01:14:19]              `use core::convert::TryInto;`
[01:14:19] 
[01:14:19] error[E0599]: no method named `try_into` found for type `rc::Rc<[u32]>` in the current scope
[01:14:19]      |
[01:14:19]      |
[01:14:19] 273  | pub struct Rc<T: ?Sized> {
[01:14:19]      | ------------------------ method `try_into` not found for this
[01:14:19] ...
[01:14:19] 2177 |         let a: Result<Rc<[u32; 3]>, _> = r.clone().try_into();
[01:14:19]      |
[01:14:19]      = help: items from traits can only be used if the trait is in scope
[01:14:19]      = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
[01:14:19]              `use core::convert::TryInto;`
[01:14:19]              `use core::convert::TryInto;`
[01:14:19] 
[01:14:19] error[E0599]: no method named `try_into` found for type `rc::Rc<[u32]>` in the current scope
[01:14:19]      |
[01:14:19]      |
[01:14:19] 273  | pub struct Rc<T: ?Sized> {
[01:14:19]      | ------------------------ method `try_into` not found for this
[01:14:19] ...
[01:14:19] 2180 |         let a: Result<Rc<[u32; 2]>, _> = r.clone().try_into();
[01:14:19]      |
[01:14:19]      = help: items from traits can only be used if the trait is in scope
[01:14:19]      = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
[01:14:19]              `use core::convert::TryInto;`
---
[01:14:20] warning: build failed, waiting for other jobs to finish...
[01:15:28] error: build failed
[01:15:28] 
[01:15:28] 
[01:15:28] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "test" "--target" "x86_64-unknown-linux-gnu" "-j" "4" "--release" "--locked" "--color" "always" "--features" "panic-unwind backtrace compiler-builtins-c" "--manifest-path" "/checkout/src/libstd/Cargo.toml" "-p" "alloc" "--" "--quiet"
[01:15:28] 
[01:15:28] 
[01:15:28] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[01:15:28] Build completed unsuccessfully in 1:11:21
---
travis_time:end:3229e7e9:start=1559664762612361139,finish=1559664762618162945,duration=5801806
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:2d1884a0
$ 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 --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

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)

@bors
Copy link
Contributor

bors commented Jun 16, 2019

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

@Dylan-DPC-zz
Copy link

ping from triage @cramertj waiting for your review on this

@cramertj
Copy link
Member

cramertj commented Jul 8, 2019

It seems like there are a number of unresolved questions still remaining above, and some unchecked checkboxes in the initial post.

Also, now that #62435 has landed, we probably follow that pattern here as well rather than generating all the impls using a macro.

@shepmaster
Copy link
Member Author

a number of unresolved questions

Yes, but I didn’t wish to waste effort polishing a PR that a reviewer would reject; I was hoping for a “yes, this makes sense” or “no, let’s not do this”.

some unchecked checkboxes in the initial post.

Yes, which I was hoping a reviewer would lend feedback on.

@cramertj
Copy link
Member

cramertj commented Jul 8, 2019

Yes, but I didn’t wish to waste effort polishing a PR that a reviewer would reject; I was hoping for a “yes, this makes sense” or “no, let’s not do this”.

Yes, I think it makes sense to have TryFrom impls between Box<[T]> and Box<[T; N]>, but that's really up to @rust-lang/libs.

@alexcrichton
Copy link
Member

Thanks @shepmaster! I would personally agree that we should have these sorts of conversions. We already have &[T] => &[T; N] conversions and so it feels natural to extend that to other pointer types as well.

I'm not really sure what the discussion for the safety rationale is (these seem trivially safe) but in terms of the return type I could personally go either way. It'd be a lot simpler to define and grok if the base value wasn't returned through the error type, but that means failed Box conversions are simply off into the ether. On the other hand though you can always actually check the length yourself ahead of time so it may not be the end of the world.

Unfortunately I think though these are insta-stable impls so we need to figure this out now, so I'd be curious to hear what others think. I'd slightly lean towards leaving out the original value in the error type.

@bjorn3
Copy link
Member

bjorn3 commented Jul 9, 2019

I'd slightly lean towards leaving out the original value in the error type.

That is inconsistent with Box< dyn Any>::downcast. It will also cause code like:

if a.len() == 2 {
    do_work_on_two_array(*a.try_into().unwrap());
}

fn do_work_on_two_array<T>(_: [T; 2]){}

Notice the unwrap.

@shepmaster
Copy link
Member Author

I'd slightly lean towards leaving out the original value in the error type.

It will also cause code like […] Notice the unwrap.

@bjorn3 I don’t understand why the decision to return the original value or not would affect the unwrap. TryFrom will always return a Result, so you’d always have to handle the failure. What am I missing?

I see that I left some comments about using TryFromSliceError, but I don’t think that’s actually possible now since this code is in liballoc and TryFromSliceError is in libcore and has no public constructors. We could add a public constructor, but I’m guessing we wouldn’t want to.

That means I’m really asking about these two versions:

  1. struct SomeError(());
  2. struct SomeError<T>(Box<T>);
    
    impl SomeError {
        fn into_original(self) -> Box<T> { /* … */ }
    }

The latter could be generalized for Arc<T> / Rc<T> as well, but as @alexcrichton mentions, you could always just .clone() them first. It might be nicer to have a unified error across the three, instead of one for Box and one for Rc and Arc.

@SimonSapin
Copy link
Contributor

SimonSapin commented Jul 9, 2019

  • If the original box is not part of the error type, a user who does want to keep it around when the conversion fails (for example if they’re trying a few different sizes successively) would have to check len() themselves and then call unwrap() on the conversion result.

  • There is precedent in Box<dyn Any>::downcast of not introducing a new error type, but having the original box directly in Result::Err. In this case like in downcast, the conversion is trivial enough IMO that there is no other useful information that we could include in the error type, so keeping it extensible doesn’t seem useful to me.

  • An earlier comment said this should probably not use const generics, but Use const generics for array impls [part 1] #62435 has landed in the meantime.

All in all, I would be in favor of:

impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]>
    where
        [T; N]: LengthAtMost32,
{
    type Error = Box<[T]>;
    // …
}

@shepmaster
Copy link
Member Author

shepmaster commented Jul 9, 2019

Ah, I hadn't thought about returning the Box / Arc / Rc directly because I'm so used to the maxim that the value in Result::Err should implement std::error::Error. This means that tools like SNAFU cannot easily work with these types of errors.

I've updated the PR to use const generics, as the referenced const generic PRs have been merged since this was opened.

@Centril
Copy link
Contributor

Centril commented Jul 9, 2019

I've updated the PR to use const generics, as the referenced const generic PRs have been merged since this was opened.

Please extend the UI tests Scott added to check that implementations for size e.g. 33 and some placeholder const N: usize do not work.

@totsteps
Copy link
Member

ping from triage @shepmaster any updates on this?

@shepmaster
Copy link
Member Author

Changes:

  • returning the original type (Box<[T]> / Rc<[T]> / Arc<[T]>) on error
  • flipped Ok and unsafe
  • Added UI tests to ensure that [T; 33] does not work.

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-6.0 of your PR failed (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.
2019-07-24T02:22:55.9522959Z ##[command]git remote add origin https://github.com/rust-lang/rust
2019-07-24T02:22:55.9720805Z ##[command]git config gc.auto 0
2019-07-24T02:22:55.9789290Z ##[command]git config --get-all http.https://github.com/rust-lang/rust.extraheader
2019-07-24T02:22:55.9870737Z ##[command]git config --get-all http.proxy
2019-07-24T02:22:56.8546333Z ##[command]git -c http.extraheader="AUTHORIZATION: basic ***" fetch --force --tags --prune --progress --no-recurse-submodules --depth=2 origin +refs/heads/*:refs/remotes/origin/* +refs/pull/61515/merge:refs/remotes/pull/61515/merge
---
2019-07-24T02:23:31.9521439Z do so (now or later) by using -b with the checkout command again. Example:
2019-07-24T02:23:31.9521625Z 
2019-07-24T02:23:31.9521990Z   git checkout -b <new-branch-name>
2019-07-24T02:23:31.9522142Z 
2019-07-24T02:23:31.9522292Z HEAD is now at d55d48ffe Merge f0cb1ca8211aec933582dc470b52f95f3402a8b1 into a7f28678bbf4e16893bb6a718e427504167a9494
2019-07-24T02:23:31.9678243Z ##[section]Starting: Collect CPU-usage statistics in the background
2019-07-24T02:23:31.9681510Z ==============================================================================
2019-07-24T02:23:31.9681572Z Task         : Bash
2019-07-24T02:23:31.9681651Z Description  : Run a Bash script on macOS, Linux, or Windows
---
2019-07-24T02:29:53.0535462Z    Compiling serde_json v1.0.40
2019-07-24T02:29:57.5090136Z    Compiling tidy v0.1.0 (/checkout/src/tools/tidy)
2019-07-24T02:30:06.3564490Z     Finished release [optimized] target(s) in 1m 31s
2019-07-24T02:30:06.3622621Z tidy check
2019-07-24T02:30:06.9189478Z tidy error: /checkout/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs:6: line longer than 100 chars
2019-07-24T02:30:06.9189941Z tidy error: /checkout/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs:7: line longer than 100 chars
2019-07-24T02:30:06.9190248Z tidy error: /checkout/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs:13: line longer than 100 chars
2019-07-24T02:30:06.9190565Z tidy error: /checkout/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs:14: line longer than 100 chars
2019-07-24T02:30:06.9191130Z tidy error: /checkout/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs:20: line longer than 100 chars
2019-07-24T02:30:06.9191484Z tidy error: /checkout/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs:21: line longer than 100 chars
2019-07-24T02:30:08.3762048Z some tidy checks failed
2019-07-24T02:30:08.3771791Z 
2019-07-24T02:30:08.3771791Z 
2019-07-24T02:30:08.3772734Z command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/tidy" "/checkout/src" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "--no-vendor"
2019-07-24T02:30:08.3772874Z 
2019-07-24T02:30:08.3772902Z 
2019-07-24T02:30:08.3779995Z failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test src/tools/tidy
2019-07-24T02:30:08.3780065Z Build completed unsuccessfully in 0:01:35
2019-07-24T02:30:08.3780065Z Build completed unsuccessfully in 0:01:35
2019-07-24T02:30:09.7309125Z ##[error]Bash exited with code '1'.
2019-07-24T02:30:09.7341542Z ##[section]Starting: Checkout
2019-07-24T02:30:09.7343228Z ==============================================================================
2019-07-24T02:30:09.7343303Z Task         : Get sources
2019-07-24T02:30:09.7343351Z Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.

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)

@bors
Copy link
Contributor

bors commented Aug 2, 2019

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

This mirrors the implementations of reference slices into arrays.
@shepmaster
Copy link
Member Author

Conflicts fixed.

@cramertj
Copy link
Member

cramertj commented Aug 5, 2019

@bors r+

I think this is good to go based on the comments above and my own review. Anyone from @rust-lang/libs feel free to r- if you see opportunities for improvement.

@bors
Copy link
Contributor

bors commented Aug 5, 2019

📌 Commit 32324d2 has been approved by cramertj

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 5, 2019
@bors
Copy link
Contributor

bors commented Aug 5, 2019

⌛ Testing commit 32324d2 with merge 09a245b...

bors added a commit that referenced this pull request Aug 5, 2019
Add implementations for converting boxed slices into boxed arrays

This mirrors the implementations of reference slices into arrays.

# Discussion

- [x] Should we use const generics? ([probably not](#61515 (comment)))
- [ ] [What's the safety rationale here](#61515 (comment))?
- [ ] [Should the errors return the original object](#61515 (comment))?

# Remaining

- [ ] Implement `Error`
- [ ] Create a tracking issue
@Centril
Copy link
Contributor

Centril commented Aug 5, 2019

#61515 (comment) is still not resolved

@bors r-

@bors bors 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-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Aug 5, 2019
@Centril
Copy link
Contributor

Centril commented Aug 5, 2019

@bors retry

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 5, 2019
@alexcrichton
Copy link
Member

@bors: r=cramertj

@Centril please don't r- for not religiously documenting all unsafe blocks. That's not a showstopper reason for this PR and it is not libs team policy (nor do I even personally agree) that all unsafe blocks require documentation in the standard library. If you'd like to make this a blocking policy here's not the place to do so, I'd recommend discussion threads elsewhere.

@bors
Copy link
Contributor

bors commented Aug 6, 2019

📌 Commit 32324d2 has been approved by cramertj

@bors
Copy link
Contributor

bors commented Aug 6, 2019

⌛ Testing commit 32324d2 with merge 6a91782...

bors added a commit that referenced this pull request Aug 6, 2019
Add implementations for converting boxed slices into boxed arrays

This mirrors the implementations of reference slices into arrays.

# Discussion

- [x] Should we use const generics? ([probably not](#61515 (comment)))
- [ ] [What's the safety rationale here](#61515 (comment))?
- [ ] [Should the errors return the original object](#61515 (comment))?

# Remaining

- [ ] Implement `Error`
- [ ] Create a tracking issue
@bors
Copy link
Contributor

bors commented Aug 6, 2019

☀️ Test successful - checks-azure
Approved by: cramertj
Pushing 6a91782 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Aug 6, 2019
@bors bors merged commit 32324d2 into rust-lang:master Aug 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one. merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.