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

Missing AsMut<[T;N]> for [T;N] #129849

Open
alexkazik opened this issue Sep 1, 2024 · 3 comments · May be fixed by #129872
Open

Missing AsMut<[T;N]> for [T;N] #129849

alexkazik opened this issue Sep 1, 2024 · 3 comments · May be fixed by #129872
Assignees
Labels
T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@alexkazik
Copy link

alexkazik commented Sep 1, 2024

I tried this code:

fn foo<T: AsMut<[u8; 12]>>(mut t: T) {
    t.as_mut()[0] = 0;
}
fn bar(x: &mut [u8; 12]) {
    foo(x);
}

I expected it to compile.

Instead, this happened:

error[E0277]: the trait bound `[u8; 12]: AsMut<[u8; 12]>` is not satisfied
 --> crate/src/it.rs:5:9
  |
5 |     foo(x);
  |     --- ^ the trait `AsMut<[u8; 12]>` is not implemented for `[u8; 12]`, which is required by `&mut [u8; 12]: AsMut<[u8; 12]>`
  |     |
  |     required by a bound introduced by this call
  |
  = help: the following other types implement trait `AsMut<T>`:
            [T; N]
            [T]
  = note: required for `&mut [u8; 12]` to implement `AsMut<[u8; 12]>`
note: required by a bound in `foo`
 --> crate/src/it.rs:1:11
  |
1 | fn foo<T: AsMut<[u8; 12]>>(mut t: T) {
  |           ^^^^^^^^^^^^^^^ required by this bound in `foo`
@alexkazik alexkazik added the C-bug Category: This is a bug. label Sep 1, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Sep 1, 2024
@GrigorenkoPV
Copy link
Contributor

I expected there to be a blanket impl, but

Ideally, AsMut would be reflexive, i.e. there would be an impl<T: ?Sized> AsMut<T> for T with as_mut simply returning its argument unchanged. Such a blanket implementation is currently not provided due to technical restrictions of Rust’s type system (it would be overlapping with another existing blanket implementation for &mut T where T: AsMut<U> which allows AsMut to auto-dereference, see “Generic Implementations” above).

A trivial implementation of AsMut<T> for T must be added explicitly for a particular type T where needed or desired. Note, however, that not all types from std contain such an implementation, and those cannot be added by external code due to orphan rules.

https://doc.rust-lang.org/stable/core/convert/trait.AsMut.html#reflexivity

Sad.

Anyways, you can try to submit a PR if you want, or, alternatively:

Note, however, that APIs don’t need to be generic. In many cases taking a &mut [u8] or &mut Vec, for example, is the better choice (callers need to pass the correct type then).

But I think I'll try to submit a PR anyways, unless you want to do it yourself.

@alexkazik
Copy link
Author

Since I haven't done a PR (or even compiled the compiler) I'd appreciate you submitting the PR - but I can give it a try.

I use a generic slice since it's used as a buffer of exactly that size.
And I tried AsMut as as abstraction so that the pure reference (on no alloc systems) or Box::<[u8; N]>::try_from(vec![0u8; N]).unwrap() for alloc/testing can be used.

@GrigorenkoPV
Copy link
Contributor

Oh wow, this is worse than I thought. Many places (even in compiler itself) use .as_ref() as a substitute for .as_slice(), because array.as_ref() currently gets desugared to effectively { let tmp: &[_] = array.deref(); tmp.as_ref() }. This is more or less the same situation as with https://doc.rust-lang.org/edition-guide/rust-2021/IntoIterator-for-arrays.html, so I think I can try to push this through in time for the 2024 edition.

@rustbot claim

@GrigorenkoPV GrigorenkoPV linked a pull request Sep 2, 2024 that will close this issue
6 tasks
@saethlin saethlin added T-libs Relevant to the library team, which will review and decide on the PR/issue. and removed C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Sep 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants