Skip to content

Type inference breakage in 0.7.5 on ArrayString::as_ref #276

@jannic

Description

@jannic

This code compiles with arrayvec 0.7.4:

use arrayvec::ArrayString;

fn main() {
    let array_string = ArrayString::<32>::new();
    let as_ref = array_string.as_ref();
    let _bytes = as_ref.as_bytes();
}

However, with arrayvec 0.7.5 and 0.7.6, I get the following error:

error[E0282]: type annotations needed for `&_`
 --> src/main.rs:5:9
  |
5 |     let as_ref = array_string.as_ref();
  |         ^^^^^^
6 |     let _bytes = as_ref.as_bytes();
  |                         -------- type must be known at this point
  |
help: consider giving `as_ref` an explicit type, where the type for type parameter `T` is specified
  |
5 |     let as_ref: &T = array_string.as_ref();
  |               ++++

This is because there are now two AsRef impls, namely:

impl<const CAP: usize> AsRef<str> for ArrayString<CAP>
{
    fn as_ref(&self) -> &str { self }
}

impl<const CAP: usize> AsRef<Path> for ArrayString<CAP> {
    fn as_ref(&self) -> &Path {
        self.as_str().as_ref()
    }
}

Before, only the first existed, so the compiler could infer that as_ref must be a &str.
But with the second implementation, it became ambiguous, and now the compiler needs a type annotation.

I'm not sure how to best handle this:

  • reverting the change would hurt users of the new implementation
  • yanking 0.7.5 and 0.7.6 and releasing it as 0.8.0 also feels like a big hassle for this small change

As the fix for affected users is quite simple (add a type annotation), it may be best to just document this change?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions