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

The implementation From<&'a [T; N]> for Cow<'a, [T]> seems missing #116890

Closed
oisyn opened this issue Oct 18, 2023 · 4 comments
Closed

The implementation From<&'a [T; N]> for Cow<'a, [T]> seems missing #116890

oisyn opened this issue Oct 18, 2023 · 4 comments
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@oisyn
Copy link

oisyn commented Oct 18, 2023

This fails to compile

use std::borrow::Cow;

fn foo<'a>(v: impl Into<Cow<'a, [i32]>>) { }

fn main() {
    foo(&[1, 2, 3]);
}

Rust playground link

With the following diagnostics:

   Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `Cow<'_, [i32]>: From<&[{integer}; 3]>` is not satisfied
 --> src/main.rs:8:9
  |
8 |     foo(&[1, 2, 3]);
  |     --- ^^^^^^^^^^ the trait `From<&[{integer}; 3]>` is not implemented for `Cow<'_, [i32]>`
  |     |
  |     required by a bound introduced by this call
  |
  = help: the following other types implement trait `From<T>`:
            <Cow<'a, OsStr> as From<OsString>>
            <Cow<'a, OsStr> as From<&'a OsStr>>
            <Cow<'a, OsStr> as From<&'a OsString>>
            <Cow<'a, CStr> as From<CString>>
            <Cow<'a, CStr> as From<&'a CStr>>
            <Cow<'a, CStr> as From<&'a CString>>
            <Cow<'a, Path> as From<&'a Path>>
            <Cow<'a, Path> as From<PathBuf>>
          and 7 others
  = note: required for `&[{integer}; 3]` to implement `Into<Cow<'_, [i32]>>`
note: required by a bound in `foo`
 --> src/main.rs:5:20
  |
5 | fn foo<'a>(v: impl Into<Cow<'a, [i32]>>) { }
  |                    ^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`

For more information about this error, try `rustc --explain E0277`.

It seems that From<&'a [T; N]> is not implemented for Cow<'a [T]>, while From<&'a [T]> is. Has this been an oversight, or is there a rationale behind this?

Providing my own implementation does seem to work

impl<'a, T: Clone, const N: usize> From<&'a [T; N]> for Cow<'a, [T]> {
    fn from(s: &'a [T; N]) -> Cow<'a, [T]> {
        Cow::Borrowed(s)
    }
}
@oisyn oisyn added the C-bug Category: This is a bug. label Oct 18, 2023
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Oct 18, 2023
@demosdemon
Copy link

The two are not compatible as &[T; N] is not the same as &[T]. The former is a reference to an array which has a fixed size and thus the size and alignment of the reference is for a single usize (the pointer). The latter is reference to a slice which is an unsized type meaning the size and alignment of the reference is for 2 usizes; one for the pointer and one for the count of elements within the slice.

Converting &[T; N] to Cow<'_, [T]> is an unsizing type conversion. Your implementation for From first implicitly converts the &[T; N] into a &[T] which creates a new reference and then wraps that with the Cow enum.

The difference is important when it comes to ToOwned. The impl for ToOwned is different for &[T; N] and &[T]. The former is delegated to Clone which will create a [T; N] and the latter will create a new Vec<T> with all of the differences of an array versus a vector.

@zachs18
Copy link
Contributor

zachs18 commented Nov 5, 2023

An impl<'a, T: Clone, const N: usize> From<&'a [T; N]> for Cow<'a, [T]> could be added, but has not been proposed (yet) as far as I know (see linked PR).

There also does not currently exist an impl<'a, T: Clone> From<&'a T> for Cow<'a, T>, which is good because that means that Cow::from(array_ref) would unambiguously resolve to Cow::<[T]>::from(array_ref), and not resolve to Cow::<[T; N]>::from(array_ref) or cause an inference error.


As a workaround for the code snippet in the OP, you can use [..] after the array to slice it (and then the & on the front borrows that), e.g. (playground link)

use std::borrow::Cow;

fn foo<'a>(v: impl Into<Cow<'a, [i32]>>) { }

fn main() {
    foo(&[1, 2, 3][..]);
}

@saethlin saethlin added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. C-feature-request Category: A feature request, i.e: not implemented / a PR. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. C-bug Category: This is a bug. labels Nov 18, 2023
@minghuaw
Copy link

Should this issue be closed given that #113489 is already merged?

@oisyn
Copy link
Author

oisyn commented May 27, 2024

Yes, thank you.

@oisyn oisyn closed this as completed May 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants